package org.springframework.roo.addon.jpa.addon.entity.factories;
import static org.springframework.roo.model.HibernateJavaType.VALIDATOR_CONSTRAINTS_EMAIL;
import static org.springframework.roo.model.JavaType.STRING;
import static org.springframework.roo.model.JdkJavaType.BIG_DECIMAL;
import static org.springframework.roo.model.JdkJavaType.BIG_INTEGER;
import static org.springframework.roo.model.JdkJavaType.CALENDAR;
import static org.springframework.roo.model.JdkJavaType.DATE;
import static org.springframework.roo.model.JdkJavaType.GREGORIAN_CALENDAR;
import static org.springframework.roo.model.JdkJavaType.TIMESTAMP;
import static org.springframework.roo.model.JpaJavaType.JOIN_COLUMN;
import static org.springframework.roo.model.Jsr303JavaType.DECIMAL_MAX;
import static org.springframework.roo.model.Jsr303JavaType.DECIMAL_MIN;
import static org.springframework.roo.model.Jsr303JavaType.DIGITS;
import static org.springframework.roo.model.Jsr303JavaType.FUTURE;
import static org.springframework.roo.model.Jsr303JavaType.MAX;
import static org.springframework.roo.model.Jsr303JavaType.MIN;
import static org.springframework.roo.model.Jsr303JavaType.NOT_NULL;
import static org.springframework.roo.model.Jsr303JavaType.PAST;
import static org.springframework.roo.model.Jsr303JavaType.SIZE;
import static org.springframework.roo.model.SpringJavaType.AUTOWIRED;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.roo.addon.jpa.addon.dod.EmbeddedHolder;
import org.springframework.roo.addon.jpa.addon.dod.EmbeddedIdHolder;
import org.springframework.roo.addon.jpa.annotations.entity.factory.RooJpaEntityFactory;
import org.springframework.roo.classpath.PhysicalTypeIdentifier;
import org.springframework.roo.classpath.PhysicalTypeIdentifierNamingUtils;
import org.springframework.roo.classpath.PhysicalTypeMetadata;
import org.springframework.roo.classpath.customdata.CustomDataKeys;
import org.springframework.roo.classpath.details.BeanInfoUtils;
import org.springframework.roo.classpath.details.ClassOrInterfaceTypeDetails;
import org.springframework.roo.classpath.details.FieldMetadata;
import org.springframework.roo.classpath.details.FieldMetadataBuilder;
import org.springframework.roo.classpath.details.MemberFindingUtils;
import org.springframework.roo.classpath.details.MethodMetadata;
import org.springframework.roo.classpath.details.MethodMetadataBuilder;
import org.springframework.roo.classpath.details.annotations.AnnotatedJavaType;
import org.springframework.roo.classpath.details.annotations.AnnotationAttributeValue;
import org.springframework.roo.classpath.details.annotations.AnnotationMetadata;
import org.springframework.roo.classpath.details.annotations.AnnotationMetadataBuilder;
import org.springframework.roo.classpath.details.comments.CommentStructure;
import org.springframework.roo.classpath.details.comments.JavadocComment;
import org.springframework.roo.classpath.details.comments.CommentStructure.CommentLocation;
import org.springframework.roo.classpath.itd.AbstractItdTypeDetailsProvidingMetadataItem;
import org.springframework.roo.classpath.itd.InvocableMemberBodyBuilder;
import org.springframework.roo.metadata.MetadataIdentificationUtils;
import org.springframework.roo.model.DataType;
import org.springframework.roo.model.JavaSymbolName;
import org.springframework.roo.model.JavaType;
import org.springframework.roo.model.JdkJavaType;
import org.springframework.roo.project.LogicalPath;
/**
* Metadata for {@link RooJpaEntityFactory}.
*
* @author Sergio Clares
* @since 2.0
*/
public class JpaEntityFactoryMetadata extends AbstractItdTypeDetailsProvidingMetadataItem {
private static final String INDEX_VAR = "index";
private static final JavaSymbolName INDEX_SYMBOL = new JavaSymbolName(INDEX_VAR);
private static final JavaSymbolName MAX_SYMBOL = new JavaSymbolName("max");
private static final JavaSymbolName MIN_SYMBOL = new JavaSymbolName("min");
private static final String OBJ_VAR = "obj";
private static final JavaSymbolName OBJ_SYMBOL = new JavaSymbolName(OBJ_VAR);
private static final JavaSymbolName VALUE = new JavaSymbolName("value");
private static final JavaSymbolName CREATE_FACTORY_METHOD_NAME = new JavaSymbolName("create");
public static final JavaSymbolName SPECIFIC_METHOD_PREFIX = new JavaSymbolName("getSpecific");
private static final String PROVIDES_TYPE_STRING = JpaEntityFactoryMetadata.class.getName();
private static final String PROVIDES_TYPE = MetadataIdentificationUtils
.create(PROVIDES_TYPE_STRING);
public static String createIdentifier(final JavaType javaType, final LogicalPath path) {
return PhysicalTypeIdentifierNamingUtils.createIdentifier(PROVIDES_TYPE_STRING, javaType, path);
}
public static String createIdentifier(ClassOrInterfaceTypeDetails details) {
final LogicalPath logicalPath =
PhysicalTypeIdentifier.getPath(details.getDeclaredByMetadataId());
return createIdentifier(details.getType(), logicalPath);
}
public static JavaType getJavaType(final String metadataIdentificationString) {
return PhysicalTypeIdentifierNamingUtils.getJavaType(PROVIDES_TYPE_STRING,
metadataIdentificationString);
}
public static String getMetadataIdentiferType() {
return PROVIDES_TYPE;
}
public static LogicalPath getPath(final String metadataIdentificationString) {
return PhysicalTypeIdentifierNamingUtils.getPath(PROVIDES_TYPE_STRING,
metadataIdentificationString);
}
public static boolean isValid(final String metadataIdentificationString) {
return PhysicalTypeIdentifierNamingUtils.isValid(PROVIDES_TYPE_STRING,
metadataIdentificationString);
}
private JavaType entity;
private final List<JavaType> requiredDataOnDemandCollaborators = new ArrayList<JavaType>();
private MethodMetadata randomPersistentEntityMethod;
private final Map<FieldMetadata, Map<FieldMetadata, String>> embeddedFieldInitializers =
new LinkedHashMap<FieldMetadata, Map<FieldMetadata, String>>();
private final Map<FieldMetadata, String> fieldInitializers =
new LinkedHashMap<FieldMetadata, String>();
private EmbeddedIdHolder embeddedIdHolder;
private List<EmbeddedHolder> embeddedHolders;
private Map<FieldMetadata, JpaEntityFactoryMetadata> locatedFields;
/**
* Constructor
*
* @param identifier
* @param aspectName
* @param governorPhysicalTypeMetadata
* @param entity
* @param locatedFields
* @param embeddedHolder
* @param entityFactoryClasses
* @param embeddedIdHolder
*/
public JpaEntityFactoryMetadata(final String identifier, final JavaType aspectName,
final PhysicalTypeMetadata governorPhysicalTypeMetadata, final JavaType entity,
final Map<FieldMetadata, JpaEntityFactoryMetadata> locatedFields,
final List<EmbeddedHolder> embeddedHolders,
Set<ClassOrInterfaceTypeDetails> entityFactoryClasses, final EmbeddedIdHolder embeddedIdHolder) {
super(identifier, aspectName, governorPhysicalTypeMetadata);
Validate.notNull(locatedFields, "Located fields map required");
Validate.notNull(embeddedHolders, "Embedded holders list required");
this.entity = entity;
this.embeddedIdHolder = embeddedIdHolder;
this.embeddedHolders = embeddedHolders;
this.locatedFields = locatedFields;
builder.addMethod(getCreateMethod());
// Calculate and store field initializers
for (final Map.Entry<FieldMetadata, JpaEntityFactoryMetadata> entry : locatedFields.entrySet()) {
final FieldMetadata field = entry.getKey();
final String initializer = getFieldInitializer(field, entry.getValue(), entityFactoryClasses);
if (!StringUtils.isBlank(initializer)) {
this.fieldInitializers.put(field, initializer);
}
}
for (final EmbeddedHolder embeddedHolder : embeddedHolders) {
final Map<FieldMetadata, String> initializers = new LinkedHashMap<FieldMetadata, String>();
for (final FieldMetadata field : embeddedHolder.getFields()) {
initializers.put(field, getFieldInitializer(field, null, entityFactoryClasses));
}
this.embeddedFieldInitializers.put(embeddedHolder.getEmbeddedField(), initializers);
}
for (final EmbeddedHolder embeddedHolder : embeddedHolders) {
builder.addMethod(getEmbeddedClassMutatorMethod(embeddedHolder));
addEmbeddedClassFieldMutatorMethodsToBuilder(embeddedHolder, entityFactoryClasses);
}
for (final MethodMetadataBuilder fieldInitializerMethod : getFieldMutatorMethods()) {
builder.addMethod(fieldInitializerMethod);
}
addCollaboratingFieldsToBuilder(entityFactoryClasses);
builder.addMethod(getEmbeddedIdMutatorMethod(entityFactoryClasses));
itdTypeDetails = builder.build();
}
private void addCollaboratingFieldsToBuilder(
final Set<ClassOrInterfaceTypeDetails> entityFactoryClasses) {
final Set<JavaSymbolName> fields = new LinkedHashSet<JavaSymbolName>();
for (final JavaType entityNeedingCollaborator : this.requiredDataOnDemandCollaborators) {
final JavaType collaboratorType =
getCollaboratingType(entityNeedingCollaborator, entityFactoryClasses);
if (collaboratorType != null) {
final String collaboratingFieldName =
getCollaboratingFieldName(entityNeedingCollaborator, entityFactoryClasses)
.getSymbolName();
final JavaSymbolName fieldSymbolName = new JavaSymbolName(collaboratingFieldName);
final FieldMetadata candidate = governorTypeDetails.getField(fieldSymbolName);
if (candidate != null) {
// We really expect the field to be correct if we're going to
// rely on it
Validate
.isTrue(candidate.getFieldType().equals(collaboratorType),
"Field '%s' on '%s' must be of type '%s'", collaboratingFieldName,
destination.getFullyQualifiedTypeName(),
collaboratorType.getFullyQualifiedTypeName());
Validate.isTrue(Modifier.isPrivate(candidate.getModifier()),
"Field '%s' on '%s' must be private", collaboratingFieldName,
destination.getFullyQualifiedTypeName());
Validate.notNull(
MemberFindingUtils.getAnnotationOfType(candidate.getAnnotations(), AUTOWIRED),
"Field '%s' on '%s' must be @Autowired", collaboratingFieldName,
destination.getFullyQualifiedTypeName());
// It's ok, so we can move onto the new field
continue;
}
// Create field and add it to the ITD, if it hasn't already been
if (!fields.contains(fieldSymbolName)) {
// Must make the field
final List<AnnotationMetadataBuilder> annotations =
new ArrayList<AnnotationMetadataBuilder>();
annotations.add(new AnnotationMetadataBuilder(AUTOWIRED));
builder.addField(new FieldMetadataBuilder(getId(), 0, annotations, fieldSymbolName,
collaboratorType));
fields.add(fieldSymbolName);
}
}
}
}
private void addEmbeddedClassFieldMutatorMethodsToBuilder(final EmbeddedHolder embeddedHolder,
final Set<ClassOrInterfaceTypeDetails> dataOnDemandClasses) {
final JavaType embeddedFieldType = embeddedHolder.getEmbeddedField().getFieldType();
final JavaType[] parameterTypes = {embeddedFieldType, JavaType.INT_PRIMITIVE};
final List<JavaSymbolName> parameterNames = Arrays.asList(OBJ_SYMBOL, INDEX_SYMBOL);
for (final FieldMetadata field : embeddedHolder.getFields()) {
final String initializer = getFieldInitializer(field, null, dataOnDemandClasses);
final JavaSymbolName fieldMutatorMethodName =
BeanInfoUtils.getMutatorMethodName(field.getFieldName());
final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
bodyBuilder.append(getFieldValidationBody(field, initializer, fieldMutatorMethodName, false));
final JavaSymbolName embeddedClassMethodName =
getEmbeddedFieldMutatorMethodName(embeddedHolder.getEmbeddedField().getFieldName(),
field.getFieldName());
if (governorHasMethod(embeddedClassMethodName, parameterTypes)) {
// Method found in governor so do not create method in ITD
continue;
}
builder.addMethod(new MethodMetadataBuilder(getId(), Modifier.PUBLIC,
embeddedClassMethodName, JavaType.VOID_PRIMITIVE, AnnotatedJavaType
.convertFromJavaTypes(parameterTypes), parameterNames, bodyBuilder));
}
}
private String getColumnPrecisionAndScaleBody(final FieldMetadata field,
final Map<String, Object> values, final String suffix) {
if (values == null || !values.containsKey("precision")) {
return InvocableMemberBodyBuilder.getInstance().getOutput();
}
final String fieldName = field.getFieldName().getSymbolName();
final JavaType fieldType = field.getFieldType();
Integer precision = (Integer) values.get("precision");
Integer scale = (Integer) values.get("scale");
if (precision != null && scale != null && precision < scale) {
scale = 0;
}
final BigDecimal maxValue;
if (scale == null || scale == 0) {
maxValue = new BigDecimal(StringUtils.rightPad("9", precision, '9'));
} else {
maxValue =
new BigDecimal(StringUtils.rightPad("9", precision - scale, '9') + "."
+ StringUtils.rightPad("9", scale, '9'));
}
final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
if (fieldType.equals(BIG_DECIMAL)) {
bodyBuilder.appendFormalLine("if (" + fieldName + ".compareTo(new "
+ BIG_DECIMAL.getSimpleTypeName() + "(\"" + maxValue + "\")) == 1) {");
bodyBuilder.indent();
bodyBuilder.appendFormalLine(fieldName + " = new " + BIG_DECIMAL.getSimpleTypeName() + "(\""
+ maxValue + "\");");
} else {
bodyBuilder.appendFormalLine("if (" + fieldName + " > " + maxValue.doubleValue() + suffix
+ ") {");
bodyBuilder.indent();
bodyBuilder.appendFormalLine(fieldName + " = " + maxValue.doubleValue() + suffix + ";");
}
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
return bodyBuilder.getOutput();
}
private JavaSymbolName getCollaboratingFieldName(final JavaType entity,
final Set<ClassOrInterfaceTypeDetails> dataOnDemandClasses) {
JavaSymbolName symbolName = null;
JavaType collaboratingType = getCollaboratingType(entity, dataOnDemandClasses);
if (collaboratingType != null) {
symbolName =
new JavaSymbolName(StringUtils.uncapitalize(collaboratingType.getSimpleTypeName()));
}
return symbolName;
}
private JavaType getCollaboratingType(final JavaType entity,
final Set<ClassOrInterfaceTypeDetails> entityFactoryClasses) {
JavaType dataOnDemand = null;
for (ClassOrInterfaceTypeDetails dataOnDemandClass : entityFactoryClasses) {
String searchDataOnDemand = entity.getSimpleTypeName().concat("DataOnDemand");
if (dataOnDemandClass.getType().getSimpleTypeName().equals(searchDataOnDemand)
&& governorTypeDetails.getType().getModule()
.equals(dataOnDemandClass.getType().getModule())) {
dataOnDemand = dataOnDemandClass.getType();
}
}
return dataOnDemand;
}
private MethodMetadata getCreateMethod() {
// Define methodName
final JavaSymbolName methodName = CREATE_FACTORY_METHOD_NAME;
List<JavaType> parameterTypes = new ArrayList<JavaType>();
parameterTypes.add(JavaType.INT_PRIMITIVE);
// Check if method exists
MethodMetadata existingMethod = getGovernorMethod(methodName, parameterTypes);
if (existingMethod != null) {
return existingMethod;
}
List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(INDEX_SYMBOL);
// Add body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
// Entity obj = new Entity();
bodyBuilder.appendFormalLine("%1$s %2$s = new %1$s();", getNameOfJavaType(this.entity),
OBJ_SYMBOL);
// Set values for transient object
for (final Map.Entry<FieldMetadata, JpaEntityFactoryMetadata> entry : locatedFields.entrySet()) {
bodyBuilder.appendFormalLine("%s(%s, %s);",
BeanInfoUtils.getMutatorMethodName(entry.getKey()), OBJ_SYMBOL, INDEX_SYMBOL);
}
// return obj;
bodyBuilder.appendFormalLine("return %s;", OBJ_SYMBOL);
// Create method
MethodMetadataBuilder method =
new MethodMetadataBuilder(this.getId(), Modifier.PUBLIC, methodName, this.entity,
AnnotatedJavaType.convertFromJavaTypes(parameterTypes), parameterNames, bodyBuilder);
CommentStructure commentStructure = new CommentStructure();
List<String> paramsInfo = new ArrayList<String>();
paramsInfo.add(String.format("%s position of the %s", INDEX_VAR,
this.entity.getSimpleTypeName()));
JavadocComment comment =
new JavadocComment(String.format("Creates a new {@link %s} with the given %s.",
this.entity.getSimpleTypeName(), INDEX_VAR), paramsInfo, String.format(
"a new transient %s", this.entity.getSimpleTypeName()), null);
commentStructure.addComment(comment, CommentLocation.BEGINNING);
method.setCommentStructure(commentStructure);
return method.build();
}
private String getDecimalMinAndDecimalMaxBody(final FieldMetadata field,
final AnnotationMetadata decimalMinAnnotation, final AnnotationMetadata decimalMaxAnnotation,
final String suffix) {
final String fieldName = field.getFieldName().getSymbolName();
final JavaType fieldType = field.getFieldType();
final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
if (decimalMinAnnotation != null && decimalMaxAnnotation == null) {
final String minValue = (String) decimalMinAnnotation.getAttribute(VALUE).getValue();
if (fieldType.equals(BIG_DECIMAL)) {
bodyBuilder.appendFormalLine("if (" + fieldName + ".compareTo(new "
+ BIG_DECIMAL.getSimpleTypeName() + "(\"" + minValue + "\")) == -1) {");
bodyBuilder.indent();
bodyBuilder.appendFormalLine(fieldName + " = new " + BIG_DECIMAL.getSimpleTypeName()
+ "(\"" + minValue + "\");");
} else {
bodyBuilder.appendFormalLine("if (" + fieldName + " < " + minValue + suffix + ") {");
bodyBuilder.indent();
bodyBuilder.appendFormalLine(fieldName + " = " + minValue + suffix + ";");
}
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
} else if (decimalMinAnnotation == null && decimalMaxAnnotation != null) {
final String maxValue = (String) decimalMaxAnnotation.getAttribute(VALUE).getValue();
if (fieldType.equals(BIG_DECIMAL)) {
bodyBuilder.appendFormalLine("if (" + fieldName + ".compareTo(new "
+ BIG_DECIMAL.getSimpleTypeName() + "(\"" + maxValue + "\")) == 1) {");
bodyBuilder.indent();
bodyBuilder.appendFormalLine(fieldName + " = new " + BIG_DECIMAL.getSimpleTypeName()
+ "(\"" + maxValue + "\");");
} else {
bodyBuilder.appendFormalLine("if (" + fieldName + " > " + maxValue + suffix + ") {");
bodyBuilder.indent();
bodyBuilder.appendFormalLine(fieldName + " = " + maxValue + suffix + ";");
}
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
} else if (decimalMinAnnotation != null && decimalMaxAnnotation != null) {
final String minValue = (String) decimalMinAnnotation.getAttribute(VALUE).getValue();
final String maxValue = (String) decimalMaxAnnotation.getAttribute(VALUE).getValue();
Validate
.isTrue(
Double.parseDouble(maxValue) >= Double.parseDouble(minValue),
"The value of @DecimalMax must be greater or equal to the value of @DecimalMin for field %s",
fieldName);
if (fieldType.equals(BIG_DECIMAL)) {
bodyBuilder.appendFormalLine("if (" + fieldName + ".compareTo(new "
+ BIG_DECIMAL.getSimpleTypeName() + "(\"" + minValue + "\")) == -1 || " + fieldName
+ ".compareTo(new " + BIG_DECIMAL.getSimpleTypeName() + "(\"" + maxValue
+ "\")) == 1) {");
bodyBuilder.indent();
bodyBuilder.appendFormalLine(fieldName + " = new " + BIG_DECIMAL.getSimpleTypeName()
+ "(\"" + maxValue + "\");");
} else {
bodyBuilder.appendFormalLine("if (" + fieldName + " < " + minValue + suffix + " || "
+ fieldName + " > " + maxValue + suffix + ") {");
bodyBuilder.indent();
bodyBuilder.appendFormalLine(fieldName + " = " + maxValue + suffix + ";");
}
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
}
return bodyBuilder.getOutput();
}
private String getDigitsBody(final FieldMetadata field,
final AnnotationMetadata digitsAnnotation, final String suffix) {
final String fieldName = field.getFieldName().getSymbolName();
final JavaType fieldType = field.getFieldType();
final Integer integerValue =
(Integer) digitsAnnotation.getAttribute(new JavaSymbolName("integer")).getValue();
final Integer fractionValue =
(Integer) digitsAnnotation.getAttribute(new JavaSymbolName("fraction")).getValue();
final BigDecimal maxValue =
new BigDecimal(StringUtils.rightPad("9", integerValue, '9') + "."
+ StringUtils.rightPad("9", fractionValue, '9'));
final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
if (fieldType.equals(BIG_DECIMAL)) {
bodyBuilder.appendFormalLine("if (" + fieldName + ".compareTo(new "
+ BIG_DECIMAL.getSimpleTypeName() + "(\"" + maxValue + "\")) == 1) {");
bodyBuilder.indent();
bodyBuilder.appendFormalLine(fieldName + " = new " + BIG_DECIMAL.getSimpleTypeName() + "(\""
+ maxValue + "\");");
} else {
bodyBuilder.appendFormalLine("if (" + fieldName + " > " + maxValue.doubleValue() + suffix
+ ") {");
bodyBuilder.indent();
bodyBuilder.appendFormalLine(fieldName + " = " + maxValue.doubleValue() + suffix + ";");
}
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
return bodyBuilder.getOutput();
}
private String getFieldInitializer(final FieldMetadata field,
final JpaEntityFactoryMetadata collaboratingMetadata,
final Set<ClassOrInterfaceTypeDetails> dataOnDemandClasses) {
final JavaType fieldType = field.getFieldType();
final String fieldName = field.getFieldName().getSymbolName();
String initializer = "null";
final String fieldInitializer = field.getFieldInitializer();
final Set<Object> fieldCustomDataKeys = field.getCustomData().keySet();
// Date fields included for DataNucleus (
if (fieldType.equals(DATE)) {
if (MemberFindingUtils.getAnnotationOfType(field.getAnnotations(), PAST) != null) {
builder.getImportRegistrationResolver().addImport(DATE);
initializer = "new Date(new Date().getTime() - 10000000L)";
} else if (MemberFindingUtils.getAnnotationOfType(field.getAnnotations(), FUTURE) != null) {
builder.getImportRegistrationResolver().addImport(DATE);
initializer = "new Date(new Date().getTime() + 10000000L)";
} else {
builder.getImportRegistrationResolver().addImports(CALENDAR, GREGORIAN_CALENDAR);
initializer =
"new GregorianCalendar(Calendar.getInstance().get(Calendar.YEAR), \n\t\t\tCalendar.getInstance().get(Calendar.MONTH), \n\t\t\tCalendar.getInstance().get(Calendar.DAY_OF_MONTH), \n\t\t\tCalendar.getInstance().get(Calendar.HOUR_OF_DAY), \n\t\t\tCalendar.getInstance().get(Calendar.MINUTE), \n\t\t\tCalendar.getInstance().get(Calendar.SECOND) + \n\t\t\tnew Double(Math.random() * 1000).intValue()).getTime()";
}
} else if (fieldType.equals(CALENDAR)) {
builder.getImportRegistrationResolver().addImports(CALENDAR, GREGORIAN_CALENDAR);
final String calendarString =
"new GregorianCalendar(Calendar.getInstance().get(Calendar.YEAR), \n\t\t\tCalendar.getInstance().get(Calendar.MONTH), \n\t\t\tCalendar.getInstance().get(Calendar.DAY_OF_MONTH)";
if (MemberFindingUtils.getAnnotationOfType(field.getAnnotations(), PAST) != null) {
initializer = calendarString + " - 1)";
} else if (MemberFindingUtils.getAnnotationOfType(field.getAnnotations(), FUTURE) != null) {
initializer = calendarString + " + 1)";
} else {
initializer = "Calendar.getInstance()";
}
} else if (fieldType.equals(TIMESTAMP)) {
builder.getImportRegistrationResolver().addImports(CALENDAR, GREGORIAN_CALENDAR, TIMESTAMP);
initializer =
"new Timestamp(new GregorianCalendar(Calendar.getInstance().get(Calendar.YEAR), \n\t\t\tCalendar.getInstance().get(Calendar.MONTH), \n\t\t\tCalendar.getInstance().get(Calendar.DAY_OF_MONTH), \n\t\t\tCalendar.getInstance().get(Calendar.HOUR_OF_DAY), \n\t\t\tCalendar.getInstance().get(Calendar.MINUTE), \n\t\t\tCalendar.getInstance().get(Calendar.SECOND) + \n\t\t\tnew Double(Math.random() * 1000).intValue()).getTime().getTime())";
} else if (fieldType.equals(STRING)) {
if (fieldInitializer != null && fieldInitializer.contains("\"")) {
final int offset = fieldInitializer.indexOf("\"");
initializer = fieldInitializer.substring(offset + 1, fieldInitializer.lastIndexOf("\""));
} else {
initializer = fieldName;
}
if (MemberFindingUtils.getAnnotationOfType(field.getAnnotations(),
VALIDATOR_CONSTRAINTS_EMAIL) != null || fieldName.toLowerCase().contains("email")) {
initializer = "\"foo\" + " + INDEX_VAR + " + \"@bar.com\"";
} else {
int maxLength = Integer.MAX_VALUE;
// Check for @Size
final AnnotationMetadata sizeAnnotation =
MemberFindingUtils.getAnnotationOfType(field.getAnnotations(), SIZE);
if (sizeAnnotation != null) {
final AnnotationAttributeValue<?> maxValue = sizeAnnotation.getAttribute(MAX_SYMBOL);
if (maxValue != null) {
validateNumericAnnotationAttribute(fieldName, "@Size", "max", maxValue.getValue());
maxLength = ((Integer) maxValue.getValue()).intValue();
}
final AnnotationAttributeValue<?> minValue = sizeAnnotation.getAttribute(MIN_SYMBOL);
if (minValue != null) {
validateNumericAnnotationAttribute(fieldName, "@Size", "min", minValue.getValue());
final int minLength = ((Integer) minValue.getValue()).intValue();
Validate.isTrue(maxLength >= minLength,
"@Size attribute 'max' must be greater than 'min' for field '%s' in %s", fieldName,
entity.getFullyQualifiedTypeName());
if (initializer.length() + 2 < minLength) {
initializer =
String.format("%1$-" + (minLength - 2) + "s", initializer).replace(' ', 'x');
}
}
} else {
if (field.getCustomData().keySet().contains(CustomDataKeys.COLUMN_FIELD)) {
@SuppressWarnings("unchecked")
final Map<String, Object> columnValues =
(Map<String, Object>) field.getCustomData().get(CustomDataKeys.COLUMN_FIELD);
if (columnValues.keySet().contains("length")) {
final Object lengthValue = columnValues.get("length");
validateNumericAnnotationAttribute(fieldName, "@Column", "length", lengthValue);
maxLength = ((Integer) lengthValue).intValue();
}
}
}
switch (maxLength) {
case 0:
initializer = "\"\"";
break;
case 1:
initializer = "String.valueOf(" + INDEX_VAR + ")";
break;
case 2:
initializer = "\"" + initializer.charAt(0) + "\" + " + INDEX_VAR;
break;
default:
if (initializer.length() + 2 > maxLength) {
initializer = "\"" + initializer.substring(0, maxLength - 2) + "_\" + " + INDEX_VAR;
} else {
initializer = "\"" + initializer + "_\" + " + INDEX_VAR;
}
}
}
} else if (fieldType.equals(new JavaType(STRING.getFullyQualifiedTypeName(), 1, DataType.TYPE,
null, null))) {
initializer = StringUtils.defaultIfEmpty(fieldInitializer, "{ \"Y\", \"N\" }");
} else if (fieldType.equals(JavaType.BOOLEAN_OBJECT)) {
initializer = StringUtils.defaultIfEmpty(fieldInitializer, "Boolean.TRUE");
} else if (fieldType.equals(JavaType.BOOLEAN_PRIMITIVE)) {
initializer = StringUtils.defaultIfEmpty(fieldInitializer, "true");
} else if (fieldType.equals(JavaType.INT_OBJECT)) {
initializer = StringUtils.defaultIfEmpty(fieldInitializer, "new Integer(" + INDEX_VAR + ")");
} else if (fieldType.equals(JavaType.INT_PRIMITIVE)) {
initializer = StringUtils.defaultIfEmpty(fieldInitializer, INDEX_VAR);
} else if (fieldType.equals(new JavaType(JavaType.INT_OBJECT.getFullyQualifiedTypeName(), 1,
DataType.PRIMITIVE, null, null))) {
initializer =
StringUtils.defaultIfEmpty(fieldInitializer, "{ " + INDEX_VAR + ", " + INDEX_VAR + " }");
} else if (fieldType.equals(JavaType.DOUBLE_OBJECT)) {
initializer =
StringUtils.defaultIfEmpty(fieldInitializer, "new Integer(" + INDEX_VAR
+ ").doubleValue()"); // Auto-boxed
} else if (fieldType.equals(JavaType.DOUBLE_PRIMITIVE)) {
initializer =
StringUtils.defaultIfEmpty(fieldInitializer, "new Integer(" + INDEX_VAR
+ ").doubleValue()");
} else if (fieldType.equals(new JavaType(JavaType.DOUBLE_OBJECT.getFullyQualifiedTypeName(), 1,
DataType.PRIMITIVE, null, null))) {
initializer =
StringUtils.defaultIfEmpty(fieldInitializer, "{ new Integer(" + INDEX_VAR
+ ").doubleValue(), new Integer(" + INDEX_VAR + ").doubleValue() }");
} else if (fieldType.equals(JavaType.FLOAT_OBJECT)) {
initializer =
StringUtils.defaultIfEmpty(fieldInitializer, "new Integer(" + INDEX_VAR
+ ").floatValue()"); // Auto-boxed
} else if (fieldType.equals(JavaType.FLOAT_PRIMITIVE)) {
initializer =
StringUtils.defaultIfEmpty(fieldInitializer, "new Integer(" + INDEX_VAR
+ ").floatValue()");
} else if (fieldType.equals(new JavaType(JavaType.FLOAT_OBJECT.getFullyQualifiedTypeName(), 1,
DataType.PRIMITIVE, null, null))) {
initializer =
StringUtils.defaultIfEmpty(fieldInitializer, "{ new Integer(" + INDEX_VAR
+ ").floatValue(), new Integer(" + INDEX_VAR + ").floatValue() }");
} else if (fieldType.equals(JavaType.LONG_OBJECT)) {
initializer =
StringUtils
.defaultIfEmpty(fieldInitializer, "new Integer(" + INDEX_VAR + ").longValue()"); // Auto-boxed
} else if (fieldType.equals(JavaType.LONG_PRIMITIVE)) {
initializer =
StringUtils
.defaultIfEmpty(fieldInitializer, "new Integer(" + INDEX_VAR + ").longValue()");
} else if (fieldType.equals(new JavaType(JavaType.LONG_OBJECT.getFullyQualifiedTypeName(), 1,
DataType.PRIMITIVE, null, null))) {
initializer =
StringUtils.defaultIfEmpty(fieldInitializer, "{ new Integer(" + INDEX_VAR
+ ").longValue(), new Integer(" + INDEX_VAR + ").longValue() }");
} else if (fieldType.equals(JavaType.SHORT_OBJECT)) {
initializer =
StringUtils.defaultIfEmpty(fieldInitializer, "new Integer(" + INDEX_VAR
+ ").shortValue()"); // Auto-boxed
} else if (fieldType.equals(JavaType.SHORT_PRIMITIVE)) {
initializer =
StringUtils.defaultIfEmpty(fieldInitializer, "new Integer(" + INDEX_VAR
+ ").shortValue()");
} else if (fieldType.equals(new JavaType(JavaType.SHORT_OBJECT.getFullyQualifiedTypeName(), 1,
DataType.PRIMITIVE, null, null))) {
initializer =
StringUtils.defaultIfEmpty(fieldInitializer, "{ new Integer(" + INDEX_VAR
+ ").shortValue(), new Integer(" + INDEX_VAR + ").shortValue() }");
} else if (fieldType.equals(JavaType.CHAR_OBJECT)) {
initializer = StringUtils.defaultIfEmpty(fieldInitializer, "new Character('N')");
} else if (fieldType.equals(JavaType.CHAR_PRIMITIVE)) {
initializer = StringUtils.defaultIfEmpty(fieldInitializer, "'N'");
} else if (fieldType.equals(new JavaType(JavaType.CHAR_OBJECT.getFullyQualifiedTypeName(), 1,
DataType.PRIMITIVE, null, null))) {
initializer = StringUtils.defaultIfEmpty(fieldInitializer, "{ 'Y', 'N' }");
} else if (fieldType.equals(BIG_DECIMAL)) {
builder.getImportRegistrationResolver().addImport(BIG_DECIMAL);
initializer = BIG_DECIMAL.getSimpleTypeName() + ".valueOf(" + INDEX_VAR + ")";
} else if (fieldType.equals(BIG_INTEGER)) {
builder.getImportRegistrationResolver().addImport(BIG_INTEGER);
initializer = BIG_INTEGER.getSimpleTypeName() + ".valueOf(" + INDEX_VAR + ")";
} else if (fieldType.equals(JavaType.BYTE_OBJECT)) {
initializer = "new Byte(" + StringUtils.defaultIfEmpty(fieldInitializer, "\"1\"") + ")";
} else if (fieldType.equals(JavaType.BYTE_PRIMITIVE)) {
initializer =
"new Byte(" + StringUtils.defaultIfEmpty(fieldInitializer, "\"1\"") + ").byteValue()";
} else if (fieldType.equals(JavaType.BYTE_ARRAY_PRIMITIVE)) {
initializer =
StringUtils.defaultIfEmpty(fieldInitializer, "String.valueOf(" + INDEX_VAR
+ ").getBytes()");
} else if (fieldType.equals(entity)) {
// Avoid circular references (ROO-562)
initializer = OBJ_VAR;
} else if (fieldCustomDataKeys.contains(CustomDataKeys.ENUMERATED_FIELD)) {
builder.getImportRegistrationResolver().addImport(fieldType);
initializer = fieldType.getSimpleTypeName() + ".class.getEnumConstants()[0]";
} else if (collaboratingMetadata != null && collaboratingMetadata.getEntityType() != null) {
requiredDataOnDemandCollaborators.add(fieldType);
initializer =
getFieldInitializerForRelatedEntity(field, collaboratingMetadata, fieldCustomDataKeys,
dataOnDemandClasses);
}
return initializer;
}
private String getFieldInitializerForRelatedEntity(final FieldMetadata field,
final JpaEntityFactoryMetadata collaboratingMetadata, final Set<?> fieldCustomDataKeys,
final Set<ClassOrInterfaceTypeDetails> dataOnDemandClasses) {
// To avoid circular references, we don't try to set nullable fields
final boolean nullableField =
field.getAnnotation(NOT_NULL) == null && isNullableJoinColumn(field);
if (nullableField) {
return null;
}
JavaSymbolName collaboratingFieldName =
getCollaboratingFieldName(field.getFieldType(), dataOnDemandClasses);
if (collaboratingFieldName != null) {
final String collaboratingName = collaboratingFieldName.getSymbolName();
if (fieldCustomDataKeys.contains(CustomDataKeys.ONE_TO_ONE_FIELD)) {
// We try to keep the same ID (ROO-568)
return collaboratingName + "." + SPECIFIC_METHOD_PREFIX.getSymbolName() + "(" + INDEX_VAR
+ ")";
}
return collaboratingName + "."
+ collaboratingMetadata.getRandomPersistentEntityMethod().getMethodName().getSymbolName()
+ "()";
} else {
return null;
}
}
private List<MethodMetadataBuilder> getFieldMutatorMethods() {
final List<MethodMetadataBuilder> fieldMutatorMethods = new ArrayList<MethodMetadataBuilder>();
final List<JavaSymbolName> parameterNames = Arrays.asList(OBJ_SYMBOL, INDEX_SYMBOL);
final JavaType[] parameterTypes = {entity, JavaType.INT_PRIMITIVE};
for (final Map.Entry<FieldMetadata, String> entry : fieldInitializers.entrySet()) {
final FieldMetadata field = entry.getKey();
final JavaSymbolName mutatorName = BeanInfoUtils.getMutatorMethodName(field.getFieldName());
// Locate user-defined method
if (governorHasMethod(mutatorName, parameterTypes)) {
// Method found in governor so do not create method in ITD
continue;
}
// Method not on governor so need to create it
final String initializer = entry.getValue();
if (!StringUtils.isBlank(initializer)) {
final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
bodyBuilder.append(getFieldValidationBody(field, initializer, mutatorName, false));
fieldMutatorMethods.add(new MethodMetadataBuilder(getId(), Modifier.PUBLIC, mutatorName,
JavaType.VOID_PRIMITIVE, AnnotatedJavaType.convertFromJavaTypes(parameterTypes),
parameterNames, bodyBuilder));
}
}
return fieldMutatorMethods;
}
private String getFieldValidationBody(final FieldMetadata field, final String initializer,
final JavaSymbolName mutatorName, final boolean isFieldOfEmbeddableType) {
final String fieldName = field.getFieldName().getSymbolName();
final JavaType fieldType = field.getFieldType();
String suffix = "";
if (fieldType.equals(JavaType.LONG_OBJECT) || fieldType.equals(JavaType.LONG_PRIMITIVE)) {
suffix = "L";
} else if (fieldType.equals(JavaType.FLOAT_OBJECT)
|| fieldType.equals(JavaType.FLOAT_PRIMITIVE)) {
suffix = "F";
} else if (fieldType.equals(JavaType.DOUBLE_OBJECT)
|| fieldType.equals(JavaType.DOUBLE_PRIMITIVE)) {
suffix = "D";
}
final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
bodyBuilder.appendFormalLine(getTypeStr(fieldType) + " " + fieldName + " = " + initializer
+ ";");
if (fieldType.equals(JavaType.STRING)) {
boolean isUnique = isFieldOfEmbeddableType;
@SuppressWarnings("unchecked")
final Map<String, Object> values =
(Map<String, Object>) field.getCustomData().get(CustomDataKeys.COLUMN_FIELD);
if (!isUnique && values != null && values.containsKey("unique")) {
isUnique = (Boolean) values.get("unique");
}
// Check for @Size or @Column with length attribute
final AnnotationMetadata sizeAnnotation =
MemberFindingUtils.getAnnotationOfType(field.getAnnotations(), SIZE);
if (sizeAnnotation != null && sizeAnnotation.getAttribute(MAX_SYMBOL) != null) {
final Integer maxValue = (Integer) sizeAnnotation.getAttribute(MAX_SYMBOL).getValue();
bodyBuilder.appendFormalLine("if (" + fieldName + ".length() > " + maxValue + ") {");
bodyBuilder.indent();
if (isUnique) {
bodyBuilder.appendFormalLine(fieldName + " = new Random().nextInt(10) + " + fieldName
+ ".substring(1, " + maxValue + ");");
} else {
bodyBuilder.appendFormalLine(fieldName + " = " + fieldName + ".substring(0, " + maxValue
+ ");");
}
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
} else if (sizeAnnotation == null && values != null) {
if (values.containsKey("length")) {
final Integer lengthValue = (Integer) values.get("length");
bodyBuilder.appendFormalLine("if (" + fieldName + ".length() > " + lengthValue + ") {");
bodyBuilder.indent();
if (isUnique) {
bodyBuilder.appendFormalLine(fieldName + " = new Random().nextInt(10) + " + fieldName
+ ".substring(1, " + lengthValue + ");");
} else {
bodyBuilder.appendFormalLine(fieldName + " = " + fieldName + ".substring(0, "
+ lengthValue + ");");
}
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
}
}
} else if (JdkJavaType.isDecimalType(fieldType)) {
// Check for @Digits, @DecimalMax, @DecimalMin
final AnnotationMetadata digitsAnnotation =
MemberFindingUtils.getAnnotationOfType(field.getAnnotations(), DIGITS);
final AnnotationMetadata decimalMinAnnotation =
MemberFindingUtils.getAnnotationOfType(field.getAnnotations(), DECIMAL_MIN);
final AnnotationMetadata decimalMaxAnnotation =
MemberFindingUtils.getAnnotationOfType(field.getAnnotations(), DECIMAL_MAX);
if (digitsAnnotation != null) {
bodyBuilder.append(getDigitsBody(field, digitsAnnotation, suffix));
} else if (decimalMinAnnotation != null || decimalMaxAnnotation != null) {
bodyBuilder.append(getDecimalMinAndDecimalMaxBody(field, decimalMinAnnotation,
decimalMaxAnnotation, suffix));
} else if (field.getCustomData().keySet().contains(CustomDataKeys.COLUMN_FIELD)) {
@SuppressWarnings("unchecked")
final Map<String, Object> values =
(Map<String, Object>) field.getCustomData().get(CustomDataKeys.COLUMN_FIELD);
bodyBuilder.append(getColumnPrecisionAndScaleBody(field, values, suffix));
}
} else if (JdkJavaType.isIntegerType(fieldType)) {
// Check for @Min and @Max
bodyBuilder.append(getMinAndMaxBody(field, suffix));
}
if (mutatorName != null) {
bodyBuilder.appendFormalLine(OBJ_VAR + "." + mutatorName.getSymbolName() + "(" + fieldName
+ ");");
}
return bodyBuilder.getOutput();
}
private MethodMetadataBuilder getEmbeddedClassMutatorMethod(final EmbeddedHolder embeddedHolder) {
final JavaSymbolName methodName =
getEmbeddedFieldMutatorMethodName(embeddedHolder.getEmbeddedField().getFieldName());
final JavaType[] parameterTypes = {entity, JavaType.INT_PRIMITIVE};
// Locate user-defined method
if (governorHasMethod(methodName, parameterTypes)) {
// Method found in governor so do not create method in ITD
return null;
}
final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
// Create constructor for embedded class
final JavaType embeddedFieldType = embeddedHolder.getEmbeddedField().getFieldType();
builder.getImportRegistrationResolver().addImport(embeddedFieldType);
bodyBuilder.appendFormalLine(embeddedFieldType.getSimpleTypeName() + " embeddedClass = new "
+ embeddedFieldType.getSimpleTypeName() + "();");
for (final FieldMetadata field : embeddedHolder.getFields()) {
bodyBuilder.appendFormalLine(getEmbeddedFieldMutatorMethodName(
embeddedHolder.getEmbeddedField().getFieldName(), field.getFieldName()).getSymbolName()
+ "(embeddedClass, " + INDEX_VAR + ");");
}
bodyBuilder.appendFormalLine(OBJ_VAR + "." + embeddedHolder.getEmbeddedMutatorMethodName()
+ "(embeddedClass);");
final List<JavaSymbolName> parameterNames = Arrays.asList(OBJ_SYMBOL, INDEX_SYMBOL);
return new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName, JavaType.VOID_PRIMITIVE,
AnnotatedJavaType.convertFromJavaTypes(parameterTypes), parameterNames, bodyBuilder);
}
private MethodMetadataBuilder getEmbeddedIdMutatorMethod(
final Set<ClassOrInterfaceTypeDetails> dataOnDemandClasses) {
if (!hasEmbeddedIdentifier()) {
return null;
}
final JavaSymbolName embeddedIdMutator = embeddedIdHolder.getEmbeddedIdMutator();
final JavaSymbolName methodName = getEmbeddedIdMutatorMethodName();
final JavaType[] parameterTypes = {entity, JavaType.INT_PRIMITIVE};
// Locate user-defined method
if (governorHasMethod(methodName, parameterTypes)) {
// Method found in governor so do not create method in ITD
return null;
}
final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
// Create constructor for embedded id class
final JavaType embeddedIdFieldType = embeddedIdHolder.getEmbeddedIdField().getFieldType();
builder.getImportRegistrationResolver().addImport(embeddedIdFieldType);
final StringBuilder sb = new StringBuilder();
final List<FieldMetadata> identifierFields = embeddedIdHolder.getIdFields();
for (int i = 0, n = identifierFields.size(); i < n; i++) {
if (i > 0) {
sb.append(", ");
}
final FieldMetadata field = identifierFields.get(i);
final String fieldName = field.getFieldName().getSymbolName();
final JavaType fieldType = field.getFieldType();
builder.getImportRegistrationResolver().addImport(fieldType);
final String initializer = getFieldInitializer(field, null, dataOnDemandClasses);
bodyBuilder.append(getFieldValidationBody(field, initializer, null, true));
sb.append(fieldName);
}
bodyBuilder.appendFormalLine("");
bodyBuilder.appendFormalLine(embeddedIdFieldType.getSimpleTypeName()
+ " embeddedIdClass = new " + embeddedIdFieldType.getSimpleTypeName() + "(" + sb.toString()
+ ");");
bodyBuilder.appendFormalLine(OBJ_VAR + "." + embeddedIdMutator + "(embeddedIdClass);");
final List<JavaSymbolName> parameterNames = Arrays.asList(OBJ_SYMBOL, INDEX_SYMBOL);
return new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName, JavaType.VOID_PRIMITIVE,
AnnotatedJavaType.convertFromJavaTypes(parameterTypes), parameterNames, bodyBuilder);
}
private String getMinAndMaxBody(final FieldMetadata field, final String suffix) {
final String fieldName = field.getFieldName().getSymbolName();
final JavaType fieldType = field.getFieldType();
final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
final AnnotationMetadata minAnnotation =
MemberFindingUtils.getAnnotationOfType(field.getAnnotations(), MIN);
final AnnotationMetadata maxAnnotation =
MemberFindingUtils.getAnnotationOfType(field.getAnnotations(), MAX);
if (minAnnotation != null && maxAnnotation == null) {
final Number minValue = (Number) minAnnotation.getAttribute(VALUE).getValue();
if (fieldType.equals(BIG_INTEGER)) {
bodyBuilder.appendFormalLine("if (" + fieldName + ".compareTo(new "
+ BIG_INTEGER.getSimpleTypeName() + "(\"" + minValue + "\")) == -1) {");
bodyBuilder.indent();
bodyBuilder.appendFormalLine(fieldName + " = new " + BIG_INTEGER.getSimpleTypeName()
+ "(\"" + minValue + "\");");
} else {
bodyBuilder.appendFormalLine("if (" + fieldName + " < " + minValue + suffix + ") {");
bodyBuilder.indent();
bodyBuilder.appendFormalLine(fieldName + " = " + minValue + suffix + ";");
}
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
} else if (minAnnotation == null && maxAnnotation != null) {
final Number maxValue = (Number) maxAnnotation.getAttribute(VALUE).getValue();
if (fieldType.equals(BIG_INTEGER)) {
bodyBuilder.appendFormalLine("if (" + fieldName + ".compareTo(new "
+ BIG_INTEGER.getSimpleTypeName() + "(\"" + maxValue + "\")) == 1) {");
bodyBuilder.indent();
bodyBuilder.appendFormalLine(fieldName + " = new " + BIG_INTEGER.getSimpleTypeName()
+ "(\"" + maxValue + "\");");
} else {
bodyBuilder.appendFormalLine("if (" + fieldName + " > " + maxValue + suffix + ") {");
bodyBuilder.indent();
bodyBuilder.appendFormalLine(fieldName + " = " + maxValue + suffix + ";");
}
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
} else if (minAnnotation != null && maxAnnotation != null) {
final Number minValue = (Number) minAnnotation.getAttribute(VALUE).getValue();
final Number maxValue = (Number) maxAnnotation.getAttribute(VALUE).getValue();
Validate
.isTrue(maxValue.longValue() >= minValue.longValue(),
"The value of @Max must be greater or equal to the value of @Min for field %s",
fieldName);
if (fieldType.equals(BIG_INTEGER)) {
bodyBuilder.appendFormalLine("if (" + fieldName + ".compareTo(new "
+ BIG_INTEGER.getSimpleTypeName() + "(\"" + minValue + "\")) == -1 || " + fieldName
+ ".compareTo(new " + BIG_INTEGER.getSimpleTypeName() + "(\"" + maxValue
+ "\")) == 1) {");
bodyBuilder.indent();
bodyBuilder.appendFormalLine(fieldName + " = new " + BIG_INTEGER.getSimpleTypeName()
+ "(\"" + maxValue + "\");");
} else {
bodyBuilder.appendFormalLine("if (" + fieldName + " < " + minValue + suffix + " || "
+ fieldName + " > " + maxValue + suffix + ") {");
bodyBuilder.indent();
bodyBuilder.appendFormalLine(fieldName + " = " + maxValue + suffix + ";");
}
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
}
return bodyBuilder.getOutput();
}
private String getTypeStr(final JavaType fieldType) {
builder.getImportRegistrationResolver().addImport(fieldType);
final String arrayStr = fieldType.isArray() ? "[]" : "";
String typeStr = fieldType.getSimpleTypeName();
if (fieldType.getFullyQualifiedTypeName().equals(
JavaType.FLOAT_PRIMITIVE.getFullyQualifiedTypeName())
&& fieldType.isPrimitive()) {
typeStr = "float" + arrayStr;
} else if (fieldType.getFullyQualifiedTypeName().equals(
JavaType.DOUBLE_PRIMITIVE.getFullyQualifiedTypeName())
&& fieldType.isPrimitive()) {
typeStr = "double" + arrayStr;
} else if (fieldType.getFullyQualifiedTypeName().equals(
JavaType.INT_PRIMITIVE.getFullyQualifiedTypeName())
&& fieldType.isPrimitive()) {
typeStr = "int" + arrayStr;
} else if (fieldType.getFullyQualifiedTypeName().equals(
JavaType.SHORT_PRIMITIVE.getFullyQualifiedTypeName())
&& fieldType.isPrimitive()) {
typeStr = "short" + arrayStr;
} else if (fieldType.getFullyQualifiedTypeName().equals(
JavaType.BYTE_PRIMITIVE.getFullyQualifiedTypeName())
&& fieldType.isPrimitive()) {
typeStr = "byte" + arrayStr;
} else if (fieldType.getFullyQualifiedTypeName().equals(
JavaType.CHAR_PRIMITIVE.getFullyQualifiedTypeName())
&& fieldType.isPrimitive()) {
typeStr = "char" + arrayStr;
} else if (fieldType.equals(new JavaType(STRING.getFullyQualifiedTypeName(), 1, DataType.TYPE,
null, null))) {
typeStr = "String[]";
}
return typeStr;
}
private boolean isNullableJoinColumn(final FieldMetadata field) {
final AnnotationMetadata joinColumnAnnotation = field.getAnnotation(JOIN_COLUMN);
if (joinColumnAnnotation == null) {
return true;
}
final AnnotationAttributeValue<?> nullableAttr =
joinColumnAnnotation.getAttribute(new JavaSymbolName("nullable"));
return nullableAttr == null || (Boolean) nullableAttr.getValue();
}
private void validateNumericAnnotationAttribute(final String fieldName,
final String annotationName, final String attributeName, final Object object) {
Validate.isTrue(NumberUtils.isNumber(object.toString()),
"%s '%s' attribute for field '%s' in backing type %s must be numeric", annotationName,
attributeName, fieldName, entity.getFullyQualifiedTypeName());
}
public JavaSymbolName getCreateFactoryMethodName() {
return JpaEntityFactoryMetadata.CREATE_FACTORY_METHOD_NAME;
}
public JavaSymbolName getEmbeddedFieldMutatorMethodName(final JavaSymbolName fieldName) {
return BeanInfoUtils.getMutatorMethodName(fieldName);
}
public JavaSymbolName getEmbeddedFieldMutatorMethodName(final JavaSymbolName embeddedFieldName,
final JavaSymbolName fieldName) {
return getEmbeddedFieldMutatorMethodName(new JavaSymbolName(embeddedFieldName.getSymbolName()
+ StringUtils.capitalize(fieldName.getSymbolName())));
}
public List<EmbeddedHolder> getEmbeddedHolders() {
return this.embeddedHolders;
}
public JavaSymbolName getEmbeddedIdMutatorMethodName() {
final List<JavaSymbolName> fieldNames = new ArrayList<JavaSymbolName>();
for (final FieldMetadata field : fieldInitializers.keySet()) {
fieldNames.add(field.getFieldName());
}
int index = -1;
JavaSymbolName embeddedIdField;
while (true) {
// Compute the required field name
index++;
embeddedIdField = new JavaSymbolName("embeddedIdClass" + StringUtils.repeat("_", index));
if (!fieldNames.contains(embeddedIdField)) {
// Found a usable name
break;
}
}
return BeanInfoUtils.getMutatorMethodName(embeddedIdField);
}
public JavaType getEntityType() {
return this.entity;
}
/**
* Returns the {@link JavaType} representing the physical type of this ITD governor.
*
* @return the {@link JavaType} for the governor physical type.
*/
public JavaType getGovernorType() {
return this.governorPhysicalTypeMetadata.getType();
}
/**
* @return the "getRandomEntity():Entity" method (never returns null)
*/
public MethodMetadata getRandomPersistentEntityMethod() {
return randomPersistentEntityMethod;
}
public boolean hasEmbeddedIdentifier() {
return this.embeddedIdHolder != null;
}
@Override
public String toString() {
final ToStringBuilder builder = new ToStringBuilder(this);
builder.append("identifier", getId());
builder.append("valid", valid);
builder.append("aspectName", aspectName);
builder.append("destinationType", destination);
builder.append("governor", governorPhysicalTypeMetadata.getId());
builder.append("itdTypeDetails", itdTypeDetails);
return builder.toString();
}
}