/*
* gvNIX is an open source tool for rapid application development (RAD).
* Copyright (C) 2010 Generalitat Valenciana
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.gvnix.addon.jpa.addon.batch;
import static org.springframework.roo.model.JdkJavaType.LIST;
import static org.springframework.roo.model.JdkJavaType.MAP;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.gvnix.addon.jpa.addon.audit.JpaAuditMetadata;
import org.gvnix.addon.jpa.annotations.batch.GvNIXJpaBatch;
import org.gvnix.support.ItdBuilderHelper;
import org.springframework.roo.addon.jpa.addon.activerecord.JpaActiveRecordMetadata;
import org.springframework.roo.addon.jpa.addon.activerecord.JpaCrudAnnotationValues;
import org.springframework.roo.classpath.PhysicalTypeIdentifierNamingUtils;
import org.springframework.roo.classpath.PhysicalTypeMetadata;
import org.springframework.roo.classpath.details.FieldMetadata;
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.AnnotationMetadataBuilder;
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.JpaJavaType;
import org.springframework.roo.model.SpringJavaType;
import org.springframework.roo.project.LogicalPath;
/**
* ITD generator for {@link GvNIXJpaBatch} annotation.
*
* @author <a href="http://www.disid.com">DISID Corporation S.L.</a> made for <a
* href="http://www.dgti.gva.es">General Directorate for Information
* Technologies (DGTI)</a>
* @since 1.1.0
*/
public class JpaBatchMetadata extends
AbstractItdTypeDetailsProvidingMetadataItem {
private static final JavaSymbolName FIND_BY_VALUES_METHOD = new JavaSymbolName(
"findByValues");
private static final JavaSymbolName DELETE_BY_VALUES_METHOD = new JavaSymbolName(
"deleteByValues");
public static final JavaSymbolName DELETE_ALL_METHOD = new JavaSymbolName(
"deleteAll");
public static final JavaSymbolName DELETE_NOT_IN_METHOD = new JavaSymbolName(
"deleteNotIn");
public static final JavaSymbolName DELETE_IN_METHOD = new JavaSymbolName(
"deleteIn");
public static final JavaSymbolName DELETE_METHOD = new JavaSymbolName(
"delete");
public static final JavaSymbolName UPDATE_METHOD = new JavaSymbolName(
"update");
public static final JavaSymbolName CREATE_METHOD = new JavaSymbolName(
"create");
// Constants
private static final String PROVIDES_TYPE_STRING = JpaBatchMetadata.class
.getName();
private static final String PROVIDES_TYPE = MetadataIdentificationUtils
.create(PROVIDES_TYPE_STRING);
static final JavaType MAP_STRING_STRING = new JavaType(
MAP.getFullyQualifiedTypeName(), 0, DataType.TYPE, null,
Arrays.asList(JavaType.STRING, JavaType.STRING));
static final JavaType MAP_STRING_OBJECT = new JavaType(
MAP.getFullyQualifiedTypeName(), 0, DataType.TYPE, null,
Arrays.asList(JavaType.STRING, JavaType.OBJECT));
static final JavaType QDSL_BOOLEAN_BUILDER = new JavaType(
"com.mysema.query.BooleanBuilder");
static final JavaType QDSL_PATH_BUILDER = new JavaType(
"com.mysema.query.types.path.PathBuilder");
static final JavaType QDSL_JPA_QUERY = new JavaType(
"com.mysema.query.jpa.impl.JPAQuery");
static final JavaType QDSL_JPA_DELETE_CLAUSE = new JavaType(
"com.mysema.query.jpa.impl.JPADeleteClause");
public static final String getMetadataIdentiferType() {
return PROVIDES_TYPE;
}
public static final String createIdentifier(JavaType javaType,
LogicalPath path) {
return PhysicalTypeIdentifierNamingUtils.createIdentifier(
PROVIDES_TYPE_STRING, javaType, path);
}
public static final JavaType getJavaType(String metadataIdentificationString) {
return PhysicalTypeIdentifierNamingUtils.getJavaType(
PROVIDES_TYPE_STRING, metadataIdentificationString);
}
public static final LogicalPath getPath(String metadataIdentificationString) {
return PhysicalTypeIdentifierNamingUtils.getPath(PROVIDES_TYPE_STRING,
metadataIdentificationString);
}
public static boolean isValid(String metadataIdentificationString) {
return PhysicalTypeIdentifierNamingUtils.isValid(PROVIDES_TYPE_STRING,
metadataIdentificationString);
}
private final JpaBatchAnnotationValues annotationValues;
private final JavaType entity;
private final FieldMetadata entityIdentifier;
private final JavaType listOfIdentifiersType;
private final JavaType listOfEntitiesType;
private final String entityName;
/**
* Itd builder herlper
*/
private ItdBuilderHelper helper;
/** Related entity plural */
private final String entityPlural;
/** Audit metadata information (if any) **/
private final JpaAuditMetadata auditMetadata;
/** If target entity has any EntityListener registered **/
private final boolean hasEntityListeners;
/** use or not UPDATE/DELETE bulk statements for operations **/
private final boolean useBulkStatements;
public JpaBatchMetadata(String identifier, JavaType aspectName,
PhysicalTypeMetadata governorPhysicalTypeMetadata,
JpaBatchAnnotationValues annotationValues,
List<FieldMetadata> identifiers, String entityPlural,
JpaAuditMetadata auditMetada, boolean hasEntityListeners) {
super(identifier, aspectName, governorPhysicalTypeMetadata);
Validate.isTrue(isValid(identifier), "Metadata identification string '"
+ identifier + "' does not appear to be a valid");
this.annotationValues = annotationValues;
// Helper itd generation
this.helper = new ItdBuilderHelper(this, governorPhysicalTypeMetadata,
builder.getImportRegistrationResolver());
// Get refereed entity
this.entity = annotationValues.entity;
// Roo only use one field for pk
this.entityIdentifier = identifiers.iterator().next();
// Store auditMetadata
this.auditMetadata = auditMetada;
// Store if entity has any listeners
this.hasEntityListeners = hasEntityListeners;
// Use bulk statements only for entities with no audit set and haven't
// any entityListener registered
this.useBulkStatements = this.auditMetadata == null
&& !this.hasEntityListeners;
// Get entity name
this.entityName = entity.getSimpleTypeName();
// Get entity plural name
this.entityPlural = entityPlural;
this.listOfIdentifiersType = new JavaType(
LIST.getFullyQualifiedTypeName(), 0, DataType.TYPE, null,
Arrays.asList(entityIdentifier.getFieldType()));
this.listOfEntitiesType = new JavaType(
LIST.getFullyQualifiedTypeName(), 0, DataType.TYPE, null,
Arrays.asList(entity.getBaseType()));
builder.addMethod(getGetEntityMethod());
builder.addMethod(getEntityManagerMethod());
builder.addMethod(getDeleteAllMethod());
builder.addMethod(getDeleteInMethod());
builder.addMethod(getDeleteNotInMethod());
builder.addMethod(getCreateMethod());
builder.addMethod(getUpdateMethod());
builder.addMethod(getFindByValuesMethod());
builder.addMethod(getDeleteByValuesMethod());
builder.addMethod(getDeleteMethod());
// Create a representation of the desired output ITD
itdTypeDetails = builder.build();
}
/**
* Gets <code>deleteByValuesMethod</code> method. <br>
* This method performs a delete base on property values condition (value
* equal and concatenates conditions using "and" operator)
*
* @return
*/
private MethodMetadata getDeleteByValuesMethod() {
// Define method parameter types
List<AnnotatedJavaType> parameterTypes = AnnotatedJavaType
.convertFromJavaTypes(MAP_STRING_OBJECT);
// Check if a method with the same signature already exists in the
// target type
final MethodMetadata method = methodExists(DELETE_BY_VALUES_METHOD,
parameterTypes);
if (method != null) {
// If it already exists, just return the method and omit its
// generation via the ITD
return method;
}
// Define method annotations
List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
annotations.add(new AnnotationMetadataBuilder(
SpringJavaType.TRANSACTIONAL));
// Define method throws types (none in this case)
List<JavaType> throwsTypes = new ArrayList<JavaType>();
// Define method parameter names
List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(new JavaSymbolName("propertyValues"));
// Create the method body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
buildDeleteByValuesMethodBody(bodyBuilder);
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
getId(), Modifier.PUBLIC, DELETE_BY_VALUES_METHOD,
JavaType.LONG_PRIMITIVE, parameterTypes, parameterNames,
bodyBuilder);
methodBuilder.setAnnotations(annotations);
methodBuilder.setThrowsTypes(throwsTypes);
return methodBuilder.build(); // Build and return a MethodMetadata
// instance
}
/**
* Builds body method for <code>deleteByValues</code> method. <br>
* This method performs a delete base on property values condition (value
* equal and concatenates conditions using "and" operator)
*
* @param bodyBuilder
*/
private void buildDeleteByValuesMethodBody(
InvocableMemberBodyBuilder bodyBuilder) {
if (useBulkStatements) {
//
bodyBuilder.appendFormalLine("");
//
// // if there no is a filter
bodyBuilder.appendFormalLine("// if there no is a filter");
// if (propertyValues == null || propertyValues.isEmpty()) {
bodyBuilder
.appendFormalLine("if (propertyValues == null || propertyValues.isEmpty()) {");
bodyBuilder.indent();
// throw new IllegalArgumentException("Missing property values");
bodyBuilder
.appendFormalLine("throw new IllegalArgumentException(\"Missing property values\");");
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
// // Prepare a predicate
bodyBuilder.appendFormalLine("// Prepare a predicate");
// BooleanBuilder baseFilterPredicate = new BooleanBuilder();
bodyBuilder.appendFormalLine(String.format(
"%s baseFilterPredicate = new %s();",
helper.getFinalTypeName(QDSL_BOOLEAN_BUILDER),
helper.getFinalTypeName(QDSL_BOOLEAN_BUILDER)));
bodyBuilder.appendFormalLine("");
// // Base filter. Using BooleanBuilder, a cascading builder for
bodyBuilder
.appendFormalLine("// Base filter. Using BooleanBuilder, a cascading builder for");
// // Predicate expressions
bodyBuilder.appendFormalLine("// Predicate expressions");
// PathBuilder<Visit> entity = new PathBuilder<Visit>(Visit.class,
// "entity");
bodyBuilder.appendFormalLine(String.format(
"%s<%s> entity = new %s<%s>(%s.class, \"entity\");",
helper.getFinalTypeName(QDSL_PATH_BUILDER),
helper.getFinalTypeName(entity),
helper.getFinalTypeName(QDSL_PATH_BUILDER),
helper.getFinalTypeName(entity),
helper.getFinalTypeName(entity)));
bodyBuilder.appendFormalLine("");
//
// // Build base filter
bodyBuilder.appendFormalLine("// Build base filter");
// for (String key : propertyMap.keySet()) {
bodyBuilder
.appendFormalLine("for (String key : propertyValues.keySet()) {");
bodyBuilder.indent();
// baseFilterPredicate.and(entity.get(key).eq(propertyMap.get(key)));
bodyBuilder
.appendFormalLine("baseFilterPredicate.and(entity.get(key).eq(propertyValues.get(key)));");
// }
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
bodyBuilder.appendFormalLine("");
//
// // Create a query with filter
bodyBuilder.appendFormalLine("// Create a query with filter");
// JPADeleteClause delete = new
// JPADeleteClause(Visit.entityManager(),entity);
bodyBuilder.appendFormalLine(String.format(
"%s delete = new %s(%s.entityManager(),entity);",
helper.getFinalTypeName(QDSL_JPA_DELETE_CLAUSE),
helper.getFinalTypeName(QDSL_JPA_DELETE_CLAUSE),
helper.getFinalTypeName(entity)));
//
bodyBuilder.appendFormalLine("");
// // execute delete
bodyBuilder.appendFormalLine("// execute delete");
// return delete.where(baseFilterPredicate).execute();
bodyBuilder
.appendFormalLine("return delete.where(baseFilterPredicate).execute();");
}
else {
// List<Visit> visits = findByValues(propertyValues);
bodyBuilder.appendFormalLine(String.format(
"%s %s = %s(propertyValues);",
helper.getFinalTypeName(listOfEntitiesType),
StringUtils.uncapitalize(entityPlural),
FIND_BY_VALUES_METHOD));
// delete(visits);
bodyBuilder.appendFormalLine(String.format("%s(%s);",
DELETE_METHOD, StringUtils.uncapitalize(entityPlural)));
// return (long)visits.size();
bodyBuilder.appendFormalLine(String.format(
"return (long)%s.size();",
StringUtils.uncapitalize(entityPlural)));
}
}
/**
* Gets <code>findByParameters</code> method. <br>
* This method generates a item List based on a list of entity values.
*
* @return
*/
private MethodMetadata getFindByValuesMethod() {
// Define method parameter types
List<AnnotatedJavaType> parameterTypes = AnnotatedJavaType
.convertFromJavaTypes(MAP_STRING_OBJECT);
// Check if a method with the same signature already exists in the
// target type
final MethodMetadata method = methodExists(FIND_BY_VALUES_METHOD,
parameterTypes);
if (method != null) {
// If it already exists, just return the method and omit its
// generation via the ITD
return method;
}
// Define method annotations
List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
// Define method throws types (none in this case)
List<JavaType> throwsTypes = new ArrayList<JavaType>();
// Define method parameter names
List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(new JavaSymbolName("propertyValues"));
// Create the method body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
buildFindByValuesMethodBody(bodyBuilder);
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
getId(), Modifier.PUBLIC, FIND_BY_VALUES_METHOD,
listOfEntitiesType, parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
methodBuilder.setThrowsTypes(throwsTypes);
return methodBuilder.build(); // Build and return a MethodMetadata
// instance
}
/**
* Builds body method for <code>findByValues</code> method. <br>
* This method generates a item List based on a list of entity values.
*
* @param bodyBuilder
*/
private void buildFindByValuesMethodBody(
InvocableMemberBodyBuilder bodyBuilder) {
//
bodyBuilder.appendFormalLine("");
//
// // if there is a filter
bodyBuilder.appendFormalLine("// if there is a filter");
// if (propertyValues != null && !propertyValues.isEmpty()) {
bodyBuilder
.appendFormalLine("if (propertyValues != null && !propertyValues.isEmpty()) {");
bodyBuilder.indent();
// // Prepare a predicate
bodyBuilder.appendFormalLine("// Prepare a predicate");
// BooleanBuilder baseFilterPredicate = new BooleanBuilder();
bodyBuilder.appendFormalLine(String.format(
"%s baseFilterPredicate = new %s();",
helper.getFinalTypeName(QDSL_BOOLEAN_BUILDER),
helper.getFinalTypeName(QDSL_BOOLEAN_BUILDER)));
bodyBuilder.appendFormalLine("");
// // Base filter. Using BooleanBuilder, a cascading builder for
bodyBuilder
.appendFormalLine("// Base filter. Using BooleanBuilder, a cascading builder for");
// // Predicate expressions
bodyBuilder.appendFormalLine("// Predicate expressions");
// PathBuilder<Visit> entity = new PathBuilder<Visit>(Visit.class,
// "entity");
bodyBuilder.appendFormalLine(String.format(
"%s<%s> entity = new %s<%s>(%s.class, \"entity\");",
helper.getFinalTypeName(QDSL_PATH_BUILDER),
helper.getFinalTypeName(entity),
helper.getFinalTypeName(QDSL_PATH_BUILDER),
helper.getFinalTypeName(entity),
helper.getFinalTypeName(entity)));
bodyBuilder.appendFormalLine("");
//
// // Build base filter
bodyBuilder.appendFormalLine("// Build base filter");
// for (String key : propertyMap.keySet()) {
bodyBuilder
.appendFormalLine("for (String key : propertyValues.keySet()) {");
bodyBuilder.indent();
// baseFilterPredicate.and(entity.get(key).eq(propertyMap.get(key)));
bodyBuilder
.appendFormalLine("baseFilterPredicate.and(entity.get(key).eq(propertyValues.get(key)));");
// }
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
bodyBuilder.appendFormalLine("");
//
// // Create a query with filter
bodyBuilder.appendFormalLine("// Create a query with filter");
// JPAQuery query = new JPAQuery(Visit.entityManager());
bodyBuilder.appendFormalLine(String.format(
"%s query = new %s(%s.entityManager());",
helper.getFinalTypeName(QDSL_JPA_QUERY),
helper.getFinalTypeName(QDSL_JPA_QUERY),
helper.getFinalTypeName(entity)));
// query = query.from(entity);
bodyBuilder.appendFormalLine("query = query.from(entity);");
//
bodyBuilder.appendFormalLine("");
// // execute query
bodyBuilder.appendFormalLine("// execute query");
// return query.where(baseFilterPredicate).list(entity);
bodyBuilder
.appendFormalLine("return query.where(baseFilterPredicate).list(entity);");
// }
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
bodyBuilder.appendFormalLine("");
//
// // no filter: return all elements
bodyBuilder.appendFormalLine("// no filter: return all elements");
// return Visit.findAllVisits();
bodyBuilder.appendFormalLine(String.format("return %s.findAll%s();",
helper.getFinalTypeName(entity),
StringUtils.capitalize(entityPlural)));
}
/**
* Return method <code>getEntity</code>
*
* @return
*/
private MethodMetadata getGetEntityMethod() {
// method name
JavaSymbolName methodName = new JavaSymbolName("getEntity");
// Check if a method exist in type
final MethodMetadata method = methodExists(methodName,
new ArrayList<AnnotatedJavaType>());
if (method != null) {
// If it already exists, just return the method
return method;
}
// Define method annotations (none in this case)
List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
// Define method throws types (none in this case)
List<JavaType> throwsTypes = new ArrayList<JavaType>();
// Define method parameter types (none in this case)
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
// Define method parameter names (none in this case)
List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
// Create the method body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
bodyBuilder.appendFormalLine(String.format("return %s.class;",
getFinalTypeName(entity)));
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
getId(), Modifier.PUBLIC, methodName, JavaType.CLASS,
parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
methodBuilder.setThrowsTypes(throwsTypes);
return methodBuilder.build(); // Build and return a MethodMetadata
// instance
}
/**
* Return method <code>entityManager</code>
*
* @return
*/
private MethodMetadata getEntityManagerMethod() {
// method name
JavaSymbolName methodName = new JavaSymbolName("entityManager");
// Check if a method exist in type
final MethodMetadata method = methodExists(methodName,
new ArrayList<AnnotatedJavaType>());
if (method != null) {
// If it already exists, just return the method
return method;
}
// Define method annotations (none in this case)
List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
// Define method throws types (none in this case)
List<JavaType> throwsTypes = new ArrayList<JavaType>();
// Define method parameter types (none in this case)
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
// Define method parameter names (none in this case)
List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
// Create the method body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
bodyBuilder.appendFormalLine(String.format(
"return %s.entityManager();", getFinalTypeName(entity)));
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
getId(), Modifier.PUBLIC, methodName,
JpaJavaType.ENTITY_MANAGER, parameterTypes, parameterNames,
bodyBuilder);
methodBuilder.setAnnotations(annotations);
methodBuilder.setThrowsTypes(throwsTypes);
return methodBuilder.build(); // Build and return a MethodMetadata
// instance
}
/**
* Return method <code>deleteAll</code>
*
* @return
*/
private MethodMetadata getDeleteAllMethod() {
// method name
JavaSymbolName methodName = DELETE_ALL_METHOD;
// Check if a method exist in type
final MethodMetadata method = methodExists(methodName,
new ArrayList<AnnotatedJavaType>());
if (method != null) {
// If it already exists, just return the method
return method;
}
// Define method annotations (none in this case)
List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
annotations.add(new AnnotationMetadataBuilder(
SpringJavaType.TRANSACTIONAL));
// Define method throws types (none in this case)
List<JavaType> throwsTypes = new ArrayList<JavaType>();
// Define method parameter types (none in this case)
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
// Define method parameter names (none in this case)
List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
// Create the method body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
buildDeleteAllMethodBody(bodyBuilder);
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
getId(), Modifier.PUBLIC, methodName, JavaType.INT_PRIMITIVE,
parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
methodBuilder.setThrowsTypes(throwsTypes);
return methodBuilder.build(); // Build and return a MethodMetadata
// instance
}
/**
* Build delete all method body
*
* @param bodyBuilder
*/
private void buildDeleteAllMethodBody(InvocableMemberBodyBuilder bodyBuilder) {
if (useBulkStatements) {
bodyBuilder
.appendFormalLine(String
.format("return entityManager().createQuery(\"DELETE FROM %s\").executeUpdate();",
entityName));
}
else {
// TypedQuery<Owner> query =
// entityManager().createQuery("Select o FROM Owner o",
// Owner.class);
bodyBuilder
.appendFormalLine(String
.format("%s<%s> query = entityManager().createQuery(\"Select o FROM %s o\", %s.class);",
helper.getFinalTypeName(JpaJavaType.TYPED_QUERY),
entityName, entityName, entityName));
// List<Owner> owners = query.getResultList();
bodyBuilder.appendFormalLine(String.format(
"%s %s = query.getResultList();",
helper.getFinalTypeName(listOfEntitiesType),
StringUtils.uncapitalize(entityPlural)));
// delete(owners);
bodyBuilder.appendFormalLine(String.format("%s(%s);",
DELETE_METHOD, StringUtils.uncapitalize(entityPlural)));
// return owners.size();
bodyBuilder.appendFormalLine(String.format("return %s.size();",
StringUtils.uncapitalize(entityPlural)));
}
}
/**
* Return method <code>deleteIn</code>
*
* @return
*/
private MethodMetadata getDeleteInMethod() {
return getDeleteByIdsListMethod(DELETE_IN_METHOD, "IN");
}
/**
* Return method <code>deleteNotIn</code>
*
* @return
*/
private MethodMetadata getDeleteNotInMethod() {
return getDeleteByIdsListMethod(DELETE_NOT_IN_METHOD, "NOT IN");
}
/**
* Return method to delete entity based on a list of pks of the entity
*
* @param methodName for generated method
* @param condition use IN or NOT IN delete-by-list operation
* @return
*/
private MethodMetadata getDeleteByIdsListMethod(JavaSymbolName methodName,
String condition) {
// Define parameters types
List<AnnotatedJavaType> parameterTypes = AnnotatedJavaType
.convertFromJavaTypes(listOfIdentifiersType);
// Check if a method exist in type
final MethodMetadata method = methodExists(methodName, parameterTypes);
if (method != null) {
// If it already exists, just return the method
return method;
}
// Define method annotations (none in this case)
List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
annotations.add(new AnnotationMetadataBuilder(
SpringJavaType.TRANSACTIONAL));
// Define method throws types (none in this case)
List<JavaType> throwsTypes = new ArrayList<JavaType>();
// Define method parameter names (none in this case)
JavaSymbolName parameterName = new JavaSymbolName("ids");
List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(parameterName);
// Create the method body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
buildDeleteByIdListMethod(condition, parameterName, bodyBuilder);
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
getId(), Modifier.PUBLIC, methodName, JavaType.INT_PRIMITIVE,
parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
methodBuilder.setThrowsTypes(throwsTypes);
return methodBuilder.build(); // Build and return a MethodMetadata
// instance
}
/**
* Build method body for delete method filter by element's id list
*
* @param condition
* @param parameterName
* @param bodyBuilder
*/
private void buildDeleteByIdListMethod(String condition,
JavaSymbolName parameterName, InvocableMemberBodyBuilder bodyBuilder) {
if (useBulkStatements) {
String aliasName = entity.getSimpleTypeName().toLowerCase()
.substring(0, 1);
// Query query =
// entityManager().createQuery("DELETE FROM Pet AS p WHERE p.id IN (:idList)");
bodyBuilder
.appendFormalLine(String
.format("%s query = entityManager().createQuery(\"DELETE FROM %s as %s WHERE %s.%s %s (:idList)\");",
getFinalTypeName(JpaJavaType.QUERY),
entityName, aliasName, aliasName,
entityIdentifier.getFieldName()
.getSymbolName(), condition));
// query.setParameter("list", ids);
bodyBuilder.appendFormalLine(String.format(
"query.setParameter(\"idList\", %s);",
parameterName.getSymbolName()));
// return query.executeUpdate();
bodyBuilder.appendFormalLine("return query.executeUpdate();");
}
else {
// TypedQuery<Owner> query =
// entityManager().createQuery("Select o FROM Owner o WHERE o.id IN (:idList)",
// Owner.class);
bodyBuilder
.appendFormalLine(String
.format("%s<%s> query = entityManager().createQuery(\"SELECT o FROM %s o WHERE o.%s %s (:idList)\", %s.class);",
getFinalTypeName(JpaJavaType.TYPED_QUERY),
entityName, entityName, entityIdentifier
.getFieldName().getSymbolName(),
condition, entityName));
// query.setParameter("list", ids);
bodyBuilder.appendFormalLine(String.format(
"query.setParameter(\"idList\", %s);",
parameterName.getSymbolName()));
// List<Owner> owners = query.getResultList();
bodyBuilder.appendFormalLine(String.format(
"%s %s = query.getResultList();",
helper.getFinalTypeName(listOfEntitiesType),
StringUtils.uncapitalize(entityPlural)));
// delete(owners);
bodyBuilder.appendFormalLine(String.format("delete(%s);",
StringUtils.uncapitalize(entityPlural)));
// return owners.size();
bodyBuilder.appendFormalLine(String.format("return %s.size();",
StringUtils.uncapitalize(entityPlural)));
}
}
private MethodMetadata methodExists(JavaSymbolName methodName,
List<AnnotatedJavaType> paramTypes) {
return MemberFindingUtils.getDeclaredMethod(governorTypeDetails,
methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(paramTypes));
}
/**
* Return method to create a list of entities
*
* @return
*/
private MethodMetadata getCreateMethod() {
// Define parameters types
List<AnnotatedJavaType> parameterTypes = AnnotatedJavaType
.convertFromJavaTypes(listOfEntitiesType);
// Check if a method exist in type
final MethodMetadata method = methodExists(CREATE_METHOD,
parameterTypes);
if (method != null) {
// If it already exists, just return the method
return method;
}
// Define method annotations (none in this case)
List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
annotations.add(new AnnotationMetadataBuilder(
SpringJavaType.TRANSACTIONAL));
// Define method throws types (none in this case)
List<JavaType> throwsTypes = new ArrayList<JavaType>();
// Define method parameter names (none in this case)
JavaSymbolName parameterName = new JavaSymbolName(
StringUtils.uncapitalize(entityPlural));
List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(parameterName);
// --- Create the method body ---
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
// for(Vet vet : vets) {
// vet.persist();
// }
bodyBuilder.appendFormalLine(String.format("for( %s %s : %s) {",
entityName, entityName.toLowerCase(), parameterName));
bodyBuilder.indent();
bodyBuilder.appendFormalLine(String.format("%s.persist();",
entityName.toLowerCase()));
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
JavaType returnType = JavaType.VOID_PRIMITIVE;
MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
getId(), Modifier.PUBLIC, CREATE_METHOD, returnType,
parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
methodBuilder.setThrowsTypes(throwsTypes);
return methodBuilder.build(); // Build and return a MethodMetadata
// instance
}
/**
* Return method to update a list of entities
*
* @return
*/
private MethodMetadata getUpdateMethod() {
// Define parameters types
List<AnnotatedJavaType> parameterTypes = AnnotatedJavaType
.convertFromJavaTypes(listOfEntitiesType);
// Check if a method exist in type
final MethodMetadata method = methodExists(UPDATE_METHOD,
parameterTypes);
if (method != null) {
// If it already exists, just return the method
return method;
}
// Define method annotations (none in this case)
List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
annotations.add(new AnnotationMetadataBuilder(
SpringJavaType.TRANSACTIONAL));
// Define method throws types (none in this case)
List<JavaType> throwsTypes = new ArrayList<JavaType>();
// Define method parameter names (none in this case)
JavaSymbolName parameterName = new JavaSymbolName(
entityPlural.toLowerCase());
List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(parameterName);
// --- Create the method body ---
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
List<JavaType> typeParams = new ArrayList<JavaType>();
typeParams.add(entity);
JavaType arrayList = new JavaType("java.util.ArrayList", 0,
DataType.TYPE, null, typeParams);
// List<Vet> merged = new ArrayList<Vet>();
bodyBuilder.appendFormalLine(String.format("%s merged = new %s();",
getFinalTypeName(listOfEntitiesType),
getFinalTypeName(arrayList)));
// for(Vet vet : vets) {
// merged.add( vet.merge() );
// }
// return merged;
bodyBuilder.appendFormalLine(String.format("for( %s %s : %s) {",
entityName, entityName.toLowerCase(), parameterName));
bodyBuilder.indent();
bodyBuilder.appendFormalLine(String.format("merged.add( %s.merge() );",
entityName.toLowerCase()));
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
bodyBuilder.appendFormalLine("return merged;");
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
getId(), Modifier.PUBLIC, UPDATE_METHOD, listOfEntitiesType,
parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
methodBuilder.setThrowsTypes(throwsTypes);
return methodBuilder.build(); // Build and return a MethodMetadata
// instance
}
/**
* Return method to delete a list of entities
*
* @return
*/
private MethodMetadata getDeleteMethod() {
// Define parameters types
List<AnnotatedJavaType> parameterTypes = AnnotatedJavaType
.convertFromJavaTypes(listOfEntitiesType);
// Check if a method exist in type
final MethodMetadata method = methodExists(DELETE_METHOD,
parameterTypes);
if (method != null) {
// If it already exists, just return the method
return method;
}
// Define method annotations (none in this case)
List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
annotations.add(new AnnotationMetadataBuilder(
SpringJavaType.TRANSACTIONAL));
// Define method throws types (none in this case)
List<JavaType> throwsTypes = new ArrayList<JavaType>();
// Define method parameter names (none in this case)
JavaSymbolName parameterName = new JavaSymbolName(
entityPlural.toLowerCase());
List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(parameterName);
// --- Create the method body ---
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
List<JavaType> typeParams = new ArrayList<JavaType>();
typeParams.add(entity);
// for(Vet vet : vets) {
// vet.remove() );
// }
bodyBuilder.appendFormalLine(String.format("for( %s %s : %s) {",
entityName, entityName.toLowerCase(), parameterName));
bodyBuilder.indent();
bodyBuilder.appendFormalLine(String.format("%s.remove();",
entityName.toLowerCase()));
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
getId(), Modifier.PUBLIC, DELETE_METHOD,
JavaType.VOID_PRIMITIVE, parameterTypes, parameterNames,
bodyBuilder);
methodBuilder.setAnnotations(annotations);
methodBuilder.setThrowsTypes(throwsTypes);
return methodBuilder.build(); // Build and return a MethodMetadata
// instance
}
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("entity", entity);
builder.append("itdTypeDetails", itdTypeDetails);
return builder.toString();
}
/**
* Get entity which batch operation affects to
*
* @return
*/
public JavaType getEntity() {
return entity;
}
/**
* Get {@link GvNIXJpaBatch} values
*
* @return
*/
public JpaBatchAnnotationValues getAnnotationValues() {
return annotationValues;
}
public FieldMetadata getEntityIdentifier() {
return entityIdentifier;
}
public JavaSymbolName getDeleteAllMethodName() {
return DELETE_ALL_METHOD;
}
public JavaSymbolName getDeleteInMethodName() {
return DELETE_IN_METHOD;
}
public JavaSymbolName getDeleteNotInMethodName() {
return DELETE_NOT_IN_METHOD;
}
public JavaType getListOfIdentifiersType() {
return listOfIdentifiersType;
}
public JavaType getListOfEntitiesType() {
return listOfEntitiesType;
}
/**
* Gets final names to use of a type in method body after import resolver.
*
* @param type
* @return name to use in method body
*/
private String getFinalTypeName(JavaType type) {
return type.getNameIncludingTypeParameters(false,
builder.getImportRegistrationResolver());
}
/**
* @return Entity name in plural
*/
public String getEntityPlural() {
return entityPlural;
}
/**
* @return deleteByValue method Name
*/
public JavaSymbolName getDeleteByValuesMethodName() {
return DELETE_BY_VALUES_METHOD;
}
/**
* @return if bulk JPA statements will be used
*/
public boolean isUseBulkStatements() {
return useBulkStatements;
}
}