Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (C) 2015 HaiYang Li
*
* 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.landawn.abacus.util;
import static com.landawn.abacus.util.CodeGenerator.EntityMode.EXTEND_DIRTY_MARKER;
import static com.landawn.abacus.util.CodeGenerator.EntityMode.IMPL_DIRTY_MARKER;
import static com.landawn.abacus.util.WD._PERIOD;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Serializable;
import java.io.Writer;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.NavigableMap;
import java.util.NavigableSet;
import java.util.Objects;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import javax.xml.bind.annotation.XmlTransient;
import org.w3c.dom.Comment;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.landawn.abacus.DirtyMarker;
import com.landawn.abacus.core.AbstractDirtyMarker;
import com.landawn.abacus.core.DirtyMarkerImpl;
import com.landawn.abacus.exception.AbacusException;
import com.landawn.abacus.exception.UncheckedIOException;
import com.landawn.abacus.logging.Logger;
import com.landawn.abacus.logging.LoggerFactory;
import com.landawn.abacus.metadata.Column;
import com.landawn.abacus.metadata.ColumnType;
import com.landawn.abacus.metadata.Database;
import com.landawn.abacus.metadata.EntityDefXmlEle.DatabaseEle;
import com.landawn.abacus.metadata.EntityDefXmlEle.EntityDefEle;
import com.landawn.abacus.metadata.EntityDefXmlEle.EntityDefEle.EntityEle;
import com.landawn.abacus.metadata.EntityDefXmlEle.EntityDefEle.EntityEle.PropertyEle;
import com.landawn.abacus.metadata.EntityDefXmlEle.EntityDefEle.EntityEle.TableEle;
import com.landawn.abacus.metadata.EntityDefXmlEle.EntityDefEle.EntityEle.TableEle.ColumnEle;
import com.landawn.abacus.metadata.EntityDefinition;
import com.landawn.abacus.metadata.EntityDefinitionFactory;
import com.landawn.abacus.metadata.Property;
import com.landawn.abacus.metadata.Table;
import com.landawn.abacus.metadata.sql.SQLEntityDefinition;
import com.landawn.abacus.metadata.sql.SQLEntityDefinitionFactory;
import com.landawn.abacus.type.HBaseColumnType;
import com.landawn.abacus.type.ObjectType;
import com.landawn.abacus.type.Type;
import com.landawn.abacus.type.TypeType;
/**
*
* @since 0.8
*
* @author Haiyang Li
*/
public final class CodeGenerator {
private static final Logger logger = LoggerFactory.getLogger(CodeGenerator.class);
/**
* To generate the entity classes which not depend on N.class in the codes of hashcode/equals/toString methods, specify the parameter utilClassForHashEqualsToString in method entityDefinitionXml2Class with this value _N.
*/
public static final Class> _N = _N.class;
private static final String POSTFIX_OF_JAVA_FILE = ".java";
/**
* Field TABLE_NAME2ENTITY_NAME. (value is ""tableName2EntityName"")
*/
private static final String TABLE_NAME2ENTITY_NAME = "tableName2EntityName";
/**
* Field COLUMN_NAME2PROP_NAME. (value is ""columnName2PropName"")
*/
private static final String COLUMN_NAME2PROP_NAME = "columnName2PropName";
/**
* Field PROP_NAME2VAR_NAME. (value is ""propName2VarName"")
*/
private static final String PROP_NAME2VAR_NAME = "propName2VarName";
/**
* Field PROP_NAME2METHOD_NAME. (value is ""propName2MethodName"")
*/
private static final String PROP_NAME2METHOD_NAME = "propName2MethodName";
/**
* Field UTF_8
*/
private static final String UTF_8 = "UTF-8";
/**
* Field DOMAIN_NAME_VAR. (value is """_DN"")
*/
private static final String DOMAIN_NAME_VAR = "_DN";
/**
* Field ENTITY_NAME_VAR. (value is ""__"")
*/
private static final String ENTITY_NAME_VAR = "__";
/**
* Field PROP_NAME_LIST. (value is ""_PNL"")
*/
private static final String PROP_NAME_LIST = "_PNL";
/**
* Field PROP_NAME_MAP. (value is ""_PNM"")
*/
// private static final String PROP_NAME_MAP = "_PNM";
/**
* Field PROP_COLUMN_MAP. (value is ""_PCM"")
*/
// private static final String PROP_COLUMN_MAP = "_PCM";
/**
* Field COLUMN_NAME_LIST. (value is ""_CNL"")
*/
private static final String COLUMN_NAME_LIST = "_CNL";
/**
* Field COLUMN_NAME_MAP. (value is ""_CNM"")
*/
// private static final String COLUMN_NAME_MAP = "_CNM";
/**
* Field COLUMN_PROP_MAP. (value is ""_CPM"")
*/
// private static final String COLUMN_PROP_MAP = "_CPM";
/**
* Field POSTFIX_OF_PROP_NAME_LIST. (value is ""PNL"")
*/
private static final String POSTFIX_OF_PROP_NAME_LIST = "PNL";
/**
* Field POSTFIX_OF_COLUMN_NAME_LIST. (value is ""CNL"")
*/
private static final String POSTFIX_OF_COLUMN_NAME_LIST = "CNL";
/**
* The field name of DirtyMarker implementation in a generated entity class which implements the DirtyMarker interface. (value is ""dirtyMarkerImpl"")
*/
private static final String DIRTY_MARKER_IMPL_FIELD_NAME = "dirtyMarkerImpl";
/**
* Field USUAL_TYPES.
*/
private static Set USUAL_TYPES = new LinkedHashSet<>();
static {
USUAL_TYPES.add("java.lang");
USUAL_TYPES.add("java.util");
USUAL_TYPES.add("java.util.concurrent");
USUAL_TYPES.add("java.time");
USUAL_TYPES.add("java.io");
USUAL_TYPES.add("java.nio");
USUAL_TYPES.add("java.sql");
USUAL_TYPES.add("java.net");
USUAL_TYPES.add("java.math");
USUAL_TYPES.add("javax.xml");
USUAL_TYPES.add(HBaseColumn.class.getCanonicalName());
}
private static Map JAVA_TYPE_PROP_NAME = new HashMap<>();
static {
JAVA_TYPE_PROP_NAME.put(boolean.class.getName(), "boolean_");
JAVA_TYPE_PROP_NAME.put(char.class.getName(), "char_");
JAVA_TYPE_PROP_NAME.put(byte.class.getName(), "byte_");
JAVA_TYPE_PROP_NAME.put(short.class.getName(), "short_");
JAVA_TYPE_PROP_NAME.put(int.class.getName(), "int_");
JAVA_TYPE_PROP_NAME.put(long.class.getName(), "long_");
JAVA_TYPE_PROP_NAME.put(float.class.getName(), "float_");
JAVA_TYPE_PROP_NAME.put(double.class.getName(), "double_");
JAVA_TYPE_PROP_NAME.put("class", "class_");
}
/**
* Constructor for CodeGenerator.
*/
private CodeGenerator() {
// No instance.
}
static String makePackageFolder(String srcPath, final String pkgName) {
srcPath = (srcPath.endsWith("/") || srcPath.endsWith("\\")) ? srcPath : (srcPath + File.separator);
String classFilePath = (pkgName == null) ? srcPath : (srcPath + pkgName.replace('.', File.separatorChar) + File.separator);
File classFileFolder = new File(classFilePath);
if (!classFileFolder.exists()) {
classFileFolder.mkdirs();
}
return classFilePath;
}
static void database2Xml(final Database database, final File xml, final Map databaseElementAttrs) {
Document doc = XMLUtil.createDOMParser(true, true).newDocument();
Element databaseNode = doc.createElement(DatabaseEle.DATABASE);
database2Node(database, databaseNode, databaseElementAttrs);
doc.appendChild(databaseNode);
XMLUtil.transform(doc, xml);
}
static Element database2Node(final Database database, final Element node, final Map databaseElementAttrs) {
Document doc = node.getOwnerDocument();
Element databaseNode = null;
if (DatabaseEle.DATABASE.equals(node.getTagName())) {
databaseNode = node;
} else {
databaseNode = doc.createElement(DatabaseEle.DATABASE);
node.appendChild(databaseNode);
}
setAttributes(databaseNode, databaseElementAttrs);
databaseNode.setAttribute(DatabaseEle.NAME, database.getName());
Collection tableNames = database.getTableNameList();
for (String tableName : tableNames) {
Table table = database.getTable(tableName);
Element tableNode = table2Node(table, databaseNode);
tableNode.removeAttribute(DatabaseEle.DATABASE);
}
return databaseNode;
}
static Element table2Node(final Table table, final Element node) {
Document doc = node.getOwnerDocument();
Element tableNode = null;
if (TableEle.TABLE.equals(node.getTagName())) {
tableNode = node;
} else {
tableNode = doc.createElement(TableEle.TABLE);
node.appendChild(tableNode);
}
for (Map.Entry entry : table.getAttributes().entrySet()) {
tableNode.setAttribute(entry.getKey(), entry.getValue());
}
Collection columnNames = table.getColumnNameList();
for (String columnName : columnNames) {
Element columnNode = doc.createElement(ColumnEle.COLUMN);
Column column = table.getColumn(columnName);
for (Map.Entry entry : column.getAttributes().entrySet()) {
columnNode.setAttribute(entry.getKey(), entry.getValue());
}
columnNode.setAttribute(ColumnEle.NAME, column.getName());
tableNode.appendChild(columnNode);
}
return tableNode;
}
static void table2Xml(final Table table, final File xml) {
Document doc = XMLUtil.createDOMParser(true, true).newDocument();
Element tableNode = doc.createElement(TableEle.TABLE);
table2Node(table, tableNode);
doc.appendChild(tableNode);
XMLUtil.transform(doc, xml);
}
public static void database2EntityDefinitionXml(final Database database, final File entityDefinitionXml) {
database2EntityDefinitionXml(database, entityDefinitionXml, null);
}
public static void database2EntityDefinitionXml(final Database database, final File entityDefinitionXml, final Map entityDefAttrs) {
Map newEntityNames = new LinkedHashMap<>();
Map newPropNames = new LinkedHashMap<>();
database2EntityDefinitionXml(database, entityDefinitionXml, entityDefAttrs, newEntityNames, newPropNames, null);
}
public static void database2EntityDefinitionXml(final Database database, final File entityDefinitionXml, final Map entityDefAttrs,
final Map newEntityNames, final Map newPropNames, final Map> excludedeEntityPropNames) {
Map> newEntityPropNames = new LinkedHashMap<>();
Collection
tables = database.getTableList();
for (Table table : tables) {
String entityName = table.getName();
if (newEntityNames.get(entityName) != null) {
entityName = newEntityNames.get(entityName);
}
newEntityPropNames.put(entityName, newPropNames);
}
database2EntityDefinitionXml(database, entityDefinitionXml, entityDefAttrs, null, newEntityNames, null, newEntityPropNames, excludedeEntityPropNames);
}
public static void database2EntityDefinitionXml(final Database database, final File entityDefinitionXml, final Map entityDefAttrs,
Method tableName2EntityName, final Method columnName2PropName, final Map> excludedeEntityPropNames) {
if (tableName2EntityName == null) {
tableName2EntityName = ClassUtil.getDeclaredMethod(CodeGenerator.class, TABLE_NAME2ENTITY_NAME, String.class);
}
Map entityColumnName2PropName = new LinkedHashMap<>();
Collection
tables = database.getTableList();
for (Table table : tables) {
String entityName = (String) ClassUtil.invokeMethod(tableName2EntityName, table.getName());
entityColumnName2PropName.put(entityName, columnName2PropName);
}
database2EntityDefinitionXml(database, entityDefinitionXml, entityDefAttrs, tableName2EntityName, null, entityColumnName2PropName, null,
excludedeEntityPropNames);
}
static void database2EntityDefinitionXml(final Database database, final File entityDefinitionXml, final Map entityDefAttrs,
Method tableName2EntityName, Map newEntityNames, Map entityColumnName2PropName,
Map> newEntityPropNames, Map> excludedeEntityPropNames) {
if (tableName2EntityName == null) {
tableName2EntityName = ClassUtil.getDeclaredMethod(CodeGenerator.class, TABLE_NAME2ENTITY_NAME, String.class);
}
if (newEntityNames == null) {
newEntityNames = new LinkedHashMap<>();
}
if (entityColumnName2PropName == null) {
entityColumnName2PropName = new LinkedHashMap<>();
}
if (newEntityPropNames == null) {
newEntityPropNames = new LinkedHashMap<>();
}
if (excludedeEntityPropNames == null) {
excludedeEntityPropNames = new LinkedHashMap<>();
}
Document doc = XMLUtil.createDOMParser(true, true).newDocument();
Element entityDefNode = doc.createElement(EntityDefEle.ENTITY_DEF);
Document existedDoc = null;
if (entityDefinitionXml.exists()) {
try {
existedDoc = XMLUtil.createDOMParser(true, true).parse(entityDefinitionXml);
} catch (Exception e) {
throw new AbacusException(e);
}
NodeList nodes = existedDoc.getElementsByTagName(EntityDefEle.ENTITY_DEF);
if ((nodes != null) && (nodes.getLength() > 0)) {
NamedNodeMap attrs = nodes.item(0).getAttributes();
for (int i = 0; i < attrs.getLength(); i++) {
entityDefNode.setAttribute(attrs.item(i).getNodeName(), attrs.item(i).getNodeValue());
}
}
}
setAttributes(entityDefNode, entityDefAttrs);
String packageAttr = entityDefNode.getAttribute(EntityDefEle.PACKAGE);
if ((packageAttr == null) || (packageAttr.length() == 0)) {
entityDefNode.setAttribute(EntityDefEle.PACKAGE, database.getName());
}
Map existedEntityEleList = getEntityElementList(existedDoc);
Set entityNameList = new LinkedHashSet<>();
Collection
tables = database.getTableList();
for (Table table : tables) {
String entityName = (String) ClassUtil.invokeMethod(tableName2EntityName, table.getName());
if (newEntityNames.get(entityName) != null) {
entityName = newEntityNames.get(entityName);
}
Method columnName2PropName = entityColumnName2PropName.get(entityName);
if (columnName2PropName == null) {
for (String key : entityColumnName2PropName.keySet()) {
if (entityName.matches(key)) {
columnName2PropName = entityColumnName2PropName.get(key);
}
}
}
if (columnName2PropName == null) {
columnName2PropName = ClassUtil.getDeclaredMethod(CodeGenerator.class, COLUMN_NAME2PROP_NAME, String.class);
}
Map newPropNames = newEntityPropNames.get(entityName);
if (newPropNames == null) {
for (String key : newEntityPropNames.keySet()) {
if (entityName.matches(key)) {
newPropNames = newEntityPropNames.get(key);
}
}
}
Set excludedPropNames = excludedeEntityPropNames.get(entityName);
if (excludedPropNames == null) {
for (String key : excludedeEntityPropNames.keySet()) {
if (entityName.matches(key)) {
excludedPropNames = excludedeEntityPropNames.get(key);
}
}
}
Element importedEntityEelement = getEntityEleByName(entityName, existedEntityEleList);
EntityDefinition entityDef = new SQLEntityDefinition(entityName, table, columnName2PropName);
entityDefinition2Node(entityDef, entityDefNode, newPropNames, excludedPropNames, importedEntityEelement);
entityNameList.add(entityName.toUpperCase());
}
for (String entityEleName : existedEntityEleList.keySet()) {
if (!entityNameList.contains(entityEleName.toUpperCase())) {
Node importedNode = doc.importNode(existedEntityEleList.get(entityEleName), true);
entityDefNode.appendChild(importedNode);
}
}
Comment comment = doc.createComment("Generated by Abacus");
doc.appendChild(comment);
doc.appendChild(entityDefNode);
XMLUtil.transform(doc, entityDefinitionXml);
}
static void setAttributes(final Element element, final Map attrs) {
if (attrs != null) {
for (String attrName : attrs.keySet()) {
element.setAttribute(attrName, attrs.get(attrName));
}
}
}
/**
* @param entityDef
* @param node
* @param newPropNames
* @param excludedPropNames
* @param importedEntityEelement
*/
static void entityDefinition2Node(final EntityDefinition entityDef, final Element node, Map newPropNames, Set excludedPropNames,
final Element importedEntityEelement) {
Document doc = node.getOwnerDocument();
Element entityNode = null;
if (newPropNames == null) {
newPropNames = new LinkedHashMap<>();
}
if (excludedPropNames == null) {
excludedPropNames = new LinkedHashSet<>();
} else {
Set tempList = new LinkedHashSet<>(excludedPropNames);
for (String propName : excludedPropNames) {
tempList.add(propName.toUpperCase());
}
excludedPropNames = tempList;
}
if (EntityEle.ENTITY.equals(node.getTagName())) {
entityNode = node;
} else {
entityNode = doc.createElement(EntityEle.ENTITY);
node.appendChild(doc.createComment(entityDef.getName()));
node.appendChild(entityNode);
}
for (Map.Entry entry : entityDef.getAttributes().entrySet()) {
entityNode.setAttribute(entry.getKey(), entry.getValue());
}
if (entityDef.getIdPropertyList().size() > 0) {
String idAttr = "";
for (Property idProp : entityDef.getIdPropertyList()) {
if (excludedPropNames.contains(idProp.getName()) || excludedPropNames.contains(idProp.getName().toUpperCase())) {
continue;
}
if (idAttr.length() > 0) {
idAttr += ", ";
}
idAttr += idProp.getName();
}
if (N.notNullOrEmpty(idAttr)) {
entityNode.setAttribute(EntityEle.ID, idAttr);
} else {
entityNode.removeAttribute(EntityEle.ID);
}
}
Element propsNode = doc.createElement(EntityEle.PROPERTIES);
Collection props = entityDef.getPropertyList();
for (Property prop : props) {
String propName = prop.getName();
if (excludedPropNames.contains(propName) || excludedPropNames.contains(propName.toUpperCase())) {
continue;
}
if ((newPropNames.get(propName) != null)) {
propName = newPropNames.get(propName);
}
Element propNode = null;
if (prop.isList()) {
propNode = doc.createElement(PropertyEle.LIST);
} else if (prop.isSet()) {
propNode = doc.createElement(PropertyEle.SET);
} else {
propNode = doc.createElement(PropertyEle.PROPERTY);
}
for (Map.Entry entry : prop.getAttributes().entrySet()) {
propNode.setAttribute(entry.getKey(), entry.getValue());
}
propNode.setAttribute(PropertyEle.NAME, propName);
propNode.setAttribute(PropertyEle.TYPE, prop.getType().name());
propNode.removeAttribute(PropertyEle.COLLECTION);
propsNode.appendChild(propNode);
}
entityNode.appendChild(propsNode);
if (importedEntityEelement != null) {
NamedNodeMap attrs = importedEntityEelement.getAttributes();
for (int i = 0; i < attrs.getLength(); i++) {
Node attr = attrs.item(i);
entityNode.setAttribute(attr.getNodeName(), attr.getNodeValue());
}
try {
List propElementList = XMLUtil.getElementsByTagName(propsNode, PropertyEle.PROPERTY);
NodeList nodeList = importedEntityEelement.getChildNodes();
for (int i = 0; i < nodeList.getLength(); i++) {
if (nodeList.item(i) instanceof Element) {
Element ele = (Element) nodeList.item(i);
if (EntityEle.PROPERTIES.equals(ele.getTagName())) {
List importedPropEleList = new ArrayList<>();
NodeList propNodeList = ele.getChildNodes();
for (int j = 0; j < propNodeList.getLength(); j++) {
if (propNodeList.item(j) instanceof Element) {
importedPropEleList.add((Element) propNodeList.item(j));
}
}
for (Element importedPropEle : importedPropEleList) {
boolean isExistedProp = false;
if (importedPropEle.getTagName().equals(PropertyEle.PROPERTY)) {
String columnName = importedPropEle.getAttribute(PropertyEle.COLUMN);
for (int k = 0; k < propElementList.size(); k++) {
Element propEle = (propElementList.get(k));
if (columnName.equalsIgnoreCase(propEle.getAttribute(PropertyEle.COLUMN))) {
NamedNodeMap nnm = importedPropEle.getAttributes();
for (int j = 0; j < nnm.getLength(); j++) {
propEle.setAttribute(nnm.item(j).getNodeName(), nnm.item(j).getNodeValue());
}
isExistedProp = true;
break;
}
}
}
if (!isExistedProp) {
Node importedNode = doc.importNode(importedPropEle, true);
propsNode.appendChild(importedNode);
}
}
} else {
// objectNode.getOwnerDocument().adoptNode(addedEle);
Node importedNode = doc.importNode(ele, true);
entityNode.appendChild(importedNode);
}
}
}
} catch (Exception e) {
throw new AbacusException(e);
}
}
}
private static Map getEntityElementList(final Document doc) {
Map result = new LinkedHashMap<>();
if (doc != null) {
List entityDefElementList = XMLUtil.getElementsByTagName(doc.getDocumentElement(), EntityDefEle.ENTITY_DEF);
List entityElementList = null;
if (entityDefElementList.size() > 0) {
entityElementList = XMLUtil.getElementsByTagName((entityDefElementList.get(0)), EntityEle.ENTITY);
} else {
entityElementList = XMLUtil.getElementsByTagName(doc.getDocumentElement(), EntityEle.ENTITY);
}
for (int i = 0; i < entityElementList.size(); i++) {
String entityName = XMLUtil.getAttribute(entityElementList.get(i), EntityEle.NAME);
result.put(entityName, entityElementList.get(i));
}
}
return result;
}
private static Element getEntityEleByName(final String entityName, final Map entityEleList) {
Element importedElement = null;
for (String entityEleName : entityEleList.keySet()) {
if (entityName.equalsIgnoreCase(entityEleName)) {
importedElement = entityEleList.get(entityEleName);
break;
}
}
return importedElement;
}
protected static String getSimplePropNameTableClassName(final String className) {
String simpleClassName = className;
int index = className.lastIndexOf(WD._PERIOD);
if (index > -1) {
simpleClassName = className.substring(index + 1);
}
return simpleClassName;
}
public static void entityDefinitionXml2Class(final String domainName, final File entityDefinitionXml, final String srcPath, final EntityMode entityMode) {
entityDefinitionXml2Class(domainName, entityDefinitionXml, srcPath, entityMode, null, null, true);
}
public static void entityDefinitionXml2Class(final String domainName, final File entityDefinitionXml, final String srcPath, final EntityMode entityMode,
final Method propName2VarName, final Method propName2MethodName, final boolean fluentSetMethod) {
entityDefinitionXml2Class(domainName, entityDefinitionXml, srcPath, entityMode, propName2VarName, propName2MethodName, fluentSetMethod, null);
}
public static void entityDefinitionXml2Class(final String domainName, final File entityDefinitionXml, final String srcPath, final EntityMode entityMode,
final Method propName2VarName, final Method propName2MethodName, final boolean fluentSetMethod, final Class> extendedClass,
final Class>... implementedInterfaces) {
entityDefinitionXml2Class(domainName, entityDefinitionXml, srcPath, entityMode, propName2VarName, propName2MethodName, fluentSetMethod, extendedClass,
N.asList(implementedInterfaces), true, true);
}
public static void entityDefinitionXml2Class(final String domainName, final File entityDefinitionXml, final String srcPath, final EntityMode entityMode,
final Method propName2VarName, final Method propName2MethodName, final boolean fluentSetMethod, final Class> extendedClass,
final List> implementedInterfaces, final boolean generateHashEqualsMethod, final boolean generateToStringMethod) {
entityDefinitionXml2Class(domainName, entityDefinitionXml, srcPath, entityMode, propName2VarName, propName2MethodName, fluentSetMethod, extendedClass,
implementedInterfaces, generateHashEqualsMethod, generateToStringMethod, generateHashEqualsMethod, generateToStringMethod, Objects.class);
}
public static void entityDefinitionXml2Class(final String domainName, final File entityDefinitionXml, final String srcPath, final EntityMode entityMode,
final Method propName2VarName, final Method propName2MethodName, final boolean fluentSetMethod, final Class> extendedClass,
final List> implementedInterfaces, final boolean generateHashEqualsMethod, final boolean generateToStringMethod,
final boolean hashEqualsWithParentProperties, final boolean toStringWithParentProperties, final Class> utilClassForHashEqualsToString) {
final EntityDefinitionFactory entityDefinitionFactory = SQLEntityDefinitionFactory.newInstance(domainName, entityDefinitionXml);
Map> entityExtendedClasses = null;
if (extendedClass != null) {
entityExtendedClasses = new LinkedHashMap<>();
for (EntityDefinition entityDef : entityDefinitionFactory.getDefinitionList()) {
entityExtendedClasses.put(entityDef.getName(), extendedClass);
}
}
Map>> entityImplementedInterfaces = null;
if (N.notNullOrEmpty(implementedInterfaces)) {
entityImplementedInterfaces = new LinkedHashMap<>();
for (EntityDefinition entityDef : entityDefinitionFactory.getDefinitionList()) {
entityImplementedInterfaces.put(entityDef.getName(), implementedInterfaces);
}
}
entityDefinitionXml2Class(domainName, entityDefinitionXml, srcPath, entityMode, propName2VarName, propName2MethodName, fluentSetMethod,
entityExtendedClasses, entityImplementedInterfaces, generateHashEqualsMethod, generateToStringMethod, hashEqualsWithParentProperties,
toStringWithParentProperties, utilClassForHashEqualsToString);
}
public static void entityDefinitionXml2Class(final String domainName, final File entityDefinitionXml, final String srcPath, final EntityMode entityMode,
final Method propName2VarName, final Method propName2MethodName, final boolean fluentSetMethod, final Map> entityExtendedClasses,
final Map>> entityImplementedInterfaces) {
entityDefinitionXml2Class(domainName, entityDefinitionXml, srcPath, entityMode, propName2VarName, propName2MethodName, fluentSetMethod,
entityExtendedClasses, entityImplementedInterfaces, true, true);
}
public static void entityDefinitionXml2Class(final String domainName, final File entityDefinitionXml, final String srcPath, final EntityMode entityMode,
final Method propName2VarName, final Method propName2MethodName, final boolean fluentSetMethod, final Map> entityExtendedClasses,
final Map>> entityImplementedInterfaces, final boolean generateHashEqualsMethod, final boolean generateToStringMethod) {
entityDefinitionXml2Class(domainName, entityDefinitionXml, srcPath, entityMode, propName2VarName, propName2MethodName, fluentSetMethod,
entityExtendedClasses, entityImplementedInterfaces, generateHashEqualsMethod, generateToStringMethod, generateHashEqualsMethod,
generateToStringMethod, Objects.class);
}
/**
*
* @param domainName
* @param entityDefinitionXml
* @param srcPath
* @param entityMode
* @param propName2VarName
* @param propName2MethodName
* @param fluentSetMethod true to generate the setter methods with returning this to support fluent setter. For example: account.setFirstName("fn").setLastName("ln")...
* @param entityExtendedClasses
* @param entityImplementedInterfaces
* @param generateHashEqualsMethod
* @param generateToStringMethod
* @param hashEqualsWithParentProperties
* @param toStringWithParentProperties
* @param utilClassForHashEqualsToString is Objects.class by default. It can also be N.class or any classes else which provide the {@code hashCode/equals/toString} method.
* Or specify CodeGenerator._N or your own utility class to generate entity classes which not dependent on AbacusUtil.jar for Methods {@code hashCode/equals/toString}.
*/
public static void entityDefinitionXml2Class(final String domainName, final File entityDefinitionXml, final String srcPath, final EntityMode entityMode,
Method propName2VarName, Method propName2MethodName, final boolean fluentSetMethod, Map> entityExtendedClasses,
Map>> entityImplementedInterfaces, final boolean generateHashEqualsMethod, final boolean generateToStringMethod,
final boolean hashEqualsWithParentProperties, final boolean toStringWithParentProperties, final Class> utilClassForHashEqualsToString) {
final EntityDefinitionFactory entityDefinitionFactory = SQLEntityDefinitionFactory.newInstance(domainName, entityDefinitionXml);
final String pkgName = entityDefinitionFactory.getAttribute(EntityDefEle.PACKAGE);
if ((pkgName == null) || (pkgName.length() == 0)) {
throw new AbacusException("the package attribute in 'entityDef' element can't be null or empty");
}
//
// if (generatePropNameTable && ((domainName == null) || (domainName.length() == 0))) {
// throw new AbacusException("the domain attribute in 'entityDef' element can't be null or empty");
// }
if (entityMode == null) {
throw new AbacusException("entityMode can't be null");
}
if (propName2VarName == null) {
propName2VarName = ClassUtil.getDeclaredMethod(CodeGenerator.class, PROP_NAME2VAR_NAME, String.class);
}
if (propName2MethodName == null) {
propName2MethodName = ClassUtil.getDeclaredMethod(CodeGenerator.class, PROP_NAME2METHOD_NAME, String.class);
}
if (entityExtendedClasses == null) {
entityExtendedClasses = new LinkedHashMap<>();
}
if (entityImplementedInterfaces == null) {
entityImplementedInterfaces = new LinkedHashMap<>();
}
final Class> utilClass = utilClassForHashEqualsToString == null ? Objects.class : utilClassForHashEqualsToString;
final String classFilePath = makePackageFolder(srcPath, pkgName);
if (_N.equals(utilClass)) {
File utilClassFile = new File(classFilePath + ClassUtil.getSimpleClassName(_N) + POSTFIX_OF_JAVA_FILE);
if (!utilClassFile.exists()) {
String sourceCode = _N_STRING.replaceFirst("package com.landawn.abacus.util;", N.isNullOrEmpty(pkgName) ? "" : "package " + pkgName + ";");
IOUtil.write(utilClassFile, sourceCode);
}
}
String propNameTableClass = null;
if (entityMode != EntityMode.POJO) {
entityDefinitionXml2PropNameTable(domainName, entityDefinitionXml, srcPath, propName2VarName, utilClass.equals(Objects.class) ? _N : utilClass);
propNameTableClass = getPropNameTableClassName(entityDefinitionFactory);
}
final ExecutorService executorService = Executors.newFixedThreadPool(8);
final AtomicInteger activeThreadNum = new AtomicInteger();
for (EntityDefinition entityDef : entityDefinitionFactory.getDefinitionList()) {
if (entityDef.isSliceEntity()) {
continue;
}
final EntityDefinition entityDef2 = entityDef;
final String propNameTableClass2 = propNameTableClass;
final Method propName2VarName2 = propName2VarName;
final Method propName2MethodName2 = propName2MethodName;
final File classFile = new File(classFilePath + entityDef.getName() + POSTFIX_OF_JAVA_FILE);
final Class> extendedClass = entityExtendedClasses.get(entityDef.getName());
final List> implementedInterfaces = entityImplementedInterfaces.get(entityDef.getName());
activeThreadNum.incrementAndGet();
executorService.execute(new Runnable() {
@Override
public void run() {
try {
entityDefinition2Class(entityDef2, classFile, entityMode, propNameTableClass2, propName2VarName2, propName2MethodName2, extendedClass,
implementedInterfaces, fluentSetMethod, generateHashEqualsMethod, generateToStringMethod, hashEqualsWithParentProperties,
toStringWithParentProperties, utilClass);
} finally {
activeThreadNum.decrementAndGet();
}
}
});
}
while (activeThreadNum.get() > 0) {
N.sleep(1);
}
}
private static String getPropNameTableClassName(final EntityDefinitionFactory entityDefinitionFactory) {
String propNameTableClass = POSTFIX_OF_PROP_NAME_LIST;
String domainName = entityDefinitionFactory.domainName();
if (N.notNullOrEmpty(domainName)) {
propNameTableClass = N.capitalize(domainName) + propNameTableClass;
}
String pkgName = entityDefinitionFactory.getAttribute(EntityDefEle.PACKAGE);
if (pkgName != null) {
propNameTableClass = pkgName + '.' + propNameTableClass;
}
return propNameTableClass;
}
static void entityDefinition2Class(final EntityDefinition entityDef, final File classFile, final EntityMode entityMode, final String propNameTableClass,
final Method propName2VarName, final Method propName2MethodName, Class> extendedClass, List> implementedInterfaces,
final boolean fluentSetMethod, boolean generateHashEqualsMethod, boolean generateToStringMethod, boolean hashEqualsWithParentProperties,
boolean toStringWithParentProperties, final Class> utilClass) {
final String pkgName = getPackageName(entityDef);
String attr = entityDef.getAttribute("extends");
if (N.notNullOrEmpty(attr)) {
String className = attr;
try {
try {
ClassUtil.forClass(className);
} catch (Throwable e) {
className = attr.indexOf('.') > 0 ? attr : pkgName + "." + attr;
}
extendedClass = ClassUtil.forClass(className);
} catch (Throwable e) {
// ignore for second time run.
if (logger.isWarnEnabled()) {
logger.warn("No class found by name: " + className + ". Please run it again after the generated codes are compiled");
}
}
}
attr = entityDef.getAttribute("implements");
if (N.notNullOrEmpty(attr)) {
implementedInterfaces = new ArrayList<>();
final List strList = Splitter.with(",").trim(true).split(attr);
for (String str : strList) {
String className = str;
try {
try {
ClassUtil.forClass(className);
} catch (Throwable e) {
className = str.indexOf('.') > 0 ? str : pkgName + "." + str;
}
implementedInterfaces.add(ClassUtil.forClass(className));
} catch (Throwable e) {
// ignore for second time run.
if (logger.isWarnEnabled()) {
logger.warn("No class found by name: " + className + ". Please run it again after the generated codes are compiled");
}
}
}
}
if (implementedInterfaces == null) {
implementedInterfaces = new ArrayList<>();
}
String generateHashEqualsMethodAttr = entityDef.getAttribute("generateHashEqualsMethod");
if (N.notNullOrEmpty(generateHashEqualsMethodAttr)) {
generateHashEqualsMethod = Boolean.valueOf(generateHashEqualsMethodAttr);
}
String generateToStringMethodAttr = entityDef.getAttribute("generateToStringMethod");
if (N.notNullOrEmpty(generateToStringMethodAttr)) {
generateToStringMethod = Boolean.valueOf(generateToStringMethodAttr);
}
String hashEqualsWithParentPropertiesAttr = entityDef.getAttribute("hashEqualsWithParentProperties");
if (N.notNullOrEmpty(hashEqualsWithParentPropertiesAttr)) {
hashEqualsWithParentProperties = Boolean.valueOf(hashEqualsWithParentPropertiesAttr);
}
String toStringWithParentPropertiesAttr = entityDef.getAttribute("toStringWithParentProperties");
if (N.notNullOrEmpty(toStringWithParentPropertiesAttr)) {
toStringWithParentProperties = Boolean.valueOf(toStringWithParentPropertiesAttr);
}
Writer fileWrite = null;
try {
if (EntityMode.POJO == entityMode || EntityMode.POJO_WITH_PROP_NAME_TABLE == entityMode) {
// do something.
} else if (EntityMode.EXTEND_DIRTY_MARKER == entityMode) {
if (extendedClass == null) {
extendedClass = AbstractDirtyMarker.class;
} else {
if (!AbstractDirtyMarker.class.isAssignableFrom(extendedClass)) {
throw new AbacusException(
"the class: " + extendedClass.getCanonicalName() + " must extend " + AbstractDirtyMarker.class.getCanonicalName());
}
}
} else if (EntityMode.IMPL_DIRTY_MARKER == entityMode) {
if (extendedClass == null) {
extendedClass = DirtyMarkerImpl.class;
}
if (implementedInterfaces.size() == 0) {
implementedInterfaces.add(DirtyMarker.class);
}
}
Map> annotationLinesMapper = new LinkedHashMap<>();
Set> annotationImportClasses = new LinkedHashSet<>();
if (classFile.exists()) {
List lines = IOUtil.readLines(classFile);
List annotationLines = null;
for (String line : lines) {
if (line.startsWith("import")) {
String str = line.trim().substring(6);
str = str.trim();
str = str.substring(0, str.length() - 1);
try {
Class> cls = ClassUtil.forClass(str);
if (cls.isAnnotation()) {
annotationImportClasses.add(cls);
}
} catch (Exception e) {
// ignore.
}
} else if (N.notNullOrEmpty(line) && line.length() > 4) {
boolean isAnnotationLine = false;
for (int i = 0, len = line.length(); i < len; i++) {
char ch = line.charAt(i);
if (ch == ' ' || ch == '\t') {
continue;
}
if (ch == '@') {
isAnnotationLine = true;
}
break;
}
if (isAnnotationLine) {
if (annotationLines == null) {
annotationLines = new ArrayList<>();
}
annotationLines.add(line);
} else if (N.notNullOrEmpty(annotationLines) && line.trim().length() > 0) {
annotationLinesMapper.put(line, annotationLines);
annotationLines = null;
}
}
}
} else {
classFile.createNewFile();
}
fileWrite = newFileWriter(classFile);
writeFileHead(fileWrite);
writePackageName(pkgName, fileWrite);
final Map> importedClasses = writeImport(entityDef, pkgName, propNameTableClass, entityMode, extendedClass, implementedInterfaces,
fileWrite, generateHashEqualsMethod, generateToStringMethod, utilClass, annotationImportClasses);
fileWrite.write(IOUtil.LINE_SEPARATOR);
fileWrite.write(IOUtil.LINE_SEPARATOR);
writeClassComment(fileWrite);
writeClass(entityDef, pkgName, propNameTableClass, propName2VarName, propName2MethodName, entityMode, extendedClass, implementedInterfaces, "",
fileWrite, generateHashEqualsMethod, generateToStringMethod, hashEqualsWithParentProperties, toStringWithParentProperties, utilClass,
fluentSetMethod, importedClasses);
fileWrite.flush();
if (N.notNullOrEmpty(annotationLinesMapper)) {
IOUtil.close(fileWrite);
List lines = IOUtil.readLines(classFile);
List newLines = new ArrayList<>(lines.size() + 64);
for (String line : lines) {
List annotationLines = annotationLinesMapper.get(line);
if (N.notNullOrEmpty(annotationLines)) {
if (annotationLines.size() == 2) {
N.println(annotationLines);
}
for (int len = newLines.size(), i = len - 1; i > N.max(0, len - 5); i--) {
String str = newLines.get(i);
if (str.indexOf('@') > 0) {
if (annotationLines.size() > 0 && !annotationLines.remove(str)) {
String annoLine = annotationLines.iterator().next();
String prefixSpaces = annoLine.substring(0, annoLine.indexOf('@'));
str = prefixSpaces + str.trim();
annotationLines.remove(str);
}
} else if (str.trim().length() > 0) {
break;
}
}
if (N.notNullOrEmpty(annotationLines)) {
// String prevLine = newLines.get(newLines.size() - 1).trim();
//
// if (prevLine.length() > 0 && (prevLine.charAt(0) != '/' && prevLine.charAt(0) != '*')) {
// newLines.add(N.EMPTY_STRING);
// }
newLines.addAll(annotationLines);
}
}
newLines.add(line);
}
fileWrite = newFileWriter(classFile);
IOUtil.writeLines(fileWrite, newLines);
fileWrite.flush();
}
} catch (Exception e) {
throw new AbacusException(e);
} finally {
IOUtil.close(fileWrite);
}
}
public static void entityDefinitionXml2PropNameTable(final String domainName, final File entityDefinitionXml, final String srcPath) {
entityDefinitionXml2PropNameTable(domainName, entityDefinitionXml, srcPath, null, _N);
}
/**
* @param domainName
* @param entityDefinitionXml
* @param srcPath
* @param propName2VarName
* @param utilClass specify CodeGenerator._N or your own utility class to generate entity classes which not dependent on AbacusUtil.java
*/
public static void entityDefinitionXml2PropNameTable(String domainName, final File entityDefinitionXml, final String srcPath, Method propName2VarName,
Class> utilClass) {
if (propName2VarName == null) {
propName2VarName = ClassUtil.getDeclaredMethod(CodeGenerator.class, PROP_NAME2VAR_NAME, String.class);
}
if (utilClass == null) {
utilClass = _N;
}
domainName = N.nullToEmpty(domainName);
EntityDefinitionFactory entityDefinitionFactory = SQLEntityDefinitionFactory.newInstance(domainName, entityDefinitionXml);
String pkgName = entityDefinitionFactory.getAttribute(EntityDefEle.PACKAGE);
String classFilePath = makePackageFolder(srcPath, pkgName);
// if (utilClass.equals(_N)) {
// File utilClassFile = new File(classFilePath + ClassUtil.getSimpleClassName(_N) + POSTFIX_OF_JAVA_FILE);
// if (!utilClassFile.exists()) {
// String sourceCode = _N_STRING.replaceFirst("com.landawn.abacus.util", pkgName);
// IOUtil.write(utilClassFile, sourceCode);
// }
// }
String propNameTableClassName = getSimplePropNameTableClassName(getPropNameTableClassName(entityDefinitionFactory));
File propNameDefClassFile = new File(classFilePath + propNameTableClassName + POSTFIX_OF_JAVA_FILE);
entityDefinition2PropNameTable(entityDefinitionFactory, propNameDefClassFile, pkgName, propName2VarName, utilClass);
}
static void entityDefinition2PropNameTable(final EntityDefinitionFactory entityDefinitionFactory, final File propNameDefClassFile, final String pkgName,
final Method propName2VarName, final Class> utilClass) {
if (propNameDefClassFile.exists()) {
propNameDefClassFile.delete();
}
Writer fileWrite = null;
try {
propNameDefClassFile.createNewFile();
fileWrite = newFileWriter(propNameDefClassFile);
writeFileHead(fileWrite);
writePackageName(pkgName, fileWrite);
fileWrite.write(IOUtil.LINE_SEPARATOR);
fileWrite.write("import " + Arrays.class.getCanonicalName() + ";" + IOUtil.LINE_SEPARATOR);
fileWrite.write("import " + Collections.class.getCanonicalName() + ";" + IOUtil.LINE_SEPARATOR);
fileWrite.write("import " + List.class.getCanonicalName() + ";" + IOUtil.LINE_SEPARATOR);
// if (utilClass.equals(N.class)) {
// fileWrite.write("import " + Map.class.getCanonicalName() + ";" + N.LINE_SEPARATOR);
// fileWrite.write("import " + BiMap.class.getCanonicalName() + ";" + N.LINE_SEPARATOR);
// }
// fileWrite.write(N.LINE_SEPARATOR);
// String utilClassName = ClassUtil.getCanonicalClassName(utilClass);
// if (pkgName.equals(utilClassName.substring(0, utilClassName.lastIndexOf('.'))) || utilClass.equals(_N)) {
// // ignore
// } else {
// fileWrite.write("import " + ClassUtil.getCanonicalClassName(utilClass) + ";" + N.LINE_SEPARATOR);
// fileWrite.write(N.LINE_SEPARATOR);
// }
writeClassComment(fileWrite);
String clazzName = propNameDefClassFile.getName().substring(0, propNameDefClassFile.getName().indexOf(_PERIOD));
fileWrite.write("public interface " + clazzName + " {");
String headSpace = "";
String domainName = entityDefinitionFactory.domainName();
writeDomainPropNameClass(domainName, fileWrite, headSpace);
EntityDefinition[] entityDefinitions = entityDefinitionFactory.getDefinitionList()
.toArray(new EntityDefinition[entityDefinitionFactory.getDefinitionList().size()]);
writePropNameTable(entityDefinitions, propName2VarName, headSpace, fileWrite, utilClass);
// -------- write global domain property name.
Map allPropNamesMap = new LinkedHashMap<>();
Map allPropColumnNameMap = new LinkedHashMap<>();
for (EntityDefinition entityDef : entityDefinitions) {
if (entityDef.isSliceEntity()) {
continue;
}
for (Property prop : entityDef.getPropertyList()) {
allPropNamesMap.put(prop.getName().toUpperCase(), prop.getName());
if (prop.getColumnType() == ColumnType.TABLE_COLUMN) {
allPropColumnNameMap.put(prop.getName().toUpperCase(), prop.getColumnName());
}
}
}
List keys = new ArrayList<>(allPropNamesMap.keySet());
N.sort(keys);
for (String key : keys) {
String propName = allPropNamesMap.get(key);
String propVarName = ClassUtil.invokeMethod(propName2VarName, propName);
fileWrite.write(IOUtil.LINE_SEPARATOR);
fileWrite.write(" public static final String " + propVarName + " = \"" + propName + "\".intern();");
fileWrite.write(IOUtil.LINE_SEPARATOR);
}
// if (utilClass.equals(N.class)) {
// fileWrite.write(N.LINE_SEPARATOR);
// fileWrite.write(" /**" + N.LINE_SEPARATOR);
// fileWrite.write(" * Mapping of property name to column name " + N.LINE_SEPARATOR);
// fileWrite.write(" */" + N.LINE_SEPARATOR);
// fileWrite.append(headSpace + " @SuppressWarnings(\"rawtypes\")" + N.LINE_SEPARATOR);
// fileWrite.write(" public static final BiMap " + PROP_COLUMN_MAP + " = " + N.getSimpleClassName(utilClass)
// + ".newImmutableBiMapForInterface((Map) " + N.getSimpleClassName(utilClass) + ".asLinkedHashMap(");
//
// int i = 0;
// for (String key : keys) {
// String propName = allPropNamesMap.get(key);
// String propVarName = N.invokeMethod(propName2VarName, propName);
// String columnName = allPropColumnNameMap.get(key);
//
// if (N.isNullOrEmpty(columnName)) {
// continue;
// }
//
// if (i++ > 0) {
// fileWrite.write(", ");
// }
//
// fileWrite.write(propVarName + ", \"" + columnName + "\".intern()");
// }
//
// fileWrite.write("));" + N.LINE_SEPARATOR);
// }
fileWrite.write("}" + IOUtil.LINE_SEPARATOR);
fileWrite.flush();
} catch (IOException e) {
throw new UncheckedIOException(e);
} finally {
IOUtil.close(fileWrite);
}
}
private static void writePropNameTable(final EntityDefinition[] entityDefs, final Method propName2VarName, final String headSpace, final Writer fileWrite,
final Class> utilClass) throws IOException {
for (EntityDefinition entityDef : entityDefs) {
if (entityDef.isSliceEntity()) {
continue;
}
fileWrite.write(IOUtil.LINE_SEPARATOR);
fileWrite.write(headSpace + " public static interface " + entityDef.getName() + POSTFIX_OF_PROP_NAME_LIST + " {");
writePropNameField(entityDef, propName2VarName, headSpace + " ", fileWrite, utilClass);
fileWrite.write(headSpace + " }" + IOUtil.LINE_SEPARATOR);
// write slice entities
for (EntityDefinition hed : entityDef.getSliceEntityList()) {
fileWrite.write(IOUtil.LINE_SEPARATOR);
fileWrite.write(headSpace + " public static interface " + hed.getName() + POSTFIX_OF_PROP_NAME_LIST + " {");
fileWrite.write(IOUtil.LINE_SEPARATOR);
fileWrite.write(headSpace + " /**" + IOUtil.LINE_SEPARATOR);
fileWrite.write(headSpace + " * Name of \"" + hed.getName() + "\" entity. " + IOUtil.LINE_SEPARATOR);
fileWrite.write(headSpace + " */" + IOUtil.LINE_SEPARATOR);
fileWrite.write(headSpace + " public static final String " + ENTITY_NAME_VAR + " = \"" + hed.getName() + "\";" + IOUtil.LINE_SEPARATOR);
fileWrite.write(headSpace + " }" + IOUtil.LINE_SEPARATOR);
}
}
}
/**
*
* @param entityDef
* @param propName2VarName
* @param headSpace
* @param fileWrite
* @throws IOException
*/
private static void writePropNameField(final EntityDefinition entityDef, final Method propName2VarName, final String headSpace, final Writer fileWrite,
final Class> utilClass) throws IOException {
final StringBuilder sb = ObjectFactory.createStringBuilder();
sb.append(IOUtil.LINE_SEPARATOR);
sb.append(headSpace + " /**" + IOUtil.LINE_SEPARATOR);
sb.append(headSpace + " * Name of \"" + entityDef.getName() + "\" entity. " + IOUtil.LINE_SEPARATOR);
sb.append(headSpace + " */" + IOUtil.LINE_SEPARATOR);
sb.append(headSpace + " public static final String " + ENTITY_NAME_VAR + " = \"" + entityDef.getName() + "\".intern();" + IOUtil.LINE_SEPARATOR);
String _propNameList = "";
String _columnNameList = "";
// String _propNameMap = "";
// String _propColumnNameMap = "";
// String _columnNameMap = "";
for (Property prop : entityDef.getPropertyList()) {
String propVarName = ClassUtil.invokeMethod(propName2VarName, prop.getName());
sb.append(IOUtil.LINE_SEPARATOR);
sb.append(headSpace + " /**" + IOUtil.LINE_SEPARATOR);
sb.append(headSpace + " * Name of \"" + prop.getName() + "\" property. " + IOUtil.LINE_SEPARATOR);
sb.append(headSpace + " * type: " + prop.getType().name() + ". " + IOUtil.LINE_SEPARATOR);
sb.append(headSpace + " * column: \"" + prop.getAttribute(PropertyEle.COLUMN) + "\". " + IOUtil.LINE_SEPARATOR);
sb.append(headSpace + " */" + IOUtil.LINE_SEPARATOR);
// sb.append(headSpace + " public static final String " + propVarName + " = \"" + prop.getName() + "\".intern();" + N.LINE_SEPARATOR);
// sb.append(headSpace + " public static final String _" + propVarName + " = (_ + \"." + prop.getName() + "\").intern();" + N.LINE_SEPARATOR);
sb.append(headSpace + " public static final String " + propVarName + " = (" + ENTITY_NAME_VAR + " + \"." + prop.getName() + "\").intern();"
+ IOUtil.LINE_SEPARATOR);
_propNameList += (", " + propVarName);
// _propNameMap += (", " + propVarName + ", \"" + prop.getName() + "\".intern()");
if (prop.getColumnType() == ColumnType.TABLE_COLUMN) {
String columnName = "\"" + entityDef.getTableName() + "." + prop.getColumnName() + "\".intern()";
_columnNameList += (", " + columnName + "");
// _propColumnNameMap += (", " + propVarName + ", " + columnName);
// _columnNameMap += (", " + columnName + ", \"" + prop.getColumnName() + "\".intern()");
}
}
sb.append(IOUtil.LINE_SEPARATOR);
sb.append(headSpace + " /**" + IOUtil.LINE_SEPARATOR);
sb.append(headSpace + " * Immutable property name list" + IOUtil.LINE_SEPARATOR);
sb.append(headSpace + " */" + IOUtil.LINE_SEPARATOR);
sb.append(headSpace + " public static final List " + PROP_NAME_LIST + " = Collections.unmodifiableList(Arrays.asList("
+ _propNameList.substring(2) + "));" + IOUtil.LINE_SEPARATOR);
// if (utilClass.equals(N.class)) {
// sb.append(N.LINE_SEPARATOR);
// sb.append(headSpace + " /**" + N.LINE_SEPARATOR);
// sb.append(headSpace + " * Immutable property name to entityName.propName mapper" + N.LINE_SEPARATOR);
// sb.append(headSpace + " */" + N.LINE_SEPARATOR);
// sb.append(headSpace + " @SuppressWarnings(\"rawtypes\")" + N.LINE_SEPARATOR);
// sb.append(headSpace + " public static final BiMap " + PROP_NAME_MAP + " = " + N.getSimpleClassName(utilClass)
// + ".newImmutableBiMapForInterface((Map)" + N.getSimpleClassName(utilClass) + ".asLinkedHashMap(" + _propNameMap.substring(2) + "));"
// + N.LINE_SEPARATOR);
//
// sb.append(N.LINE_SEPARATOR);
// sb.append(headSpace + " /**" + N.LINE_SEPARATOR);
// sb.append(headSpace + " * Immutable property name to column name mapper" + N.LINE_SEPARATOR);
// sb.append(headSpace + " */" + N.LINE_SEPARATOR);
// sb.append(headSpace + " @SuppressWarnings(\"rawtypes\")" + N.LINE_SEPARATOR);
// sb.append(headSpace + " public static final BiMap " + PROP_COLUMN_MAP + " = " + N.getSimpleClassName(utilClass)
// + ".newImmutableBiMapForInterface((Map)" + N.getSimpleClassName(utilClass) + ".asLinkedHashMap(" + _propColumnNameMap.substring(2) + "));"
// + N.LINE_SEPARATOR);
// }
sb.append(IOUtil.LINE_SEPARATOR);
sb.append(headSpace + " /**" + IOUtil.LINE_SEPARATOR);
sb.append(headSpace + " * Immutable column name list" + IOUtil.LINE_SEPARATOR);
sb.append(headSpace + " */" + IOUtil.LINE_SEPARATOR);
sb.append(headSpace + " public static final List " + COLUMN_NAME_LIST + " = Collections.unmodifiableList(Arrays.asList("
+ _columnNameList.substring(2) + "));" + IOUtil.LINE_SEPARATOR);
// if (utilClass.equals(N.class)) {
// sb.append(N.LINE_SEPARATOR);
// sb.append(headSpace + " /**" + N.LINE_SEPARATOR);
// sb.append(headSpace + " * Immutable column name to tableName.columnName mapper" + N.LINE_SEPARATOR);
// sb.append(headSpace + " */" + N.LINE_SEPARATOR);
// sb.append(headSpace + " @SuppressWarnings(\"rawtypes\")" + N.LINE_SEPARATOR);
// sb.append(headSpace + " public static final BiMap " + COLUMN_NAME_MAP + " = " + N.getSimpleClassName(utilClass)
// + ".newImmutableBiMapForInterface((Map)" + N.getSimpleClassName(utilClass) + ".asLinkedHashMap(" + _columnNameMap.substring(2) + "));"
// + N.LINE_SEPARATOR);
// }
fileWrite.write(sb.toString());
ObjectFactory.recycle(sb);
}
public static void entityDefinitionXml2ColumnNameTable(final String domainName, final File entityDefinitionXml, final String srcPath) {
entityDefinitionXml2ColumnNameTable(domainName, entityDefinitionXml, srcPath, null, _N);
}
/**
*
* @param domainName
* @param entityDefinitionXml
* @param srcPath
* @param columnName2VarName
* @param utilClass specify CodeGenerator._N or your own utility class to generate entity classes which not dependent on AbacusUtil.java
*/
public static void entityDefinitionXml2ColumnNameTable(final String domainName, final File entityDefinitionXml, final String srcPath,
Method columnName2VarName, Class> utilClass) {
if (columnName2VarName == null) {
columnName2VarName = ClassUtil.getDeclaredMethod(CodeGenerator.class, PROP_NAME2VAR_NAME, String.class);
}
if (utilClass == null) {
utilClass = _N;
}
final EntityDefinitionFactory entityDefinitionFactory = SQLEntityDefinitionFactory.newInstance(domainName, entityDefinitionXml);
final Collection entityDefs = entityDefinitionFactory.getDefinitionList();
final String pkgName = entityDefinitionFactory.getAttribute(EntityDefEle.PACKAGE);
final String classFilePath = makePackageFolder(srcPath, pkgName);
// if (utilClass.equals(_N)) {
// File utilClassFile = new File(classFilePath + ClassUtil.getSimpleClassName(_N) + POSTFIX_OF_JAVA_FILE);
// if (!utilClassFile.exists()) {
// String sourceCode = _N_STRING.replaceFirst("com.landawn.abacus.util", pkgName);
// IOUtil.write(utilClassFile, sourceCode);
// }
// }
String columnNameTableClassName = POSTFIX_OF_COLUMN_NAME_LIST;
if (N.notNullOrEmpty(domainName)) {
columnNameTableClassName = N.capitalize(domainName) + columnNameTableClassName;
}
File columnNameTableClassFile = new File(classFilePath + columnNameTableClassName + POSTFIX_OF_JAVA_FILE);
if (columnNameTableClassFile.exists()) {
columnNameTableClassFile.delete();
}
Writer fileWrite = null;
try {
columnNameTableClassFile.createNewFile();
fileWrite = newFileWriter(columnNameTableClassFile);
writeFileHead(fileWrite);
writePackageName(pkgName, fileWrite);
fileWrite.write(IOUtil.LINE_SEPARATOR);
fileWrite.write("import " + Arrays.class.getCanonicalName() + ";" + IOUtil.LINE_SEPARATOR);
fileWrite.write("import " + Collections.class.getCanonicalName() + ";" + IOUtil.LINE_SEPARATOR);
fileWrite.write("import " + List.class.getCanonicalName() + ";" + IOUtil.LINE_SEPARATOR);
// if (utilClass.equals(N.class)) {
// fileWrite.write("import " + Map.class.getCanonicalName() + ";" + N.LINE_SEPARATOR);
// fileWrite.write("import " + BiMap.class.getCanonicalName() + ";" + N.LINE_SEPARATOR);
// }
// fileWrite.write(N.LINE_SEPARATOR);
// String utilClassName = ClassUtil.getCanonicalClassName(utilClass);
// if (pkgName.equals(utilClassName.substring(0, utilClassName.lastIndexOf('.'))) || utilClass.equals(_N)) {
// // ignore
// } else {
// fileWrite.write("import " + ClassUtil.getCanonicalClassName(utilClass) + ";" + N.LINE_SEPARATOR);
// fileWrite.write(N.LINE_SEPARATOR);
// }
writeClassComment(fileWrite);
String clazzName = columnNameTableClassFile.getName().substring(0, columnNameTableClassFile.getName().indexOf(_PERIOD));
fileWrite.write("public interface " + clazzName + " {");
String headSpace = "";
writeDomainPropNameClass(domainName, fileWrite, headSpace);
writeColumnNameTable(entityDefs, columnName2VarName, headSpace, fileWrite, utilClass);
// -------- write global domain property name.
Map allColumnNamesMap = new LinkedHashMap<>();
Map allColumnPropNameMap = new LinkedHashMap<>();
for (EntityDefinition entityDef : entityDefs) {
for (Property prop : entityDef.getPropertyList()) {
if (prop.getColumnType() == ColumnType.ENTITY || N.isNullOrEmpty(prop.getColumnName())) {
continue;
}
String columnName = prop.getColumnName();
allColumnNamesMap.put(columnName.toUpperCase(), columnName);
allColumnPropNameMap.put(columnName.toUpperCase(), prop.getName());
}
}
List keys = new ArrayList<>(allColumnNamesMap.keySet());
N.sort(keys);
for (String key : keys) {
String columnName = allColumnNamesMap.get(key);
String columnVarName = ClassUtil.invokeMethod(columnName2VarName, columnName);
fileWrite.write(IOUtil.LINE_SEPARATOR);
fileWrite.write(" public static final String " + columnVarName + " = \"" + columnName + "\".intern();");
fileWrite.write(IOUtil.LINE_SEPARATOR);
}
// if (utilClass.equals(N.class)) {
// fileWrite.write(N.LINE_SEPARATOR);
// fileWrite.write(" /**" + N.LINE_SEPARATOR);
// fileWrite.write(" * Mapping of column name to property name " + N.LINE_SEPARATOR);
// fileWrite.write(" */" + N.LINE_SEPARATOR);
// fileWrite.append(headSpace + " @SuppressWarnings(\"rawtypes\")" + N.LINE_SEPARATOR);
// fileWrite.write(" public static final BiMap " + COLUMN_PROP_MAP + " = " + N.getSimpleClassName(utilClass)
// + ".newImmutableBiMapForInterface((Map) " + N.getSimpleClassName(utilClass) + ".asLinkedHashMap(");
//
// int i = 0;
// for (String key : keys) {
// String columnName = allColumnNamesMap.get(key);
// String columnVarName = N.invokeMethod(columnName2VarName, columnName);
// String propName = allColumnPropNameMap.get(key);
//
// if (i++ > 0) {
// fileWrite.write(", ");
// }
//
// fileWrite.write(columnVarName + ", \"" + propName + "\".intern()");
// }
//
// fileWrite.write("));" + N.LINE_SEPARATOR);
// }
fileWrite.write("}" + IOUtil.LINE_SEPARATOR);
fileWrite.flush();
} catch (IOException e) {
throw new UncheckedIOException(e);
} finally {
IOUtil.close(fileWrite);
}
}
private static void writeColumnNameTable(final Collection entityDefs, final Method columnName2VarName, final String headSpace,
final Writer fileWrite, final Class> utilClass) throws IOException {
for (EntityDefinition entityDef : entityDefs) {
if (entityDef.isSliceEntity()) {
continue;
}
fileWrite.write(IOUtil.LINE_SEPARATOR);
fileWrite.write(headSpace + " public static interface " + entityDef.getName() + POSTFIX_OF_COLUMN_NAME_LIST + " {");
writeColumnNameField(entityDef, columnName2VarName, headSpace + " ", fileWrite, utilClass);
fileWrite.write(headSpace + " }" + IOUtil.LINE_SEPARATOR);
}
}
private static void writeColumnNameField(final EntityDefinition entityDef, final Method columnName2VarName, final String headSpace, final Writer fileWrite,
final Class> utilClass) throws IOException {
final StringBuilder sb = ObjectFactory.createStringBuilder();
sb.append(IOUtil.LINE_SEPARATOR);
sb.append(headSpace + " /**" + IOUtil.LINE_SEPARATOR);
sb.append(headSpace + " * Name of \"" + entityDef.getTableName() + "\" table. " + IOUtil.LINE_SEPARATOR);
sb.append(headSpace + " */" + IOUtil.LINE_SEPARATOR);
sb.append(
headSpace + " public static final String " + ENTITY_NAME_VAR + " = \"" + entityDef.getTableName() + "\".intern();" + IOUtil.LINE_SEPARATOR);
String _columnNameList = "";
String _propNameList = "";
// String _columnNameMap = "";
// String _columnPropNameMap = "";
// String _propNameMap = "";
for (Property prop : entityDef.getPropertyList()) {
if (prop.getColumnType().isEntity()) {
continue;
}
String columnName = prop.getColumnName();
if (N.isNullOrEmpty(columnName)) {
continue;
}
String columnVarName = ClassUtil.invokeMethod(columnName2VarName, columnName);
sb.append(IOUtil.LINE_SEPARATOR);
sb.append(headSpace + " /**" + IOUtil.LINE_SEPARATOR);
sb.append(headSpace + " * Name of \"" + columnName + "\" column. " + IOUtil.LINE_SEPARATOR);
sb.append(headSpace + " * Java type: " + prop.getType().name() + ". " + IOUtil.LINE_SEPARATOR);
sb.append(headSpace + " */" + IOUtil.LINE_SEPARATOR);
// sb.append(headSpace + " public static final String " + propVarName + " = \"" + columnName + "\".intern();" + N.LINE_SEPARATOR);
// sb.append(headSpace + " public static final String _" + propVarName + " = (_ + \"." + columnName + "\").intern();" + N.LINE_SEPARATOR);
sb.append(headSpace + " public static final String " + columnVarName + " = (" + ENTITY_NAME_VAR + " + \"." + columnName + "\").intern();"
+ IOUtil.LINE_SEPARATOR);
_columnNameList += (", " + columnVarName);
String propName = "\"" + entityDef.getName() + "." + prop.getName() + "\".intern()";
_propNameList += (", " + propName);
// _columnNameMap += (", " + columnVarName + ", \"" + columnName + "\".intern()");
// _columnPropNameMap += (", " + columnVarName + ", " + propName);
// _propNameMap += (", " + propName + ", \"" + prop.getName() + "\".intern()");
}
sb.append(IOUtil.LINE_SEPARATOR);
sb.append(headSpace + " /**" + IOUtil.LINE_SEPARATOR);
sb.append(headSpace + " * Immutable column name list" + IOUtil.LINE_SEPARATOR);
sb.append(headSpace + " */" + IOUtil.LINE_SEPARATOR);
sb.append(headSpace + " public static final List " + COLUMN_NAME_LIST + " = Collections.unmodifiableList(Arrays.asList("
+ _columnNameList.substring(2) + "));" + IOUtil.LINE_SEPARATOR);
// if (utilClass.equals(N.class)) {
// sb.append(N.LINE_SEPARATOR);
// sb.append(headSpace + " /**" + N.LINE_SEPARATOR);
// sb.append(headSpace + " * Immutable column name to tableName.columnName mapper" + N.LINE_SEPARATOR);
// sb.append(headSpace + " */" + N.LINE_SEPARATOR);
// sb.append(headSpace + " @SuppressWarnings(\"rawtypes\")" + N.LINE_SEPARATOR);
// sb.append(headSpace + " public static final BiMap " + COLUMN_NAME_MAP + " = " + N.getSimpleClassName(utilClass)
// + ".newImmutableBiMapForInterface((Map)" + N.getSimpleClassName(utilClass) + ".asLinkedHashMap(" + _columnNameMap.substring(2) + "));"
// + N.LINE_SEPARATOR);
//
// sb.append(N.LINE_SEPARATOR);
// sb.append(headSpace + " /**" + N.LINE_SEPARATOR);
// sb.append(headSpace + " * Immutable column name to property name mapper" + N.LINE_SEPARATOR);
// sb.append(headSpace + " */" + N.LINE_SEPARATOR);
// sb.append(headSpace + " @SuppressWarnings(\"rawtypes\")" + N.LINE_SEPARATOR);
// sb.append(headSpace + " public static final BiMap " + COLUMN_PROP_MAP + " = " + N.getSimpleClassName(utilClass)
// + ".newImmutableBiMapForInterface((Map)" + N.getSimpleClassName(utilClass) + ".asLinkedHashMap(" + _columnPropNameMap.substring(2) + "));"
// + N.LINE_SEPARATOR);
// }
sb.append(IOUtil.LINE_SEPARATOR);
sb.append(headSpace + " /**" + IOUtil.LINE_SEPARATOR);
sb.append(headSpace + " * Immutable property name list" + IOUtil.LINE_SEPARATOR);
sb.append(headSpace + " */" + IOUtil.LINE_SEPARATOR);
sb.append(headSpace + " public static final List " + PROP_NAME_LIST + " = Collections.unmodifiableList(Arrays.asList("
+ _propNameList.substring(2) + "));" + IOUtil.LINE_SEPARATOR);
// if (utilClass.equals(N.class)) {
// sb.append(N.LINE_SEPARATOR);
// sb.append(headSpace + " /**" + N.LINE_SEPARATOR);
// sb.append(headSpace + " * Immutable property name to entityName.propName mapper" + N.LINE_SEPARATOR);
// sb.append(headSpace + " */" + N.LINE_SEPARATOR);
// sb.append(headSpace + " @SuppressWarnings(\"rawtypes\")" + N.LINE_SEPARATOR);
// sb.append(headSpace + " public static final BiMap " + PROP_NAME_MAP + " = " + N.getSimpleClassName(utilClass)
// + ".newImmutableBiMapForInterface((Map)" + N.getSimpleClassName(utilClass) + ".asLinkedHashMap(" + _propNameMap.substring(2) + "));"
// + N.LINE_SEPARATOR);
// }
fileWrite.write(sb.toString());
ObjectFactory.recycle(sb);
}
public static void generateSQLMapperIdTable(final String filePath, final String srcPath, final String pkgName, final String className,
final Method id2VarName) {
generateSQLMapperIdTable(SQLMapper.fromFile(filePath), srcPath, pkgName, className, id2VarName);
}
public static void generateSQLMapperIdTable(final SQLMapper sqlMapper, final String srcPath, final String pkgName, final String className,
Method id2VarName) {
String classFilePath = makePackageFolder(srcPath, pkgName);
File sqlMapperTableClassFile = new File(classFilePath + className + POSTFIX_OF_JAVA_FILE);
if (sqlMapperTableClassFile.exists()) {
sqlMapperTableClassFile.delete();
}
if (id2VarName == null) {
id2VarName = ClassUtil.getDeclaredMethod(CodeGenerator.class, PROP_NAME2VAR_NAME, String.class);
}
Writer fileWrite = null;
try {
sqlMapperTableClassFile.createNewFile();
fileWrite = newFileWriter(sqlMapperTableClassFile);
writeFileHead(fileWrite);
writePackageName(pkgName, fileWrite);
fileWrite.write(IOUtil.LINE_SEPARATOR);
writeClassComment(fileWrite);
fileWrite.write("public final class " + className + " {");
fileWrite.write(IOUtil.LINE_SEPARATOR);
for (String id : sqlMapper.keySet()) {
String propVarName = ClassUtil.invokeMethod(id2VarName, id);
fileWrite.write(" public static final String " + propVarName + " = \"" + id + "\";" + IOUtil.LINE_SEPARATOR);
}
fileWrite.write("}" + IOUtil.LINE_SEPARATOR);
fileWrite.flush();
} catch (IOException e) {
throw new UncheckedIOException(e);
} finally {
IOUtil.close(fileWrite);
}
}
public static void generateEntity(File srcDir, String packageName, String className, Map fields) {
generateEntity(srcDir, packageName, className, fields, false, false, false, Objects.class);
}
/**
*
* @param srcDir
* @param packageName
* @param className
* @param fields key is field name, value is field type, which must be Class, Type or the name of them.
* It must be LinkedHashMap.
* @param constructor
* @param copyMethod
* @param fluentSetter
* @param utilClassForHashEqualsToString is Objects.class by default. It can also be N.class or any classes else which provide the {@code hashCode/equals/toString} method.
* Or specify CodeGenerator._N or your own utility class to generate entity classes which not dependent on AbacusUtil.jar for Methods {@code hashCode/equals/toString}.
*/
public static void generateEntity(File srcDir, String packageName, String className, Map fields, final boolean constructor,
final boolean copyMethod, final boolean fluentSetter, final Class> utilClassForHashEqualsToString) {
generateEntity(srcDir, packageName, className, fields, constructor, copyMethod, fluentSetter, null, null, null, null, utilClassForHashEqualsToString);
}
/**
*
* @param srcDir
* @param packageName
* @param className
* @param fields key is field name, value is field type, which must be Class, Type or the name of them.
* It must be LinkedHashMap.
* @param constructor
* @param copyMethod
* @param fluentSetter
* @param fieldName2MethodName
* @param parentClass
* @param parentPropertyModeForHashEquals
* @param parentPropertyModeForToString
* @param utilClassForHashEqualsToString is Objects.class by default. It can also be N.class or any classes else which provide the {@code hashCode/equals/toString} method.
* Or specify CodeGenerator._N or your own utility class to generate entity classes which not dependent on AbacusUtil.jar for Methods {@code hashCode/equals/toString}.
*/
public static void generateEntity(File srcDir, String packageName, String className, Map fields, final boolean constructor,
final boolean copyMethod, final boolean fluentSetter, final Map fieldName2MethodName, Class> parentClass,
final ParentPropertyMode parentPropertyModeForHashEquals, final ParentPropertyMode parentPropertyModeForToString,
final Class> utilClassForHashEqualsToString) {
if (fields instanceof LinkedHashMap == false) {
throw new IllegalArgumentException("'fields has to be LinkedHashMap to keep the order");
}
if (N.isNullOrEmpty(fields)) {
return;
}
final Class> utilClass = utilClassForHashEqualsToString == null ? Objects.class : utilClassForHashEqualsToString;
final Map> fieldTypes = new LinkedHashMap<>(N.initHashCapacity(fields.size()));
Type> type = null;
for (Map.Entry entry : fields.entrySet()) {
if (entry.getValue() instanceof Type) {
type = (Type>) entry.getValue();
} else if (entry.getValue() instanceof Class) {
type = N.typeOf((Class>) entry.getValue());
} else if (entry.getValue() instanceof String) {
String typeName = (String) entry.getValue();
final TypeAttrParser attrs = TypeAttrParser.parse(typeName);
if (N.notNullOrEmpty(attrs.getTypeParameters())) {
if (attrs.getTypeParameters().length == 1) {
Class> eleClass = null;
try {
eleClass = ClassUtil.forClass(attrs.getTypeParameters()[0]);
} catch (Throwable e) {
// ignore.
}
if (eleClass == null && N.notNullOrEmpty(packageName)) {
try {
eleClass = ClassUtil.forClass(packageName + "." + attrs.getTypeParameters()[0]);
} catch (Throwable e) {
// ignore.
}
if (eleClass != null) {
typeName = attrs.getClassName() + "<" + eleClass.getCanonicalName() + ">";
}
}
} else if (attrs.getTypeParameters().length == 2) {
String keyTypeName = attrs.getTypeParameters()[0];
String valueTypeName = attrs.getTypeParameters()[1];
Class> keyClass = null;
Class> valueClass = null;
try {
keyClass = ClassUtil.forClass(attrs.getTypeParameters()[0]);
} catch (Throwable e) {
// ignore.
}
try {
valueClass = ClassUtil.forClass(attrs.getTypeParameters()[1]);
} catch (Throwable e) {
// ignore.
}
if ((keyClass == null || valueClass == null) && N.notNullOrEmpty(packageName)) {
if (keyClass == null) {
try {
keyClass = ClassUtil.forClass(packageName + "." + attrs.getTypeParameters()[0]);
if (keyClass != null) {
keyTypeName = keyClass.getCanonicalName();
}
} catch (Throwable e) {
// ignore.
}
}
if (valueClass == null) {
try {
valueClass = ClassUtil.forClass(packageName + "." + attrs.getTypeParameters()[1]);
if (valueClass != null) {
valueTypeName = valueClass.getCanonicalName();
}
} catch (Throwable e) {
// ignore.
}
}
if (keyClass != null && valueClass != null) {
typeName = attrs.getClassName() + "<" + keyTypeName + ", " + valueTypeName + ">";
}
}
}
}
type = N.typeOf(typeName);
} else {
throw new IllegalArgumentException("Only Class, Type or the name of them are supported");
}
fieldTypes.put(entry.getKey(), type);
}
final File dirFile = new File(
srcDir.getAbsolutePath() + (N.isNullOrEmpty(packageName) ? "" : IOUtil.FILE_SEPARATOR + N.replaceAll(packageName, ".", IOUtil.FILE_SEPARATOR)));
if (dirFile.exists() == false) {
dirFile.mkdirs();
}
if (_N.equals(utilClass)) {
File utilClassFile = new File(dirFile.getAbsolutePath() + IOUtil.FILE_SEPARATOR + ClassUtil.getSimpleClassName(_N) + POSTFIX_OF_JAVA_FILE);
if (!utilClassFile.exists()) {
String sourceCode = _N_STRING.replaceFirst("package com.landawn.abacus.util;",
N.isNullOrEmpty(packageName) ? "" : "package " + packageName + ";");
IOUtil.write(utilClassFile, sourceCode);
}
}
final File classFile = new File(dirFile.getAbsolutePath() + IOUtil.FILE_SEPARATOR + className + ".java");
IOUtil.createIfNotExists(classFile);
final BufferedWriter writer = IOUtil.newBufferedWriter(classFile);
try {
IOUtil.writeLine(writer, "package " + packageName + ";");
// IOUtil.writeLine(writer, N.EMPTY_STRING);
// write imports
final Multimap> packClasses = new Multimap<>(SortedMap.class, Set.class);
for (Map.Entry> entry : fieldTypes.entrySet()) {
readPackageTypes(entry.getValue(), packageName, packClasses);
}
if (parentClass != null) {
Package pkg = parentClass.getPackage();
if (pkg == null || pkg.getName().equals(packageName) || parentClass.getCanonicalName().startsWith("java.lang.")) {
// ignore
} else {
packClasses.put(pkg.getName(), parentClass.getCanonicalName());
}
}
if (!ClassUtil.getPackageName(utilClass).equals(packageName) && !utilClass.equals(_N)) {
packClasses.put(ClassUtil.getPackageName(utilClass), utilClass.getCanonicalName());
}
// if (N.notNullOrEmpty(fields) && ClassUtil.getPackageName(com.landawn.abacus.annotation.Type.class).equals(packageName) == false) {
// packClasses.put(ClassUtil.getPackageName(com.landawn.abacus.annotation.Type.class),
// com.landawn.abacus.annotation.Type.class.getCanonicalName());
// }
final Map> importedClasses = new LinkedHashMap<>();
try {
for (Set clsNames : packClasses.values()) {
for (String clsName : clsNames) {
// IOUtil.writeLine(writer, "import " + clsName + ";");
Class> cls = ClassUtil.forClass(clsName);
writeClassImport(writer, cls, importedClasses);
}
// IOUtil.writeLine(writer, N.EMPTY_STRING);
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
IOUtil.writeLine(writer, N.EMPTY_STRING);
IOUtil.writeLine(writer, N.EMPTY_STRING);
final String iden = " ";
IOUtil.writeLine(writer, "/**");
IOUtil.writeLine(writer, " * Generated by Abacus.");
IOUtil.writeLine(writer, " * @version ${version}");
IOUtil.writeLine(writer, " */");
if (parentClass == null) {
IOUtil.writeLine(writer, "public class " + className + " {");
} else {
IOUtil.writeLine(writer, "public class " + className + " extends " + parentClass.getSimpleName() + " {");
}
if (parentClass != null && Serializable.class.isAssignableFrom(parentClass)) {
long hashCode = className.hashCode();
for (Map.Entry> entry : fieldTypes.entrySet()) {
hashCode += hashCode * 31 + entry.getKey().hashCode();
hashCode += hashCode * 31 + entry.getValue().name().hashCode();
}
long serialVersionUID = 0;
if (String.valueOf(Long.MAX_VALUE).length() > (String.valueOf(hashCode).length() + 1)) {
serialVersionUID = Long.valueOf(String.valueOf(hashCode) + fieldTypes.size());
} else {
serialVersionUID = Long.valueOf(String.valueOf(hashCode + fieldTypes.size()));
}
IOUtil.writeLine(writer, N.EMPTY_STRING);
IOUtil.writeLine(writer, iden + "private static final long serialVersionUID = " + serialVersionUID + "L;");
}
IOUtil.writeLine(writer, N.EMPTY_STRING);
for (Map.Entry> entry : fieldTypes.entrySet()) {
IOUtil.writeLine(writer, iden + "private " + getSimpleType(entry.getValue(), null, packageName, importedClasses) + " " + entry.getKey() + ";");
}
writeClassMethod(null, className, parentClass, packageName, fieldTypes, constructor, copyMethod, fluentSetter, parentPropertyModeForHashEquals,
parentPropertyModeForToString, fieldName2MethodName, importedClasses, utilClass, writer);
IOUtil.writeLine(writer, "}");
} catch (NoSuchFieldException | SecurityException e) {
throw N.toRuntimeException(e);
} finally {
IOUtil.closeQuietly(writer);
}
}
private static void readPackageTypes(Type> type, String packageName, final Multimap> packClasses) {
final Package pkg = type.clazz().getPackage();
if (pkg == null || pkg.getName().equals(packageName) || type.clazz().getCanonicalName().startsWith("java.lang.")) {
// ignore.
} else {
packClasses.put(pkg.getName(), type.clazz().getCanonicalName());
}
if (N.notNullOrEmpty(type.getParameterTypes())) {
for (Type> paramType : type.getParameterTypes()) {
readPackageTypes(paramType, packageName, packClasses);
}
}
}
/**
* Write the generated methods by the fields defined the in specified class to the source file.
*
*
* Add below comments to specified the section where the generated methods should be written to
*
* =====>
*
* <=====
*
*
* @param srcDir
* @param cls
*/
public static void writeClassMethod(final File srcDir, final Class> cls) {
writeClassMethod(srcDir, cls, false, false, false, null, null, Objects.class);
}
/**
* Write the generated methods by the fields defined the in specified class to the source file.
*
*
* Add below comments to specified the section where the generated methods should be written to
*
* =====>
*
* <=====
*
*
* @param srcDir
* @param cls
* @param constructor generate constructor
* @param copyMethod generate the copy method.
* @param fluentSetter
* @param ignoreFieldNames
* @param fieldName2MethodName
* @param utilClassForHashEqualsToString is Objects.class by default. It can also be N.class or any classes else which provide the {@code hashCode/equals/toString} method.
* Or specify CodeGenerator._N or your own utility class to generate entity classes which not dependent on AbacusUtil.jar for Methods {@code hashCode/equals/toString}.
*/
public static void writeClassMethod(final File srcDir, final Class> cls, final boolean constructor, final boolean copyMethod, final boolean fluentSetter,
Set ignoreFieldNames, final Map fieldName2MethodName, final Class> utilClassForHashEqualsToString) {
writeClassMethod(srcDir, cls, constructor, copyMethod, fluentSetter, ignoreFieldNames, fieldName2MethodName, ParentPropertyMode.FIRST,
ParentPropertyMode.FIRST, utilClassForHashEqualsToString);
}
/**
* Write the generated methods by the fields defined the in specified class to the source file.
*
*
* Add below comments to specified the section where the generated methods should be written to
*