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 java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import com.landawn.abacus.core.AbstractDirtyMarker;
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 {
/**
* 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 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.
}
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;
}
/**
* 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
*
* =====>
*
* <=====
*
*
* @param srcDir
* @param cls
* @param constructor
* @param copyMethod
* @param fluentSetter
* @param ignoreFieldNames
* @param fieldName2MethodName
* @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 writeClassMethod(final File srcDir, final Class cls, final boolean constructor, final boolean copyMethod, final boolean fluentSetter,
Set ignoreFieldNames, final Map fieldName2MethodName, final ParentPropertyMode parentPropertyModeForHashEquals,
final ParentPropertyMode parentPropertyModeForToString, final Class utilClassForHashEqualsToString) {
final Package pkg = cls.getPackage();
final String clsSourcePath = srcDir.getAbsolutePath()
+ (pkg == null ? "" : IOUtil.FILE_SEPARATOR + StringUtil.replaceAll(pkg.getName(), ".", IOUtil.FILE_SEPARATOR)) + IOUtil.FILE_SEPARATOR
+ cls.getSimpleName() + ".java";
final File clsSourceFile = new File(clsSourcePath);
if (clsSourceFile.exists() == false) {
throw new RuntimeException("No source file found by path: " + clsSourcePath + " for class: " + cls.getCanonicalName());
}
if (ignoreFieldNames == null) {
ignoreFieldNames = new LinkedHashSet<>();
}
final String simpleClassName = cls.getSimpleName();
final List lines = ImmutableList.of(IOUtil.readLines(clsSourceFile));
final Map> fieldTypes = new LinkedHashMap<>();
for (Field field : cls.getDeclaredFields()) {
final String fieldName = field.getName();
if (Modifier.isStatic(field.getModifiers()) || ignoreFieldNames.contains(fieldName)) {
continue;
} else {
fieldTypes.put(fieldName, N.typeOf(field.getType()));
}
}
if (N.isNullOrEmpty(fieldTypes) && fluentSetter == false && constructor == false && copyMethod == false) {
return;
}
final BiMap> importedClasses = new BiMap<>();
boolean hasGenericTypeField = false;
for (int i = 0, size = lines.size(); i < size; i++) {
final String tmp = "class " + simpleClassName;
while (i < size && lines.get(i).indexOf(tmp) < 0) {
String line = lines.get(i);
if (line.startsWith("import ") && line.endsWith(";") && line.indexOf(" static ") < 0) {
String clsName = StringUtil.substringBetween(line, ' ', line.lastIndexOf(';')).get();
importedClasses.put(clsName, ClassUtil.forClass(clsName));
}
i++;
}
int start = i + 1;
while (i < size && (lines.get(i).indexOf(") {") < 0 /*&& lines.get(i).indexOf("}") < 0*/)) {
i++;
}
int end = i;
if (start < size && end <= size && start < end) {
for (int j = start; j < end; j++) {
String line = lines.get(j).trim().replaceAll(" ", " ");
int lastIndex = line.lastIndexOf(' ');
String fieldName = null;
if (lastIndex > 0 && line.endsWith(";") && fieldTypes.containsKey((fieldName = line.substring(lastIndex + 1, line.length() - 1)))) {
int firstIdx = line.indexOf('<');
if (firstIdx > 0) {
hasGenericTypeField = true;
int fromIndex = line.lastIndexOf(' ', firstIdx);
if (fromIndex >= 0) {
String typeName = line.substring(fromIndex + 1, lastIndex);
if ((typeName = typeName.trim()).length() > 0) {
// for java.util.Date
if (importedClasses.containsKey("java.util.Date")) {
typeName = StringUtil.replaceAll(typeName, "", "");
typeName = StringUtil.replaceAll(typeName, "", " java.util.Date>");
typeName = StringUtil.replaceAll(typeName, ",Date>", ",java.util.Date>");
typeName = StringUtil.replaceAll(typeName, " Date,", " java.util.Date,");
typeName = StringUtil.replaceAll(typeName, ",Date,", ",java.util.Date,");
typeName = StringUtil.replaceAll(typeName, " utilClass = utilClassForHashEqualsToString == null ? Objects.class : utilClassForHashEqualsToString;
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);
}
}
try (StringWriter writer = new StringWriter()) {
writeClassMethod(cls, ClassUtil.getSimpleClassName(cls), cls.getSuperclass(), packageName, fieldTypes, constructor, copyMethod, fluentSetter,
parentPropertyModeForHashEquals, parentPropertyModeForToString, fieldName2MethodName, importedClasses, utilClass, writer);
int start = -1, end = -1;
for (int i = 0, size = lines.size(); i < size; i++) {
if (lines.get(i).indexOf("=====>") > 0) {
start = i;
} else if (lines.get(i).indexOf("<=====") > 0) {
end = i;
}
}
final List newLines = new ArrayList<>();
if (start >= 0 && end >= 0) {
newLines.addAll(lines.subList(0, start + 1));
newLines.add(writer.toString());
newLines.addAll(lines.subList(end, lines.size()));
} else {
for (int i = 0, size = lines.size(); i < size; i++) {
if (lines.get(i).indexOf(") {") > 0) {
String tmp = lines.get(i).trim();
if (tmp.startsWith("public ") && (tmp.indexOf(cls.getSimpleName()) > 0 || tmp.indexOf(" get") > 0 || tmp.indexOf(" set") > 0)) {
start = i;
while (start-- > 0 && lines.get(start).trim().startsWith("@")) {
}
while (lines.get(start).trim().length() == 0 && start-- > 0) {
}
break;
}
}
}
if (start < 0) {
for (int i = lines.size() - 1; i >= 0; i--) {
if (lines.get(i).trim().startsWith("}")) {
start = i - 1;
break;
}
}
}
newLines.addAll(lines.subList(0, start + 1));
newLines.add(writer.toString());
newLines.add("}");
}
if (!ClassUtil.getPackageName(utilClass).equals(packageName) && !_N.equals(utilClass) && fieldTypes.size() > 0) {
String importUtilClass = "import " + utilClass.getCanonicalName() + ";";
for (int i = 0, size = newLines.size(); i < size; i++) {
if (newLines.get(i).indexOf(importUtilClass) >= 0) {
break;
} else if (newLines.get(i).indexOf("public ") >= 0) {
int j = i;
while (j-- >= 0) {
if (newLines.get(j).startsWith("import") || newLines.get(j).startsWith("package")) {
break;
}
}
newLines.add(j + 1, N.EMPTY_STRING);
newLines.add(j + 2, importUtilClass);
if (newLines.get(j + 3).trim().length() > 0) {
newLines.add(j + 3, N.EMPTY_STRING);
}
break;
}
}
}
if (hasGenericTypeField) {
// String importTypeClass = "import com.landawn.abacus.annotation.Type;";
//
// for (int i = 0, size = newLines.size(); i < size; i++) {
// if (newLines.get(i).indexOf(importTypeClass) >= 0) {
// break;
// } else if (newLines.get(i).indexOf("public ") >= 0) {
// int ins = 0;
// if (newLines.get(i - 1).trim().length() > 0) {
// newLines.add(i + ins++, N.EMPTY_STRING);
// }
// newLines.add(i + ins++, importTypeClass);
// newLines.add(i + ins++, N.EMPTY_STRING);
// break;
// }
// }
}
if (newLines.get(newLines.size() - 1).startsWith("}") && newLines.get(newLines.size() - 2).endsWith(IOUtil.LINE_SEPARATOR)) {
newLines.set(newLines.size() - 2, StringUtil.chop(newLines.get(newLines.size() - 2)));
}
IOUtil.writeLines(clsSourceFile, newLines);
// Add annotation back.
Map> annoMap = new LinkedHashMap<>();
for (int i = 0, len = lines.size(); i < len; i++) {
String line = lines.get(i);
if (line.trim().startsWith("@")) {
Set tmp = new LinkedHashSet<>();
tmp.add(line);
while (++i < len && lines.get(i).trim().startsWith("@")) {
tmp.add(lines.get(i));
}
while (i < len && lines.get(i).trim().equals("")) {
i++;
}
annoMap.put(lines.get(i), tmp);
}
}
if (N.notNullOrEmpty(annoMap)) {
final List finalLines = new ArrayList<>();
final List srcLines = IOUtil.readLines(clsSourceFile);
for (int i = 0, len = srcLines.size(); i < len; i++) {
final String line = srcLines.get(i);
final Set annons = annoMap.get(line);
if (N.notNullOrEmpty(annons)) {
int j = finalLines.size() - 1;
while (j >= 0 && finalLines.get(j).trim().startsWith("@")) {
annons.add(finalLines.remove(j--));
}
finalLines.addAll(annoMap.get(line));
}
finalLines.add(line);
}
IOUtil.writeLines(clsSourceFile, finalLines);
}
} catch (IOException | NoSuchFieldException | SecurityException e) {
throw N.toRuntimeException(e);
}
}
// public static void generateEntity(File srcDir, String packageName, Map> classNameFields) {
// generateEntity(srcDir, packageName, classNameFields, false, false, false);
// }
//
// /**
// *
// * @param srcDir
// * @param packageName
// * @param classNameFields
// * @param constructor
// * @param copyMethod
// * @param fluentSetter
// */
// public static void generateEntity(File srcDir, String packageName, Map> classNameFields, final boolean constructor,
// final boolean copyMethod, final boolean fluentSetter) {
// generateEntity(srcDir, packageName, classNameFields, constructor, copyMethod, fluentSetter, null, ParentPropertyMode.NONE, ParentPropertyMode.NONE);
// }
//
// /**
// *
// * @param srcDir
// * @param packageName
// * @param classNameFields
// * @param constructor
// * @param copyMethod
// * @param fluentSetter
// * @param parentClass
// * @param parentPropertyModeForHashEquals
// * @param parentPropertyModeForToString
// */
// public static void generateEntity(File srcDir, String packageName, Map> classNameFields, final boolean constructor,
// final boolean copyMethod, final boolean fluentSetter, Class parentClass, final ParentPropertyMode parentPropertyModeForHashEquals,
// final ParentPropertyMode parentPropertyModeForToString) {
//
// for (String className : classNameFields.keySet()) {
// generateEntity(srcDir, packageName, className, classNameFields.get(className), constructor, copyMethod, fluentSetter, parentClass,
// parentPropertyModeForHashEquals, parentPropertyModeForToString);
// }
// }
// /**
// * Generate and Print out the methods according to fields defined the in specified class.
// *
// * @param cls
// */
// public static void printClassMethod(final Class cls) {
// printClassMethod(cls, false, false, false, null, null);
// }
//
// /**
// * Generate and Print out the methods according to fields defined the in specified class.
// *
// * @param cls
// * @param constructor generate constructor
// * @param copyMethod generate the copy method.
// * @param fluentSetter
// * @param ignoreFieldNames
// * @param fieldName2MethodName
// */
// public static void printClassMethod(final Class cls, final boolean constructor, final boolean copyMethod, final boolean fluentSetter,
// Set ignoreFieldNames, final Map fieldName2MethodName) {
// printClassMethod(cls, constructor, copyMethod, fluentSetter, ignoreFieldNames, fieldName2MethodName, ParentPropertyMode.FIRST,
// ParentPropertyMode.FIRST);
// }
//
// /**
// * Generate and Print out the methods according to fields defined the in specified class.
// *
// * @param cls
// * @param constructor
// * @param copyMethod
// * @param fluentSetter
// * @param ignoreFieldNames
// * @param fieldName2MethodName
// * @param parentPropertyModeForHashEquals
// * @param parentPropertyModeForToString
// */
// public static void printClassMethod(final Class cls, final boolean constructor, final boolean copyMethod, final boolean fluentSetter,
// Set ignoreFieldNames, final Map fieldName2MethodName, final ParentPropertyMode parentPropertyModeForHashEquals,
// final ParentPropertyMode parentPropertyModeForToString) {
// if (ignoreFieldNames == null) {
// ignoreFieldNames = new LinkedHashSet<>();
// }
//
// final Map> fieldTypes = new LinkedHashMap<>();
//
// for (Field field : cls.getDeclaredFields()) {
// final String fieldName = field.getName();
// if (Modifier.isStatic(field.getModifiers()) || ignoreFieldNames.contains(fieldName)) {
// continue;
// } else {
// fieldTypes.put(fieldName, N.typeOf(field.getType()));
// }
// }
//
// try (Writer writer = new OutputStreamWriter(System.out)) {
// printClassMethod(cls, ClassUtil.getSimpleClassName(cls), cls.getSuperclass(), cls.getPackage() == null ? null : ClassUtil.getPackageName(cls),
// fieldTypes, constructor, copyMethod, fluentSetter, parentPropertyModeForHashEquals, parentPropertyModeForToString, fieldName2MethodName,
// new LinkedHashMap>(), writer);
// } catch (IOException | NoSuchFieldException | SecurityException e) {
// throw N.toRuntimeException(e);
// }
// }
private static void writeClassMethod(Class cls, final String className, final Class parentClass, final String pkgName,
final Map> fieldTypes, final boolean constructor, final boolean copyMethod, final boolean fluentSetter,
ParentPropertyMode parentPropertyModeForHashEquals, ParentPropertyMode parentPropertyModeForToString, Map fieldName2MethodName,
final Map> importedClasses, final Class utilClass, Writer writer) throws NoSuchFieldException, SecurityException {
if (N.isNullOrEmpty(fieldTypes) && fluentSetter == false && constructor == false && copyMethod == false) {
return;
}
if (parentPropertyModeForHashEquals == null) {
parentPropertyModeForHashEquals = ParentPropertyMode.NONE;
}
if (parentPropertyModeForToString == null) {
parentPropertyModeForToString = ParentPropertyMode.NONE;
}
if (fieldName2MethodName == null) {
fieldName2MethodName = new LinkedHashMap<>();
}
final String utilClassName = utilClass.getSimpleName();
final List parentGetterMethods = new ArrayList<>();
final Map parentSettterMethods = new LinkedHashMap<>();
final List> allClasses = new ArrayList<>();
if (parentClass != null) {
allClasses.add(parentClass);
while (allClasses.get(allClasses.size() - 1).getSuperclass() != null) {
allClasses.add(allClasses.get(allClasses.size() - 1).getSuperclass());
}
for (Class superClass : allClasses) {
parentGetterMethods.addAll(ClassUtil.getPropGetMethodList(superClass).values());
parentSettterMethods.putAll(ClassUtil.getPropSetMethodList(superClass));
}
}
final String iden = " ";
if (constructor) {
IOUtil.writeLine(writer, N.EMPTY_STRING);
IOUtil.writeLine(writer, iden + "public " + className + "() {");
if (parentClass != null && AbstractDirtyMarker.class.isAssignableFrom(parentClass)) {
IOUtil.writeLine(writer, iden + iden + "super(" + className + ".class.getSimpleName());");
}
IOUtil.writeLine(writer, iden + "}");
IOUtil.writeLine(writer, N.EMPTY_STRING);
String parameterStr = "";
String signValues = "";
for (Map.Entry entry : parentSettterMethods.entrySet()) {
if (parameterStr.length() > 0) {
parameterStr += ", ";
}
parameterStr += (getParameterTypeName(pkgName, entry));
if (signValues.length() > 0) {
signValues += IOUtil.LINE_SEPARATOR;
}
signValues += (iden + iden + "this." + entry.getValue().getName() + "(" + entry.getKey() + ");");
}
for (Map.Entry> entry : fieldTypes.entrySet()) {
if (parameterStr.length() > 0) {
parameterStr += ", ";
}
parameterStr += (getSimpleType(entry.getValue(), pkgName, importedClasses) + " " + entry.getKey());
if (signValues.length() > 0) {
signValues += IOUtil.LINE_SEPARATOR;
}
signValues += (iden + iden + "this." + entry.getKey() + " = " + entry.getKey() + ";");
}
if (parameterStr.length() > 0) {
IOUtil.writeLine(writer, iden + "public " + className + "(" + parameterStr + ") {");
if (parentClass != null && AbstractDirtyMarker.class.isAssignableFrom(parentClass)) {
IOUtil.writeLine(writer, iden + iden + "super(" + className + ".class.getSimpleName());");
IOUtil.writeLine(writer, N.EMPTY_STRING);
}
IOUtil.writeLine(writer, signValues);
IOUtil.writeLine(writer, iden + "}");
}
}
if (fluentSetter && N.notNullOrEmpty(parentSettterMethods)) {
for (Map.Entry entry : parentSettterMethods.entrySet()) {
if (parentClass.isAssignableFrom(entry.getValue().getReturnType()) == false) {
continue;
}
final String methodName = entry.getValue().getName();
IOUtil.writeLine(writer, N.EMPTY_STRING);
IOUtil.writeLine(writer, iden + "public " + className + " " + methodName + "(" + getParameterTypeName(pkgName, entry) + ") {");
IOUtil.writeLine(writer, iden + iden + "super." + methodName + "(" + entry.getKey() + ");");
IOUtil.writeLine(writer, N.EMPTY_STRING);
IOUtil.writeLine(writer, iden + iden + "return this;");
IOUtil.writeLine(writer, iden + "}");
}
}
for (Map.Entry> entry : fieldTypes.entrySet()) {
final String fieldName = entry.getKey();
final String simpleTypeName = getSimpleType(entry.getValue(), pkgName, importedClasses);
// final String getPrefix = boolean.class.equals(entry.getValue().getTypeClass()) || Boolean.class.equals(entry.getValue().getTypeClass()) ? "is"
// : "get";
final String postfix = fieldName2MethodName.containsKey(fieldName) ? fieldName2MethodName.get(fieldName)
: (StringUtil.isAllUpperCase(fieldName) ? fieldName : StringUtil.capitalize(fieldName));
IOUtil.writeLine(writer, N.EMPTY_STRING);
// final String annoTypeName = getAnnoType(entry.getValue(), pkgName, importedClasses);
// IOUtil.writeLine(writer, iden + "@Type(\"" + entry.getValue().getName() + "\")");
// if (!entry.getValue().getName().equals(annoTypeName) || N.notNullOrEmpty(entry.getValue().getParameterTypes())) {
// IOUtil.writeLine(writer, iden + "@Type(\"" + annoTypeName + "\")");
// }
IOUtil.writeLine(writer, iden + "public " + simpleTypeName + " get" + postfix + "() {");
IOUtil.writeLine(writer, iden + iden + "return " + fieldName + ";");
IOUtil.writeLine(writer, iden + "}");
if (cls == null || Modifier.isFinal(cls.getDeclaredField(fieldName).getModifiers()) == false) {
IOUtil.writeLine(writer, N.EMPTY_STRING);
if (fluentSetter) {
IOUtil.writeLine(writer, iden + "public " + className + " set" + postfix + "(" + simpleTypeName + " " + fieldName + ") {");
} else {
IOUtil.writeLine(writer, iden + "public void set" + postfix + "(" + simpleTypeName + " " + fieldName + ") {");
}
if (parentClass != null && AbstractDirtyMarker.class.isAssignableFrom(parentClass)) {
IOUtil.writeLine(writer, iden + iden + "super.setUpdatedPropName(\"" + fieldName + "\");");
}
IOUtil.writeLine(writer, iden + iden + "this." + fieldName + " = " + fieldName + ";");
if (fluentSetter) {
IOUtil.writeLine(writer, N.EMPTY_STRING);
IOUtil.writeLine(writer, iden + iden + "return this;");
}
IOUtil.writeLine(writer, iden + "}");
}
}
if (copyMethod) {
IOUtil.writeLine(writer, N.EMPTY_STRING);
IOUtil.writeLine(writer, iden + "public " + className + " copy() {");
IOUtil.writeLine(writer, iden + iden + "final " + className + " copy = new " + className + "();");
IOUtil.writeLine(writer, N.EMPTY_STRING);
for (Method method : parentGetterMethods) {
IOUtil.writeLine(writer,
iden + iden + "copy." + ClassUtil.getPropSetMethod(method.getDeclaringClass(), ClassUtil.getPropNameByMethod(method)).getName()
+ "(this." + method.getName() + "());");
}
for (Map.Entry> entry : fieldTypes.entrySet()) {
IOUtil.writeLine(writer, iden + iden + "copy." + entry.getKey() + " = this." + entry.getKey() + ";");
}
IOUtil.writeLine(writer, IOUtil.LINE_SEPARATOR + iden + iden + "return copy;");
IOUtil.writeLine(writer, iden + "}");
}
if (N.notNullOrEmpty(fieldTypes)) {
{
IOUtil.writeLine(writer, N.EMPTY_STRING);
IOUtil.writeLine(writer, iden + "@Override");
IOUtil.writeLine(writer, iden + "public int hashCode() {");
IOUtil.writeLine(writer, iden + iden + "int h = 17;");
if (parentPropertyModeForHashEquals == ParentPropertyMode.FIRST && parentGetterMethods.size() > 0) {
for (Method method : parentGetterMethods) {
IOUtil.writeLine(writer, iden + iden + "h = 31 * h + " + utilClassName + ".hashCode(" + method.getName() + "());");
}
}
for (Map.Entry> entry : fieldTypes.entrySet()) {
IOUtil.writeLine(writer, iden + iden + "h = 31 * h + " + utilClassName + ".hashCode(" + entry.getKey() + ");");
}
if (parentPropertyModeForHashEquals == ParentPropertyMode.LAST && parentGetterMethods.size() > 0) {
for (Method method : parentGetterMethods) {
IOUtil.writeLine(writer, iden + iden + "h = 31 * h + " + utilClassName + "hashCode(" + method.getName() + "());");
}
}
IOUtil.writeLine(writer, IOUtil.LINE_SEPARATOR + iden + iden + "return h;");
IOUtil.writeLine(writer, iden + "}");
}
{
IOUtil.writeLine(writer, N.EMPTY_STRING);
IOUtil.writeLine(writer, iden + "@Override");
IOUtil.writeLine(writer, iden + "public boolean equals(Object obj) {");
IOUtil.writeLine(writer, iden + iden + "if (this == obj) {");
IOUtil.writeLine(writer, iden + iden + iden + "return true;");
IOUtil.writeLine(writer, iden + iden + "}");
IOUtil.writeLine(writer, IOUtil.LINE_SEPARATOR + iden + iden + "if (obj instanceof " + className + ") {");
IOUtil.writeLine(writer, iden + iden + iden + "final " + className + " other = (" + className + ") obj;");
int i = 0;
if (parentPropertyModeForHashEquals == ParentPropertyMode.FIRST && parentGetterMethods.size() > 0) {
for (Method method : parentGetterMethods) {
if (i++ == 0) {
if (i == parentGetterMethods.size() + fieldTypes.size()) {
IOUtil.writeLine(writer, IOUtil.LINE_SEPARATOR + iden + iden + iden + "return " + utilClassName + ".equals(" + method.getName()
+ "(), other." + method.getName() + "());");
} else {
IOUtil.writeLine(writer, IOUtil.LINE_SEPARATOR + iden + iden + iden + "return " + utilClassName + ".equals(" + method.getName()
+ "(), other." + method.getName() + "())");
}
} else {
if (i == parentGetterMethods.size() + fieldTypes.size()) {
IOUtil.writeLine(writer, iden + iden + iden + iden + "&& " + utilClassName + ".equals(" + method.getName() + "(), other."
+ method.getName() + "());");
} else {
IOUtil.writeLine(writer, iden + iden + iden + iden + "&& " + utilClassName + ".equals(" + method.getName() + "(), other."
+ method.getName() + "())");
}
}
}
}
for (Map.Entry> entry : fieldTypes.entrySet()) {
final String fieldName = entry.getKey();
if (i++ == 0) {
if (i == fieldTypes.size() && (parentGetterMethods.size() == 0 || parentPropertyModeForHashEquals != ParentPropertyMode.LAST)) {
IOUtil.writeLine(writer, IOUtil.LINE_SEPARATOR + iden + iden + iden + "return " + utilClassName + ".equals(" + fieldName
+ ", other." + fieldName + ");");
} else {
IOUtil.writeLine(writer, IOUtil.LINE_SEPARATOR + iden + iden + iden + "return " + utilClassName + ".equals(" + fieldName
+ ", other." + fieldName + ")");
}
} else {
if (((parentPropertyModeForHashEquals != ParentPropertyMode.FIRST && i == fieldTypes.size())
|| (parentPropertyModeForHashEquals == ParentPropertyMode.FIRST && i == fieldTypes.size() + parentGetterMethods.size()))
&& (parentGetterMethods.size() == 0 || parentPropertyModeForHashEquals != ParentPropertyMode.LAST)) {
IOUtil.writeLine(writer,
iden + iden + iden + iden + "&& " + utilClassName + ".equals(" + fieldName + ", other." + fieldName + ");");
} else {
IOUtil.writeLine(writer, iden + iden + iden + iden + "&& " + utilClassName + ".equals(" + fieldName + ", other." + fieldName + ")");
}
}
}
if (parentPropertyModeForHashEquals == ParentPropertyMode.LAST && parentGetterMethods.size() > 0) {
for (Method method : parentGetterMethods) {
if (i++ == 0) {
if (i == parentGetterMethods.size() + fieldTypes.size()) {
IOUtil.writeLine(writer, IOUtil.LINE_SEPARATOR + iden + iden + iden + "return " + utilClassName + ".equals(" + method.getName()
+ "(), other." + method.getName() + "());");
} else {
IOUtil.writeLine(writer, IOUtil.LINE_SEPARATOR + iden + iden + iden + "return " + utilClassName + ".equals(" + method.getName()
+ "(), other." + method.getName() + "())");
}
} else {
if (i == parentGetterMethods.size() + fieldTypes.size()) {
IOUtil.writeLine(writer, iden + iden + iden + iden + "&& " + utilClassName + ".equals(" + method.getName() + "(), other."
+ method.getName() + "());");
} else {
IOUtil.writeLine(writer, iden + iden + iden + iden + "&& " + utilClassName + ".equals(" + method.getName() + "(), other."
+ method.getName() + "())");
}
}
}
}
IOUtil.writeLine(writer, iden + iden + "}");
IOUtil.writeLine(writer, IOUtil.LINE_SEPARATOR + iden + iden + "return false;");
IOUtil.writeLine(writer, iden + "}");
}
{
final StringBuilder sb = new StringBuilder();
IOUtil.writeLine(writer, N.EMPTY_STRING);
sb.append(iden + "@Override" + IOUtil.LINE_SEPARATOR);
sb.append(iden + "public String toString() {" + IOUtil.LINE_SEPARATOR);
int i = 0;
if (parentPropertyModeForToString == ParentPropertyMode.FIRST && parentGetterMethods.size() > 0) {
for (Method method : parentGetterMethods) {
if (i++ == 0) {
sb.append(iden + iden + "return \"{" + ClassUtil.getPropNameByMethod(method) + "=\" + " + utilClassName + ".toString("
+ method.getName() + "())");
} else {
sb.append(IOUtil.LINE_SEPARATOR + iden + iden + " + \", " + ClassUtil.getPropNameByMethod(method) + "=\" + " + utilClassName
+ ".toString(" + method.getName() + "())");
}
if (i == parentGetterMethods.size() + fieldTypes.size()) {
if (i > 1) {
sb.append(IOUtil.LINE_SEPARATOR + iden + iden + " + \"}\";" + IOUtil.LINE_SEPARATOR);
} else {
sb.append(" + \"}\";" + IOUtil.LINE_SEPARATOR);
}
}
}
}
for (Map.Entry> entry : fieldTypes.entrySet()) {
final String fieldName = entry.getKey();
if (i++ == 0) {
sb.append(iden + iden + "return \"{" + fieldName + "=\" + " + utilClassName + ".toString(" + fieldName + ")");
} else {
sb.append(IOUtil.LINE_SEPARATOR + iden + iden + " + \", " + fieldName + "=\" + " + utilClassName + ".toString(" + fieldName
+ ")");
}
if ((((parentPropertyModeForToString == null || parentPropertyModeForToString == ParentPropertyMode.NONE)
|| (parentPropertyModeForToString == ParentPropertyMode.LAST && parentGetterMethods.size() == 0)) && i == fieldTypes.size())
|| (parentPropertyModeForToString == ParentPropertyMode.FIRST && i == parentGetterMethods.size() + fieldTypes.size())) {
if (i > 1) {
sb.append(IOUtil.LINE_SEPARATOR + iden + iden + " + \"}\";" + IOUtil.LINE_SEPARATOR);
} else {
sb.append(" + \"}\";" + IOUtil.LINE_SEPARATOR);
}
}
}
if (parentPropertyModeForToString == ParentPropertyMode.LAST && parentGetterMethods.size() > 0) {
for (Method method : parentGetterMethods) {
if (i++ == 0) {
sb.append(iden + iden + "return \"{" + ClassUtil.getPropNameByMethod(method) + "=\" + " + utilClassName + ".toString("
+ method.getName() + "())");
} else {
sb.append(IOUtil.LINE_SEPARATOR + iden + iden + " + \", " + ClassUtil.getPropNameByMethod(method) + "=\" + " + utilClassName
+ ".toString(" + method.getName() + "())");
}
if (i == parentGetterMethods.size() + fieldTypes.size()) {
if (i > 1) {
sb.append(IOUtil.LINE_SEPARATOR + iden + iden + " + \"}\";" + IOUtil.LINE_SEPARATOR);
} else {
sb.append(" + \"}\";" + IOUtil.LINE_SEPARATOR);
}
}
}
}
sb.append(iden + "}");
IOUtil.writeLine(writer, sb.toString());
}
}
}
private static String getParameterTypeName(final String pkgName, Map.Entry entry) {
String paraTypeName = ClassUtil.getParameterizedTypeNameByMethod(entry.getValue());
if (N.notNullOrEmpty(pkgName)) {
String tmp = pkgName + ".";
int idx = 0;
char ch = 0;
while ((idx = paraTypeName.indexOf(tmp, idx)) >= 0) {
for (int i = idx + tmp.length(), len = paraTypeName.length(); i < len; i++) {
ch = paraTypeName.charAt(i);
if ((Character.isLetterOrDigit(ch) || ch == '$' || ch == '_') && i != len - 1) {
continue;
} else if (ch == '.') {
idx = i;
break;
} else {
paraTypeName = paraTypeName.replace(paraTypeName.substring(idx, i), paraTypeName.substring(idx + tmp.length(), i));
idx += (i - idx - tmp.length());
break;
}
}
}
}
return paraTypeName + " " + entry.getKey();
}
/**
*
* @param srcDir
* @param pkgName
*/
public static void writeUtilClassForHashEqualsToString(final File srcDir, final String pkgName) {
writeUtilClassForHashEqualsToString(srcDir, pkgName, "_N");
}
/**
*
* @param srcDir
* @param pkgName
* @param utilClassName
*/
public static void writeUtilClassForHashEqualsToString(final File srcDir, final String pkgName, final String utilClassName) {
final String utilClassFilePath = srcDir.getAbsolutePath()
+ (N.isNullOrEmpty(pkgName) ? "" : IOUtil.FILE_SEPARATOR + StringUtil.replaceAll(pkgName, ".", IOUtil.FILE_SEPARATOR)) + IOUtil.FILE_SEPARATOR
+ utilClassName + ".java";
final File utilClassFile = new File(utilClassFilePath);
if (utilClassFile.exists() == false && IOUtil.createIfNotExists(utilClassFile) == false) {
throw new RuntimeException("Failed to create new File by path: " + utilClassFilePath);
}
if (N.isNullOrEmpty(pkgName)) {
IOUtil.write(utilClassFile, _N_STRING.replaceFirst("package com.landawn.abacus.util;", "").replaceAll("_N", utilClassName));
} else {
IOUtil.write(utilClassFile, _N_STRING.replaceFirst("com.landawn.abacus.util", pkgName).replaceAll("_N", utilClassName));
}
}
public static void printTransferMethod(final Class sourceClass, final Class targetClass) {
printTransferMethod(sourceClass, targetClass, null);
}
public static void printTransferMethod(final Class sourceClass, final Class targetClass, final Map propNameMapping) {
final String iden = " ";
final String srcClassName = sourceClass.getSimpleName();
final String targetClassName = targetClass.getSimpleName();
StringBuilder sb = new StringBuilder();
sb.append("public static ")
.append(targetClassName)
.append(" ")
.append(ClassUtil.formalizePropName(srcClassName))
.append("2")
.append(targetClassName)
.append(" (")
.append(srcClassName)
.append(" source) {")
.append(IOUtil.LINE_SEPARATOR);
sb.append(iden).append("final ").append(targetClassName).append(" result = new ").append(targetClassName).append("();").append(IOUtil.LINE_SEPARATOR);
for (Map.Entry entry : ClassUtil.getPropGetMethodList(sourceClass).entrySet()) {
final Method getMethod = entry.getValue();
String propName = entry.getKey();
if (propNameMapping != null && propNameMapping.containsKey(propName)) {
propName = propNameMapping.get(propName);
}
final Method setMethod = ClassUtil.getPropSetMethod(targetClass, propName);
if (setMethod == null) {
sb.append(iden).append("// No set method found for: source.").append(getMethod.getName()).append("()").append(IOUtil.LINE_SEPARATOR);
} else if (!setMethod.getParameterTypes()[0].isAssignableFrom(getMethod.getReturnType())) {
sb.append(iden).append("// Incompatible parameter type for: source.").append(getMethod.getName()).append("()").append(IOUtil.LINE_SEPARATOR);
} else {
sb.append(iden).append("result.").append(setMethod.getName()).append("(source.").append(getMethod.getName()).append("());").append(
IOUtil.LINE_SEPARATOR);
}
}
sb.append(iden).append("return result; ").append(IOUtil.LINE_SEPARATOR);
sb.append("}").append(IOUtil.LINE_SEPARATOR);
System.out.println(IOUtil.LINE_SEPARATOR);
System.out.println(sb.toString());
System.out.println(IOUtil.LINE_SEPARATOR);
}
private static String getSimpleType(Type type, final String pkgName, final Map> importedClasses) {
final Class typeClass = type.clazz();
String typeName = null;
if (type.isGenericType()) {
typeName = type.name();
} else {
Class clazz = type.clazz();
typeName = Object.class.equals(clazz) && !type.name().equals(ObjectType.OBJECT) ? type.name() : clazz.getCanonicalName();
}
if (typeClass.isArray()) {
String componentClassName = StringUtil.substring(typeName, 0, typeName.indexOf('[')).get();
if (importedClasses.containsKey(componentClassName)) {
typeName = typeName.replaceAll(componentClassName.substring(0, componentClassName.lastIndexOf('.') + 1), "");
}
} else if (typeName.startsWith("java.lang.") || (importedClasses.containsValue(typeClass) && N.notNullOrEmpty(ClassUtil.getPackageName(typeClass)))) {
typeName = typeName.replace(ClassUtil.getPackageName(typeClass) + ".", "");
}
if (type.isGenericType()) {
Type[] paramTypes = type.getParameterTypes();
if (N.notNullOrEmpty(paramTypes)) {
String tmp = typeName.substring(0, typeName.indexOf('<')) + "<";
for (int i = 0, len = paramTypes.length; i < len; i++) {
if (i > 0) {
tmp += ", ";
}
tmp += getSimpleType(paramTypes[i], pkgName, importedClasses);
}
tmp += ">";
typeName = tmp;
// for (Type paraType : parameterTypes) {
// try {
// if (isUsualType(paraType.getTypeClass().getCanonicalName())) {
// typeName = typeName.replace(ClassUtil.getPackageName(paraType.getTypeClass()) + ".", "");
// }
// } catch (Exception e) {
// // ignore;
// }
// }
}
}
if ((ClassUtil.getPackageName(TypeType.class) + "." + TypeType.TYPE).equals(typeName)) {
typeName = typeName + "