diff --git a/cobigen-templates/templates-devon4j/src/main/java/com/devonfw/cobigen/templates/devon4j/utils/JavaUtil.java b/cobigen-templates/templates-devon4j/src/main/java/com/devonfw/cobigen/templates/devon4j/utils/JavaUtil.java index 4bd3880670..1af7c139bb 100644 --- a/cobigen-templates/templates-devon4j/src/main/java/com/devonfw/cobigen/templates/devon4j/utils/JavaUtil.java +++ b/cobigen-templates/templates-devon4j/src/main/java/com/devonfw/cobigen/templates/devon4j/utils/JavaUtil.java @@ -3,10 +3,20 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; +import java.util.List; import java.util.Map; +import java.util.Optional; + +import javax.persistence.Column; +import javax.persistence.Id; +import javax.persistence.Table; import org.apache.commons.lang3.ClassUtils; +import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -499,4 +509,142 @@ public String getFirstEnumValue(String className) { return null; } } + + /** + * Get the annotated table name of a given Entity class + * + * @param className + * full qualified class name + * @return the annotated table name if existed or class name without the word Entity + */ + public String getEntityTableName(String className) { + if (!className.endsWith("Entity")) { + LOG.error("Could not return table name because {} is not an Entity class", className); + return null; + } + try { + Class entityClass = Class.forName(className); + Table table = entityClass.getAnnotation(Table.class); + return table == null + ? StringUtils.left(entityClass.getSimpleName(), + entityClass.getSimpleName().length() - "Entity".length()) + : table.name(); + } catch (ClassNotFoundException e) { + LOG.error("{}: Could not find {}", e.getMessage(), className); + return null; + } + } + + /** + * Helper method to get all fields recursively inclusive fields from super classes + * + * @param cl + * class to find fields + * @param fields + * list of fields to accumulate recursively + * @return list of all fields found + */ + private static List getAllFields(List fields, Class cl) { + fields.addAll(Arrays.asList(cl.getDeclaredFields())); + + if (cl.getSuperclass() != null) { + getAllFields(fields, cl.getSuperclass()); + } + + return fields; + } + + /** + * Helper method to get type of a field inclusive field from super classes + * + * @param pojoClass + * {@link Class} the class object of the pojo + * @param fieldName + * {@link String} the name of the field + * @return type of the field + */ + private Class getTypeOfField(Class pojoClass, String fieldName) { + if (pojoClass != null) { + List fields = new ArrayList(); + getAllFields(fields, pojoClass); + + Optional field = fields.stream().filter(f -> f.getName().equals(fieldName)).findFirst(); + + if (field.isPresent()) { + return field.get().getType(); + } + } + LOG.error("Could not find type of field {}", fieldName); + return null; + } + + /** + * @param pojoClass + * {@link Class} the class object of the pojo + * @param fieldName + * {@link String} the name of the field + * @return true if the field is an instance of java.utils.Collections + */ + public boolean isCollection2(Class pojoClass, String fieldName) { + Class type = getTypeOfField(pojoClass, fieldName); + return type == null ? false : Collection.class.isAssignableFrom(type); + } + + /** + * @param className + * {@link String} full qualified class name + * @param fieldName + * {@link String} the name of the field + * @return type of the field in String + */ + public String getCanonicalNameOfField(String className, String fieldName) { + try { + Class entityClass = Class.forName(className); + Class type = getTypeOfField(entityClass, fieldName); + if (type != null) { + return type.getCanonicalName(); + } + } catch (ClassNotFoundException e) { + LOG.error("{}: Could not find {}", e.getMessage(), className); + } + return null; + } + + /** + * Get the primary key and its type of a given Entity class + * + * @param className + * full qualified class name + * @return the primary key and its type if found or null + */ + public String getPrimaryKey(String className) { + try { + Class entityClass = Class.forName(className); + List fields = new ArrayList(); + getAllFields(fields, entityClass); + for (Field field : fields) { + if (field.isAnnotationPresent(Id.class)) { + return field.getType().getCanonicalName() + "," + + (field.isAnnotationPresent(Column.class) ? field.getAnnotation(Column.class).name() + : field.getName()); + } else { + Optional getterOptional = Arrays.stream(entityClass.getMethods()) + .filter(m -> m.getName().equals( + "get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1)) + && m.isAnnotationPresent(Id.class)) + .findFirst(); + if (getterOptional.isPresent()) { + Method getter = getterOptional.get(); + return getter.getReturnType().getCanonicalName() + "," + + (getter.isAnnotationPresent(Column.class) ? getter.getAnnotation(Column.class).name() + : field.getName()); + } + } + } + } catch (ClassNotFoundException e) { + LOG.error("{}: Could not find {}", e.getMessage(), className); + } + LOG.error("Could not find the field or getter with @Id annotated"); + return null; + } } diff --git a/cobigen-templates/templates-devon4j/src/main/templates/context.xml b/cobigen-templates/templates-devon4j/src/main/templates/context.xml index 583f5fce32..1e8a735325 100644 --- a/cobigen-templates/templates-devon4j/src/main/templates/context.xml +++ b/cobigen-templates/templates-devon4j/src/main/templates/context.xml @@ -1,6 +1,10 @@ - + + + + + diff --git a/cobigen-templates/templates-devon4j/src/main/templates/sql/functions.ftl b/cobigen-templates/templates-devon4j/src/main/templates/sql/functions.ftl new file mode 100644 index 0000000000..c7e29ef7c2 --- /dev/null +++ b/cobigen-templates/templates-devon4j/src/main/templates/sql/functions.ftl @@ -0,0 +1,47 @@ +<#function get_type field> + <#assign type = get_mapping_type(field.canonicalType)> + <#if type?contains("VARCHAR") && field.annotations.javax_validation_constraints_Size?? && field.annotations.javax_validation_constraints_Size.max??> + <#assign type = "VARCHAR(" + field.annotations.javax_validation_constraints_Size.max +")"> + + <#if (field.annotations.javax_persistence_Column?? + && field.annotations.javax_persistence_Column.nullable?? + && field.annotations.javax_persistence_Column.nullable=="false") || field.annotations.javax_validation_constraints_NotNull?? > + <#assign type = type + " NOT NULL"> + + <#return type> + + +<#function get_mapping_type input_type> + <#if input_type?contains("Integer") || input_type=="int" || input_type?contains("Year") || input_type?contains("Month") || JavaUtil.isEnum(input_type)> + <#assign type = "INTEGER"> + <#elseif input_type?contains("Long") || input_type=="long" || input_type?contains("Object")> + <#assign type = "BIGINT"> + <#elseif input_type?contains("Short") || input_type=="short"> + <#assign type = "SMALLINT"> + <#elseif input_type?contains("Float") || input_type=="float"> + <#assign type = "FLOAT"> + <#elseif input_type?contains("Double") || input_type=="double"> + <#assign type = "DOUBLE"> + <#elseif input_type?contains("BigDecimal") || input_type?contains("BigInteger")> + <#assign type = "NUMERIC"> + <#elseif input_type?contains("Character") || input_type=="char"> + <#assign type = "CHAR"> + <#elseif input_type?contains("Byte") || input_type=='byte'> + <#assign type = "TINYINT"> + <#elseif input_type?contains("Boolean") || input_type=="boolean"> + <#assign type = "BOOLEAN"> + <#elseif input_type?contains("Instant") || input_type?contains("Timestamp")> + <#assign type = "TIMESTAMP"> + <#elseif input_type?contains("Date") || input_type?contains("Calendar")> + <#assign type = "DATE"> + <#elseif input_type?contains("Time")> + <#assign type = 'TIME'> + <#elseif input_type?contains("UUID")> + <#assign type = "BINARY"> + <#elseif input_type?contains("Blob")> + <#assign type = "BLOB"> + <#else> + <#assign type = "VARCHAR"> + + <#return type> + diff --git a/cobigen-templates/templates-devon4j/src/main/templates/sql/templates.xml b/cobigen-templates/templates-devon4j/src/main/templates/sql/templates.xml new file mode 100644 index 0000000000..0800eeb52c --- /dev/null +++ b/cobigen-templates/templates-devon4j/src/main/templates/sql/templates.xml @@ -0,0 +1,15 @@ + + + + +