{{~namespace_with_grace_begin __namespace~}}

{{~for enum in __enums~}} 
{{~if enum.comment != '' ~}}
/**
 * {{enum.comment | html.escape}}
 */
{{~end~}}
class {{full_name enum}} {
    {{~for item in enum.items ~}}
{{~if item.comment != '' ~}}
    /**
     * {{escape_comment item.comment}}
     */
{{~end~}}
    public const {{item.name}} = {{item.value}};
    {{~end~}}
}

{{~end~}}


{{~for bean in __beans~}}
{{name = (full_name bean)}}
{{~if bean.comment != '' ~}}
/**
 * {{escape_comment bean.comment}}
 */
{{~end~}}
{{class_modifier bean}} class {{name}}{{if bean.parent_def_type}} extends {{full_name bean.parent_def_type}}{{end}} {
{{~if bean.is_abstract_type~}}
    public static function constructFrom($_json_) {
        $type = $_json_['$type'];
        switch ($type) {
        {{~ for child in bean.hierarchy_not_abstract_children~}}
            case '{{impl_data_type child bean}}': return new {{full_name child}}($_json_);
        {{~end~}}
            default: throw new \Exception("unknown type:$type");
        }
    }
{{~end~}}

    public function __construct($_json_) {
        {{~if bean.parent_def_type~}}
        parent::__construct($_json_);
        {{~end~}}
        {{~ for field in bean.export_fields ~}}
        {{~if !field.ctype.is_nullable~}}
        if (!array_key_exists('{{field.name}}', $_json_)) { throw new \Exception("field:'{{field.name}}' missing"); }
        {{~end~}}
        {{deserialize ('$this->' + format_field_name __code_style field.name) ( '$_json_[\'' + field.name + '\']') field.ctype}};
        {{~end~}}
    }

    {{~ for field in bean.export_fields ~}}
{{~if field.comment != '' ~}}
    /**
     * {{escape_comment field.comment}}
     */
{{~end~}}
    public ${{format_field_name __code_style field.name}};
    {{~end~}}
}


{{~end~}}

{{~for table in __tables
    key_type = table.key_ttype
    value_type = table.value_ttype
    name = (full_name table)
~}}

{{~if table.comment != '' ~}}
/**
 * {{escape_comment table.comment}}
 */
{{~end~}}
class {{name}} {
    {{~if table.is_map_table ~}}
    private $_dataMap;
    private $_dataList;
    public function __construct($_json_) {
        $this->_dataMap = [];
        $this->_dataList = [];
        foreach ($_json_ as $_json2_) {
            {{deserialize '$_v' '$_json2_' value_type}};
            array_push($this->_dataList, $_v);
            $this->_dataMap[$_v->{{format_field_name __code_style table.index_field.name}}] = $_v;
        }
    }

    public function getDataMap() { return $this->_dataMap; }
    public function getDataList() { return $this->_dataList; }

    public function get($key) { return $this->_dataMap[$key]; }

    {{~else if table.is_list_table ~}}
    private $_dataList;
    
    public function __construct($_json_) {
        $this->_dataList = [];
        foreach ($_json_ as $_json2_) {
            {{deserialize '$_v' '$_json2_' value_type}};
            array_push($this->_dataList, $_v);
        }
    }

    public function getDataList() { return $this->_dataList; }

    public function get($index) { return $this->_dataList[$index]; }
    
    {{~else~}}

    private $_data;
    public function __construct($_json_) {
        if (count($_json_) != 1) throw new \Exception('table:{{table.name}} mode=one, but size != 1');
        {{deserialize '$this->_data' '$_json_[0]' value_type}};
    }

    public function getData() { return $this->_data; }

    {{~ for field in value_type.def_bean.hierarchy_export_fields ~}}
{{~if field.comment != '' ~}}
    /**
     * {{escape_comment field.comment}}
     */
{{~end~}}
    public function get{{format_field_name __code_style field.name}}() { return $this->_data->{{format_field_name __code_style field.name}}; }
    {{~end~}}

    {{end}}
}

{{~end~}}

class {{__name}} {
    {{~ for table in __tables ~}}
    private $_{{table.name}};
{{~if table.comment != '' ~}}
    /**
     * {{escape_comment table.comment}}
     */
{{~end~}}
    public function get{{table.name}}() { return $this->_{{table.name}}; }
    {{~end~}}

    public function __construct($loader) {
        {{~for table in __tables ~}}
        $this->_{{table.name}} = new {{full_name table}}($loader('{{table.output_data_file}}'));
        {{~end~}}
    }
}

{{~namespace_with_grace_end __namespace~}}
