Java tutorial
/* * Copyright 2011, Mysema Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ccl.jersey.codegen; import com.ccl.jersey.codegen.serializer.SimpleDictSerializer; import com.google.common.io.Files; import com.mysema.codegen.CodeWriter; import com.mysema.codegen.ScalaWriter; import com.mysema.codegen.model.ClassType; import com.mysema.codegen.model.SimpleType; import com.mysema.codegen.model.Type; import com.mysema.codegen.model.TypeCategory; import com.querydsl.codegen.*; import com.querydsl.sql.*; import com.querydsl.sql.codegen.KeyDataFactory; import com.querydsl.sql.codegen.NamingStrategy; import com.querydsl.sql.codegen.SQLCodegenModule; import com.querydsl.sql.codegen.SpatialSupport; import com.querydsl.sql.codegen.support.ForeignKeyData; import com.querydsl.sql.codegen.support.InverseForeignKeyData; import com.querydsl.sql.codegen.support.PrimaryKeyData; import com.querydsl.sql.codegen.support.SizeImpl; import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.HierarchicalConfiguration; import org.apache.commons.configuration.XMLConfiguration; import org.apache.commons.configuration.tree.ConfigurationNode; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.querydsl.codegen.Property; import javax.annotation.Nullable; import javax.validation.constraints.Size; import java.io.File; import java.io.IOException; import java.io.StringWriter; import java.lang.annotation.Annotation; import java.nio.charset.Charset; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.*; /** * SimpleMetaDataExporter exports JDBC metadata to Querydsl query types * <p> * <p> * Example * </p> * <p> * <pre> * SimpleMetaDataExporter exporter = new SimpleMetaDataExporter(); * exporter.setPackageName("com.example.domain"); * exporter.setTargetFolder(new File("target/generated-sources/java")); * exporter.export(connection.getMetaData()); * </pre> * * @author ccl */ public class SimpleMetaDataExporter { private static final Logger logger = LoggerFactory.getLogger(SimpleMetaDataExporter.class); private final SQLTemplatesRegistry sqlTemplatesRegistry = new SQLTemplatesRegistry(); private final SQLCodegenModule module = new SQLCodegenModule(); private final Set<String> classes = new HashSet<String>(); private File targetFolder; @Nullable private String basePackageName; @Nullable private String schemaPattern, tableNamePattern; @Nullable private Serializer beanSerializer; @Nullable private Serializer modelSerializer; @Nullable private Serializer daoIfcSerializer; @Nullable private Serializer daoImplSerializer; @Nullable private Serializer actionFactorySerializer; @Nullable private Serializer dictSerializer; private boolean createScalaSources = false; private final Map<EntityType, Type> entityToWrapped = new HashMap<EntityType, Type>(); private Serializer metaDataSerializer; private TypeMappings typeMappings; private QueryTypeFactory queryTypeFactory; private NamingStrategy namingStrategy; private Configuration configuration; private KeyDataFactory keyDataFactory; private boolean columnAnnotations = false; private boolean validationAnnotations = false; private boolean schemaToPackage = false; private String sourceEncoding = "UTF-8"; private boolean lowerCase = false; private boolean exportTables = true; private boolean exportViews = true; private boolean exportAll = false; private boolean exportPrimaryKeys = true; private boolean exportForeignKeys = true; private boolean exportBelongsTos = true; private boolean exportHasManys = false; private boolean hasVersionColumn = false; private boolean spatial = false; private Map<String, Map<String, Type>> registerDataTypes = new HashMap<>(); private Map<String, Map<String, DictType>> registerDictTypes = new HashMap<>(); private Map<String, String> tableModelMapper = new HashMap<>(); @Nullable private String tableTypesToExport; public SimpleMetaDataExporter() { } public void registerVoDataType(String voClassName, String property, Type type) { Map<String, Type> map = registerDataTypes.get(voClassName); if (null == map) { map = new HashMap<>(); } map.put(property, type); registerDataTypes.put(voClassName, map); } protected EntityType createEntityType(@Nullable String schemaName, String tableName, final String className) { EntityType classModel; if (beanSerializer == null) { String packageName = normalizePackage(module.getPackageName(), schemaName); String simpleName = module.getPrefix() + className + module.getSuffix(); Type classTypeModel = new SimpleType(TypeCategory.ENTITY, packageName + "." + simpleName, packageName, simpleName, false, false); classModel = new PEntityType(classTypeModel); typeMappings.register(classModel, classModel); } else { String beanPackageName = basePackageName + ".entity"; String beanPackage = normalizePackage(beanPackageName, schemaName); String simpleName = module.getBeanPrefix() + className + module.getBeanSuffix(); Type classTypeModel = new SimpleType(TypeCategory.ENTITY, beanPackage + "." + simpleName, beanPackage, simpleName, false, false); classModel = new PEntityType(classTypeModel); Type mappedType = queryTypeFactory.create(classModel); entityToWrapped.put(classModel, mappedType); typeMappings.register(classModel, mappedType); } classModel.getData().put("schema", schemaName); classModel.getData().put("table", tableName); return classModel; } protected EntityType createVOEntityType(@Nullable String schemaName, String tableName, final String className) { EntityType classModel; if (beanSerializer == null) { String packageName = normalizePackage(module.getPackageName(), schemaName); String simpleName = className; Type classTypeModel = new SimpleType(TypeCategory.ENTITY, packageName + "." + simpleName, packageName, simpleName, false, false); classModel = new PEntityType(classTypeModel); typeMappings.register(classModel, classModel); } else { String voPackageName = basePackageName + ".model"; String beanPackage = normalizePackage(voPackageName, schemaName); String simpleName = className; Type classTypeModel = new SimpleType(TypeCategory.ENTITY, beanPackage + "." + simpleName, beanPackage, simpleName, false, false); classModel = new PEntityType(classTypeModel); typeMappings.register(classModel, classModel); } classModel.getData().put("schema", schemaName); classModel.getData().put("table", tableName); return classModel; } private String normalizePackage(String packageName, @Nullable String schemaName) { if (schemaToPackage && schemaName != null) { return namingStrategy.appendSchema(packageName, schemaName); } else { return packageName; } } protected Property createProperty(EntityType classModel, String normalizedColumnName, String propertyName, String escapedName, Type typeModel) { return new Property(classModel, propertyName, escapedName, typeModel, Collections.<String>emptyList(), false); } /** * Export the tables based on the given database metadata * * @param md * @param stmt * @throws SQLException */ public void export(DatabaseMetaData md, Statement stmt) throws SQLException { if (basePackageName == null) { basePackageName = module.getPackageName(); } module.bind(SQLCodegenModule.PACKAGE_NAME, basePackageName + ".query"); String beanPackageName = basePackageName + ".entity"; module.bind(SQLCodegenModule.BEAN_PACKAGE_NAME, beanPackageName); if (spatial) { SpatialSupport.addSupport(module); } typeMappings = module.get(TypeMappings.class); queryTypeFactory = module.get(QueryTypeFactory.class); metaDataSerializer = module.get(Serializer.class); beanSerializer = module.get(Serializer.class, SQLCodegenModule.BEAN_SERIALIZER); namingStrategy = module.get(NamingStrategy.class); configuration = module.get(Configuration.class); SQLTemplates templates = sqlTemplatesRegistry.getTemplates(md); if (templates != null) { configuration.setTemplates(templates); } else { logger.info("Found no specific dialect for " + md.getDatabaseProductName()); } if (beanSerializer == null) { keyDataFactory = new KeyDataFactory(namingStrategy, module.getPackageName(), module.getPrefix(), module.getSuffix(), schemaToPackage); } else { keyDataFactory = new KeyDataFactory(namingStrategy, beanPackageName, module.getBeanPrefix(), module.getBeanSuffix(), schemaToPackage); } String[] typesArray = null; if (tableTypesToExport != null && !tableTypesToExport.isEmpty()) { List<String> types = new ArrayList<String>(); for (String tableType : tableTypesToExport.split(",")) { types.add(tableType.trim()); } typesArray = types.toArray(new String[types.size()]); } else if (!exportAll) { List<String> types = new ArrayList<String>(2); if (exportTables) { types.add("TABLE"); } if (exportViews) { types.add("VIEW"); } typesArray = types.toArray(new String[types.size()]); } Map<String, String> modules = new HashMap<String, String>(); if (tableNamePattern != null && tableNamePattern.contains(",")) { for (String table : tableNamePattern.split(",")) { ResultSet tables = md.getTables(null, schemaPattern, null, typesArray); try { while (tables.next()) { String tableName = normalize(tables.getString("TABLE_NAME")); if (tableName.matches(table)) { addModule(stmt, modules, tableName); handleTable(md, tables, stmt); } } } finally { tables.close(); } } } else { ResultSet tables = md.getTables(null, schemaPattern, null, typesArray); try { while (tables.next()) { String tableName = normalize(tables.getString("TABLE_NAME")); if (null == tableNamePattern || tableName.matches(tableNamePattern)) { addModule(stmt, modules, tableName); handleTable(md, tables, stmt); } } } finally { tables.close(); } } stmt.close(); } private void handleDict() { try { XMLConfiguration config = new XMLConfiguration("dict.xml"); HierarchicalConfiguration.Node root = config.getRoot(); if (root.hasChildren()) { List<ConfigurationNode> dicts = root.getChildren("dict"); for (int i = 0; i < dicts.size(); i++) { String name = config.getString("dict(" + i + ")[@name]"); String label = config.getString("dict(" + i + ")[@label]"); String table = config.getString("dict(" + i + ")[@table]"); String column = config.getString("dict(" + i + ")[@column]"); Map<String, DictType> dictTypeMap = registerDictTypes.get(table); if (null == dictTypeMap) { dictTypeMap = new HashMap<>(); } registerDictTypes.put(table, dictTypeMap); DictType dictType = new DictType(name, label, table, column); dictTypeMap.put(column, dictType); if (dicts.get(i).getChildrenCount() > 0) { List<ConfigurationNode> configurationNodes = dicts.get(i).getChildren("item"); for (int j = 0; j < configurationNodes.size(); j++) { String itemName = config.getString("dict(" + i + ").item(" + j + ")[@name]"); Integer itemValue = config.getInt("dict(" + i + ").item(" + j + ")[@value]"); String itemLabel = config.getString("dict(" + i + ").item(" + j + ")[@label]"); dictType.getItems().add(new DictItemType(itemName, itemValue, itemLabel)); } } } } } catch (ConfigurationException e) { e.printStackTrace(); } } public void serializeDicts() { handleDict(); try { String dictPackageName = basePackageName + ".dict"; for (Map<String, DictType> map : registerDictTypes.values()) { for (DictType dictType : map.values()) { String simpleName = dictType.getName(); String fileSuffix = createScalaSources ? ".scala" : ".java"; String modulesPath = dictPackageName.replace('.', '/') + "/" + simpleName + fileSuffix; Type classTypeModel = new SimpleType(TypeCategory.ENUM, dictPackageName + "." + simpleName, dictPackageName, simpleName, false, false); EntityType classModel = new EntityType(classTypeModel); classModel.addSupertype(new Supertype(new ClassType(DictData.class))); classModel.addProperty(new Property(classModel, "label", new ClassType(String.class))); classModel.addProperty(new Property(classModel, "value", new ClassType(Integer.class))); classModel.addAnnotation(new LabelImpl(dictType.getLabel())); if (null != dictSerializer) { SimpleDictSerializer dictSerializer = (SimpleDictSerializer) this.dictSerializer; dictSerializer.setItemTypes(dictType.getItems()); write(this.dictSerializer, modulesPath, classModel); } dictType.setDictType(classModel); } } } catch (IOException e) { e.printStackTrace(); } } private void addModule(Statement stmt, Map<String, String> modules, String tableName) throws SQLException { String normalizedTableName = namingStrategy.normalizeTableName(tableName); String className = namingStrategy.getClassName(normalizedTableName); String tableComment = getTableComment(stmt, tableName); modules.put(className, null == tableComment ? className : tableComment); } private String getTableComment(Statement stmt, String table) throws SQLException { ResultSet rs = stmt.executeQuery("SHOW CREATE TABLE " + table); String comment = null; if (rs != null && rs.next()) { String create = rs.getString(2); comment = parse(create); } rs.close(); return comment; } String parse(String all) { String comment = null; int index = all.indexOf("COMMENT='"); if (index < 0) { return ""; } comment = all.substring(index + 9); comment = comment.substring(0, comment.length() - 1); return comment; } Set<String> getClasses() { return classes; } private void handleColumn(EntityType classModel, String tableName, ResultSet columns) throws SQLException { String columnName = normalize(columns.getString("COLUMN_NAME")); String normalizedColumnName = namingStrategy.normalizeColumnName(columnName); int columnType = columns.getInt("DATA_TYPE"); String typeName = columns.getString("TYPE_NAME"); Number columnSize = (Number) columns.getObject("COLUMN_SIZE"); Number columnDigits = (Number) columns.getObject("DECIMAL_DIGITS"); int columnIndex = columns.getInt("ORDINAL_POSITION"); int nullable = columns.getInt("NULLABLE"); String remarks = columns.getString("REMARKS"); String defaultValue = columns.getString("COLUMN_DEF"); String propertyName = namingStrategy.getPropertyName(normalizedColumnName, classModel); Map<String, DictType> stringDictTypeMap = registerDictTypes.get(tableName); if (null != stringDictTypeMap) { DictType dictType = stringDictTypeMap.get(columnName); if (null != dictType) { String modelClassName = tableModelMapper.get(tableName); registerVoDataType(modelClassName, propertyName, dictType.getDictType()); } } Class<?> clazz = configuration.getJavaType(columnType, typeName, columnSize != null ? columnSize.intValue() : 0, columnDigits != null ? columnDigits.intValue() : 0, tableName, columnName); if (clazz == null) { throw new IllegalStateException("Found no mapping for " + columnType + " (" + tableName + "." + columnName + " " + typeName + ")"); } TypeCategory fieldType = TypeCategory.get(clazz.getName()); if (Number.class.isAssignableFrom(clazz)) { fieldType = TypeCategory.NUMERIC; } else if (Enum.class.isAssignableFrom(clazz)) { fieldType = TypeCategory.ENUM; } Type typeModel = new ClassType(fieldType, clazz); Property property = createProperty(classModel, normalizedColumnName, propertyName, propertyName, typeModel); if (null != defaultValue) property.setDefaultValue(DataTypeConvertUtils.convert(defaultValue, clazz)); ColumnMetadata column = ColumnMetadata.named(normalizedColumnName).ofType(columnType) .withIndex(columnIndex); if (nullable == DatabaseMetaData.columnNoNulls) { column = column.notNull(); } if (columnSize != null) { column = column.withSize(columnSize.intValue()); } if (columnDigits != null) { column = column.withDigits(columnDigits.intValue()); } property.getData().put("COLUMN", column); if (columnAnnotations) { property.addAnnotation(new ColumnImpl(normalizedColumnName)); } if (validationAnnotations) { if (nullable == DatabaseMetaData.columnNoNulls) { NotNullImpl annotation = new NotNullImpl(); property.addAnnotation(annotation); } int size = columns.getInt("COLUMN_SIZE"); if (size > 0 && clazz.equals(String.class)) { property.addAnnotation(new SizeImpl(0, size)); } } LabelImpl label = new LabelImpl(StringUtils.isBlank(remarks) ? propertyName : remarks); property.addAnnotation(label); classModel.addProperty(property); } @SuppressWarnings("unchecked") private void handleTable(DatabaseMetaData md, ResultSet tables, Statement stmt) throws SQLException { String catalog = tables.getString("TABLE_CAT"); String schema = tables.getString("TABLE_SCHEM"); String schemaName = normalize(tables.getString("TABLE_SCHEM")); String tableName = normalize(tables.getString("TABLE_NAME")); String comment = getTableComment(stmt, tableName); String normalizedTableName = namingStrategy.normalizeTableName(tableName); String className = namingStrategy.getClassName(normalizedTableName); EntityType classModel = createEntityType(schemaName, normalizedTableName, className); EntityType modelClassModel = createVOEntityType(schemaName, normalizedTableName, className); tableModelMapper.put(normalizedTableName, modelClassModel.getFullName()); if (exportPrimaryKeys) { // collect primary keys Map<String, PrimaryKeyData> primaryKeyData = keyDataFactory.getPrimaryKeys(md, catalog, schema, tableName); if (!primaryKeyData.isEmpty()) { classModel.getData().put(PrimaryKeyData.class, primaryKeyData.values()); } } Map<String, UniqueKeyData> uniqueKeyDatas = new HashMap<>(); ResultSet indexInfo = md.getIndexInfo(catalog, schema, tableName, true, false); while (indexInfo.next()) { String indexName = indexInfo.getString("INDEX_NAME"); if (!"PRIMARY".equals(indexName)) { UniqueKeyData uniqueKeyData = uniqueKeyDatas.get(indexName); if (null == uniqueKeyData) { uniqueKeyData = new UniqueKeyData(indexName); } uniqueKeyDatas.put(indexName, uniqueKeyData); String columnName = indexInfo.getString("COLUMN_NAME"); String normalizedColumnName = namingStrategy.normalizeColumnName(columnName); String propertyName = namingStrategy.getPropertyName(normalizedColumnName, classModel); uniqueKeyData.add(propertyName); } } indexInfo.close(); if (!uniqueKeyDatas.isEmpty()) { Collection<UniqueKeyData> values = uniqueKeyDatas.values(); classModel.getData().put(UniqueKeyData.class, values); List<Unique> uniques = new ArrayList<>(); for (UniqueKeyData uniqueKeyData : values) { UniqueImpl unique = new UniqueImpl( uniqueKeyData.getColumns().toArray(new String[uniqueKeyData.getColumns().size()])); uniques.add(unique); } classModel.addAnnotation(new UniquesImpl(uniques.toArray(new Unique[uniques.size()]))); } if (exportForeignKeys) { // collect foreign keys Map<String, ForeignKeyData> foreignKeyData = keyDataFactory.getImportedKeys(md, catalog, schema, tableName); if (!foreignKeyData.isEmpty()) { classModel.getData().put(ForeignKeyData.class, foreignKeyData.values()); } // collect inverse foreign keys Map<String, InverseForeignKeyData> inverseForeignKeyData = keyDataFactory.getExportedKeys(md, catalog, schema, tableName); if (!inverseForeignKeyData.isEmpty()) { classModel.getData().put(InverseForeignKeyData.class, inverseForeignKeyData.values()); } } // collect columns ResultSet columns = md.getColumns(catalog, schema, tableName.replace("/", "//"), null); try { while (columns.next()) { handleColumn(classModel, tableName, columns); } } finally { columns.close(); } // serialize model LabelImpl label = new LabelImpl(StringUtils.isBlank(comment) ? className : comment); classModel.addAnnotation(label); Set<Property> properties = classModel.getProperties(); Map<String, Type> dataTypeMap = registerDataTypes.get(modelClassModel.getFullName()); String modelPackageName = basePackageName + ".model"; List<BelongsToImpl> belongsTos = new ArrayList<BelongsToImpl>(); for (Property property : properties) { Type propertyType = property.getType(); boolean customType = false; String propertyName = property.getName(); if (null != dataTypeMap) { Type propertyCls = dataTypeMap.get(propertyName); if (null != propertyCls) { propertyType = propertyCls; customType = true; } } Collection<ForeignKeyData> foreignKeyDatas = (Collection<ForeignKeyData>) classModel.getData() .get(ForeignKeyData.class); boolean isForeignKey = false; if (exportBelongsTos && null != foreignKeyDatas && !foreignKeyDatas.isEmpty()) { for (ForeignKeyData foreignKey : foreignKeyDatas) { String propertyName2 = namingStrategy.getPropertyName(foreignKey.getForeignColumns().get(0), classModel); if (propertyName.equals(propertyName2)) { String simpleName = foreignKey.getType().getSimpleName(); simpleName = simpleName.substring(module.getBeanPrefix().length(), simpleName.length()); propertyType = new SimpleType(modelPackageName + "." + simpleName, modelPackageName, simpleName); propertyName = propertyName2.substring(0, propertyName2.length() - 2); belongsTos.add(new BelongsToImpl(propertyName, propertyName2)); isForeignKey = true; break; } } } Property property2 = createProperty(modelClassModel, propertyName, propertyName, propertyName, propertyType); Collection<Annotation> annotations = property.getAnnotations(); for (Annotation annotation : annotations) { if ((isForeignKey || customType) && Size.class.equals(annotation.annotationType())) { continue; } property2.addAnnotation(annotation); } modelClassModel.addProperty(property2); if (customType) { property.addAnnotation(new DictDataTypeImpl((Class<? extends Enum>) propertyType.getJavaClass())); } } Collection<InverseForeignKeyData> inverseForeignKeyDatas = (Collection<InverseForeignKeyData>) classModel .getData().get(InverseForeignKeyData.class); List<HasManyImpl> hasManys = new ArrayList<HasManyImpl>(); if (exportHasManys && null != inverseForeignKeyDatas && !inverseForeignKeyDatas.isEmpty()) { for (InverseForeignKeyData inverseForeignKeyData : inverseForeignKeyDatas) { String simpleName = inverseForeignKeyData.getType().getSimpleName(); simpleName = simpleName.substring(module.getBeanPrefix().length(), simpleName.length()); Type propertyType = new SimpleType(modelPackageName + "." + simpleName, modelPackageName, simpleName); Type propertyListType = new ClassType(TypeCategory.LIST, List.class, propertyType); String propertyName2 = namingStrategy.getPropertyName(inverseForeignKeyData.getTable(), classModel); String propertyName = propertyName2 + "s"; Set<String> propertyNames = modelClassModel.getPropertyNames(); int index = 0; while (propertyNames.contains(propertyName)) { index++; propertyName = propertyName2 + index + "s"; } Property property2 = createProperty(modelClassModel, propertyName, propertyName, propertyName, propertyListType); String tableComment = getTableComment(stmt, inverseForeignKeyData.getTable()); LabelImpl tableLabel = new LabelImpl(StringUtils.isBlank(tableComment) ? propertyName : tableComment + "" + (0 < index ? index : "")); property2.addAnnotation(tableLabel); modelClassModel.addProperty(property2); hasManys.add(new HasManyImpl(propertyName, namingStrategy .getPropertyName(inverseForeignKeyData.getParentColumns().get(0), classModel))); } } if (!belongsTos.isEmpty()) { modelClassModel .addAnnotation(new BelongsTosImpl(belongsTos.toArray(new BelongsToImpl[belongsTos.size()]))); } if (!hasManys.isEmpty()) { modelClassModel.addAnnotation(new HasManysImpl(hasManys.toArray(new HasManyImpl[hasManys.size()]))); } modelClassModel.addAnnotation(label); serialize(classModel, modelClassModel); logger.info("Exported " + tableName + " successfully"); } private String normalize(String str) { if (lowerCase && str != null) { return str.toLowerCase(); } else { return str; } } private void serialize(EntityType type, EntityType modelType) { try { Label entityLabelAnnotation = type.getAnnotation(Label.class); String entityLabel = entityLabelAnnotation.value(); String fileSuffix = createScalaSources ? ".scala" : ".java"; String beanPackageName = basePackageName + ".entity"; String daoPackageName = basePackageName + ".repository"; String actionPackageName = basePackageName + ".action"; String modelPackageName = basePackageName + ".model"; if (beanSerializer != null) { String packageName = normalizePackage(beanPackageName, (String) type.getData().get("schema")); String path = packageName.replace('.', '/') + "/" + type.getSimpleName() + fileSuffix; Set<Property> properties = type.getProperties(); Property primaryKeyProperty = null; boolean hasCreateTime = false; boolean hasUpdateTime = false; for (Property property : properties) { if ("id".equals(property.getName())) { primaryKeyProperty = property; } else if ("createTime".equals(property.getName())) { hasCreateTime = true; } else if ("updateTime".equals(property.getName())) { hasUpdateTime = true; } } PEntityType pEntityType = (PEntityType) type; PEntityType pModelType = (PEntityType) modelType; if (hasCreateTime && hasUpdateTime) { pEntityType.addSupertype(new Supertype(new ClassType(StatisticsEntity.class))); } Type primaryKeyPropertyType = primaryKeyProperty.getType(); Type beanSuperType = new ClassType(AbstractIdEntity.class, primaryKeyPropertyType); if (hasCreateTime && hasUpdateTime) { beanSuperType = new ClassType(AbstractStatisticsEntity.class, primaryKeyPropertyType); } Supertype beanEntityType = new Supertype(beanSuperType); pEntityType.setParentType(beanEntityType); write(beanSerializer, path, type); String otherPath = entityToWrapped.get(type).getFullName().replace('.', '/') + fileSuffix; write(metaDataSerializer, otherPath, type); if (modelSerializer != null) { String modelPkgName = normalizePackage(modelPackageName, (String) modelType.getData().get("schema")); String modelPath = modelPkgName.replace('.', '/') + "/" + modelType.getSimpleName() + fileSuffix; DomainImpl domainImpl = new DomainImpl(type.getFullName()); modelType.addAnnotation(domainImpl); Type modelSuperType = new ClassType(AbstractDataModel.class, type, primaryKeyPropertyType); Supertype modelEntityType = new Supertype(modelSuperType); pModelType.setParentType(modelEntityType); if (hasVersionColumn) { pModelType.addSupertype(new Supertype(new ClassType(VersionOfEntity.class))); } write(modelSerializer, modelPath, modelType); } // dao? if (daoIfcSerializer != null) { String daoIfcPkgName = normalizePackage(daoPackageName, (String) modelType.getData().get("schema")); String simpleName = modelType.getSimpleName() + "Repository"; String daoIfcPath = daoIfcPkgName.replace('.', '/') + "/" + simpleName + fileSuffix; Type superType; if (modelSerializer != null) { superType = new ClassType(ModelQueryAndBatchUpdateRepository.class, modelType, type, primaryKeyPropertyType); } else { superType = new ClassType(DataQueryAndBatchUpdateRepository.class, type, primaryKeyPropertyType); } Supertype entityType = new Supertype(superType); Type classTypeModel = new SimpleType(TypeCategory.ENTITY, daoIfcPkgName + "." + simpleName, daoIfcPkgName, simpleName, false, false); PEntityType classModel = new PEntityType(classTypeModel); classModel.addSupertype(entityType); classModel.addAnnotation(new LabelImpl(entityLabel + "")); write(daoIfcSerializer, daoIfcPath, classModel); // dao if (daoImplSerializer != null) { String daoImplPkgName = daoIfcPkgName + ".impl"; String daoImplSimpleName = simpleName + "Impl"; String daoImplPath = daoImplPkgName.replace('.', '/') + "/" + daoImplSimpleName + fileSuffix; Type daoImplSuperType; if (modelSerializer != null) { daoImplSuperType = new ClassType(AbstractModelQueryAndBatchUpdateRepository.class, type, primaryKeyPropertyType, modelType); } else { daoImplSuperType = new ClassType(AbstractDataQueryAndBatchUpdateRepository.class, type, primaryKeyPropertyType); } Supertype daoImplEntityType = new Supertype(daoImplSuperType); Type daoImplClassTypeModel = new SimpleType(TypeCategory.ENTITY, daoImplPkgName + "." + daoImplSimpleName, daoImplPkgName, daoImplSimpleName, false, false); PEntityType daoImplClassModel = new PEntityType(daoImplClassTypeModel, daoImplEntityType); daoImplClassModel.addSupertype(new Supertype(classModel)); daoImplClassModel.addAnnotation(new LabelImpl(entityLabel + "")); daoImplClassModel.addAnnotation(new ValidatedImpl(new Class[] {})); write(daoImplSerializer, daoImplPath, daoImplClassModel); } // actionFactory if (actionFactorySerializer != null) { String actionFactoryPkgName = actionPackageName; String actionFactorySimpleName = modelType.getSimpleName() + "ActionFactory"; String actionFactoryPath = actionFactoryPkgName.replace('.', '/') + "/" + actionFactorySimpleName + fileSuffix; Type actionFactorySuperType = new ClassType(AbstractCrudModelActionFactory.class, classTypeModel, modelType, type, primaryKeyPropertyType); Supertype actionFactoryEntityType = new Supertype(actionFactorySuperType); Type actionFactoryClassTypeModel = new SimpleType(TypeCategory.ENTITY, actionFactoryPkgName + "." + actionFactorySimpleName, actionFactoryPkgName, actionFactorySimpleName, false, false); PEntityType actionFactoryClassModel = new PEntityType(actionFactoryClassTypeModel, actionFactoryEntityType); actionFactoryClassModel.addAnnotation(new ParentModuleImpl(DataAdminModule.class)); actionFactoryClassModel.addAnnotation(new LabelImpl(entityLabel + "??")); actionFactoryClassModel.addAnnotation(new ValidatedImpl(new Class<?>[] {})); write(actionFactorySerializer, actionFactoryPath, actionFactoryClassModel); } } } else { String packageName = normalizePackage(module.getPackageName(), (String) type.getData().get("schema")); String path = packageName.replace('.', '/') + "/" + type.getSimpleName() + fileSuffix; write(metaDataSerializer, path, type); } } catch (IOException e) { throw new RuntimeException(e.getMessage(), e); } } private void write(Serializer serializer, String path, EntityType type) throws IOException { File targetFile = new File(targetFolder, path); classes.add(targetFile.getPath()); StringWriter w = new StringWriter(); CodeWriter writer = createScalaSources ? new ScalaWriter(w) : new MyJavaWriter(w); serializer.serialize(type, SimpleSerializerConfig.DEFAULT, writer); // conditional creation boolean generate = true; byte[] bytes = w.toString().getBytes(sourceEncoding); if (targetFile.exists() && targetFile.length() == bytes.length) { String str = Files.toString(targetFile, Charset.forName(sourceEncoding)); if (str.equals(w.toString())) { generate = false; } } else { targetFile.getParentFile().mkdirs(); } if (generate) { Files.write(bytes, targetFile); } } /** * Set the schema pattern filter to be used * * @param schemaPattern a schema name pattern; must match the schema name as it is * stored in the database; "" retrieves those without a schema; * {@code null} means that the schema name should not be used to * narrow the search (default: null) */ public void setSchemaPattern(@Nullable String schemaPattern) { this.schemaPattern = schemaPattern; } /** * Set the table name pattern filter to be used * * @param tableNamePattern a table name pattern; must match the table name as it is * stored in the database (default: null) */ public void setTableNamePattern(@Nullable String tableNamePattern) { this.tableNamePattern = tableNamePattern; } /** * Override the configuration * * @param configuration override configuration for custom type mappings etc */ public void setConfiguration(Configuration configuration) { module.bind(Configuration.class, configuration); } /** * Set true to create Scala sources instead of Java sources * * @param createScalaSources whether to create Scala sources (default: false) */ public void setCreateScalaSources(boolean createScalaSources) { this.createScalaSources = createScalaSources; } /** * Set the target folder * * @param targetFolder target source folder to create the sources into (e.g. * target/generated-sources/java) */ public void setTargetFolder(File targetFolder) { this.targetFolder = targetFolder; } /** * Override the bean package name (default: packageName) * * @param packageName */ public void setPackageName(@Nullable String packageName) { this.basePackageName = packageName; } /** * Override the name prefix for the classes (default: Q) * * @param namePrefix name prefix for query-types (default: Q) */ public void setNamePrefix(String namePrefix) { module.bind(CodegenModule.PREFIX, namePrefix); } /** * Override the name suffix for the classes (default: "") * * @param nameSuffix name suffix for query-types (default: "") */ public void setNameSuffix(String nameSuffix) { module.bind(CodegenModule.SUFFIX, nameSuffix); } /** * Override the bean prefix for the classes (default: "") * * @param beanPrefix bean prefix for bean-types (default: "") */ public void setBeanPrefix(String beanPrefix) { module.bind(SQLCodegenModule.BEAN_PREFIX, beanPrefix); } /** * Override the bean suffix for the classes (default: "") * * @param beanSuffix bean suffix for bean-types (default: "") */ public void setBeanSuffix(String beanSuffix) { module.bind(SQLCodegenModule.BEAN_SUFFIX, beanSuffix); } public void setModelSerializer(Serializer modelSerializer) { this.modelSerializer = modelSerializer; } /** * Override the NamingStrategy (default: new DefaultNamingStrategy()) * * @param namingStrategy namingstrategy to override (default: new * DefaultNamingStrategy()) */ public void setNamingStrategy(NamingStrategy namingStrategy) { module.bind(NamingStrategy.class, namingStrategy); } /** * Set the Bean serializer to create bean types as well * * @param beanSerializer serializer for JavaBeans (default: null) */ public void setBeanSerializer(@Nullable Serializer beanSerializer) { module.bind(SQLCodegenModule.BEAN_SERIALIZER, beanSerializer); } /** * Set the Bean serializer class to create bean types as well * * @param beanSerializerClass serializer for JavaBeans (default: null) */ public void setBeanSerializerClass(Class<? extends Serializer> beanSerializerClass) { module.bind(SQLCodegenModule.BEAN_SERIALIZER, beanSerializerClass); } /** * @param innerClassesForKeys */ public void setInnerClassesForKeys(boolean innerClassesForKeys) { module.bind(SQLCodegenModule.INNER_CLASSES_FOR_KEYS, innerClassesForKeys); } /** * @param columnComparatorClass */ public void setColumnComparatorClass(Class<? extends Comparator<Property>> columnComparatorClass) { module.bind(SQLCodegenModule.COLUMN_COMPARATOR, columnComparatorClass); } /** * @param serializerClass */ public void setMetadataSerializerClass(Class<? extends Serializer> serializerClass) { module.bind(Serializer.class, serializerClass); } public void setDaoIfcSerializer(Serializer daoIfcSerializer) { this.daoIfcSerializer = daoIfcSerializer; } public void setDaoImplSerializer(Serializer daoImplSerializer) { this.daoImplSerializer = daoImplSerializer; } public void setActionFactorySerializer(Serializer actionFactorySerializer) { this.actionFactorySerializer = actionFactorySerializer; } public void setDictSerializer(Serializer dictSerializer) { this.dictSerializer = dictSerializer; } /** * @param typeMappings */ public void setTypeMappings(TypeMappings typeMappings) { module.bind(TypeMappings.class, typeMappings); } /** * @param columnAnnotations */ public void setColumnAnnotations(boolean columnAnnotations) { this.columnAnnotations = columnAnnotations; } /** * @param validationAnnotations */ public void setValidationAnnotations(boolean validationAnnotations) { this.validationAnnotations = validationAnnotations; } /** * @param sourceEncoding */ public void setSourceEncoding(String sourceEncoding) { this.sourceEncoding = sourceEncoding; } /** * @param schemaToPackage */ public void setSchemaToPackage(boolean schemaToPackage) { this.schemaToPackage = schemaToPackage; module.bind(SQLCodegenModule.SCHEMA_TO_PACKAGE, schemaToPackage); } /** * @param lowerCase */ public void setLowerCase(boolean lowerCase) { this.lowerCase = lowerCase; } /** * @param exportTables */ public void setExportTables(boolean exportTables) { this.exportTables = exportTables; } /** * @param exportViews */ public void setExportViews(boolean exportViews) { this.exportViews = exportViews; } /** * @param exportAll */ public void setExportAll(boolean exportAll) { this.exportAll = exportAll; } /** * @param exportPrimaryKeys */ public void setExportPrimaryKeys(boolean exportPrimaryKeys) { this.exportPrimaryKeys = exportPrimaryKeys; } /** * @param exportForeignKeys */ public void setExportForeignKeys(boolean exportForeignKeys) { this.exportForeignKeys = exportForeignKeys; } public void setExportBelongsTos(boolean exportBelongsTos) { this.exportBelongsTos = exportBelongsTos; } public void setExportHasManys(boolean exportHasManys) { this.exportHasManys = exportHasManys; } public void setHasVersionColumn(boolean hasVersionColumn) { this.hasVersionColumn = hasVersionColumn; } /** * Set the java imports * * @param imports java imports array */ public void setImports(String[] imports) { module.bind(CodegenModule.IMPORTS, new HashSet<String>(Arrays.asList(imports))); } /** * @param spatial */ public void setSpatial(boolean spatial) { this.spatial = spatial; } /** * @param tableTypesToExport */ public void setTableTypesToExport(String tableTypesToExport) { this.tableTypesToExport = tableTypesToExport; } }