Generate code.
    
    :param data: must be list of class data, see a valid data example below
    :param output: default None, the python script file name you want to create
    :param tab: default "    "
    :param indent: global indent setting
    :param overwrite: if True, silently overwrite the output file    
    
    ::
    
        data = [
            {
                "classname": "Database",
                "metadata": {"db_id": 1, "name": "Database"},
                "subclass": [
                    {
                        "classname": "PersonCollection",
                        "metadata": {"collection_id": 1, "name": "Person", "create_date": datetime.date(2016, 1, 8)},
                        "subclass": [
                            {
                                "classname": "Person", 
                                "metadata": {"person_id": 1, "name": "Jack"},
                            },
                            {
                                "classname": "Person", 
                                "metadata": {"person_id": 2, "name": "Paul"},
                            },
                        ],
                    },
                    {
                        "classname": "DepartmentCollection",
                        "metadata": {"collection_id": 2, "name": "Department", "create_date": datetime.date(2016, 1, 1)},
                        "subclass": [
                            {
                                "classname": "Department", 
                                "metadata": {"department_id": 1, "name": "IT"},
                            },
                            {    
                                "classname": "Department", 
                                "metadata": {"department_id": 2, "name": "HR"},
                            },
                        ]
                    },
                ],
            },   
        ]

def gencode(data, output=None, tab="    ", indent=0, overwrite=False):
    """Generate code.
    
    :param data: must be list of class data, see a valid data example below
    :param output: default None, the python script file name you want to create
    :param tab: default "    "
    :param indent: global indent setting
    :param overwrite: if True, silently overwrite the output file    
    
    ::
    
        data = [
            {
                "classname": "Database",
                "metadata": {"db_id": 1, "name": "Database"},
                "subclass": [
                    {
                        "classname": "PersonCollection",
                        "metadata": {"collection_id": 1, "name": "Person", "create_date": datetime.date(2016, 1, 8)},
                        "subclass": [
                            {
                                "classname": "Person", 
                                "metadata": {"person_id": 1, "name": "Jack"},
                            },
                            {
                                "classname": "Person", 
                                "metadata": {"person_id": 2, "name": "Paul"},
                            },
                        ],
                    },
                    {
                        "classname": "DepartmentCollection",
                        "metadata": {"collection_id": 2, "name": "Department", "create_date": datetime.date(2016, 1, 1)},
                        "subclass": [
                            {
                                "classname": "Department", 
                                "metadata": {"department_id": 1, "name": "IT"},
                            },
                            {    
                                "classname": "Department", 
                                "metadata": {"department_id": 2, "name": "HR"},
                            },
                        ]
                    },
                ],
            },   
        ]
    """
    codegen = CodeGenerator(tab=tab, indent=indent)
    
    if isinstance(data, list):
        for class_data in data:
            codegen.pre_process(class_data)
            codegen.sort_metadata()
            codegen.repr_class_data(class_data)
            
        for class_data in data:            
            codegen.lines.append("")
            codegen.lines.append("%s" % codegen.repr_new_instance(class_data))
    elif isinstance(data, dict):
        codegen.pre_process(data)
        codegen.repr_class_data(data)
        codegen.lines.append("")
        codegen.lines.append("%s" % codegen.repr_new_instance(data))

    if output:
        if not overwrite:
            if os.path.exists(output):
                raise FileExistsError("%r" % output)
        with open(output, "wb") as f:
            f.write(codegen.code.encode("utf-8"))
    else:
        print(codegen.code)