/*
* 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.datatables.addon;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.ARRAYLIST_MAP_STRING_STRING;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.ARRAYLIST_STRING;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.ARRAY_UTILS;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.AUTOWIRED;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.BEAN_PROPERTY_BINDING_RESULT;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.BEAN_WRAPPER;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.BEAN_WRAPPER_IMP;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.BINDING_RESULT;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.CHECK_FILTERS_RETURN;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.CHECK_FILTER_EXPRESSIONS;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.COLLECTIONS;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.COLLECTION_UTILS;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.CONVERSION_SERVICE;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.CREATE_JSON_FORM_METHOD;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.CRITERIA_PARAM_NAME;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.DATATABLES_CRITERIA_TYPE;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.DATATABLES_CSV_EXPORT;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.DATATABLES_EXPORT;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.DATATABLES_EXPORT_CONF;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.DATATABLES_EXPORT_EXCEPTION;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.DATATABLES_EXPORT_NAME;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.DATATABLES_EXPORT_TYPE;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.DATATABLES_EXPORT_TYPE_NAME;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.DATATABLES_EXPORT_UTILS;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.DATATABLES_HTML_TABLE;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.DATATABLES_PARAMS;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.DATATABLES_PDF_EXPORT;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.DATATABLES_RESPONSE;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.DATATABLES_UTILS_BEAN;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.DATATABLES_XLSX_EXPORT;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.DATATABLES_XLS_EXPORT;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.DATATABLES_XML_EXPORT;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.DATA_SET_MAP_STRING_STRING;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.ENUMERATION_STRING;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.EXTENDED_MODEL_MAP;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.FIND_ALL_RETURN;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.GET_COLUMN_TYPE;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.GET_I18N_TEXT;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.GET_PROPERTY_MAP;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.HASHMAP_STRING_OBJECT;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.HASHMAP_STRING_STRING;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.HTTP_SERVLET_REQUEST;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.HTTP_SERVLET_RESPONSE;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.HTTP_SERVLET_RESPONSE_WRAPPER;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.IDS_PARAM_NAME;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.IO_EXCEPTION;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.LIST_DATATABLES;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.LIST_MAP_STRING_STRING;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.LIST_ROO;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.LIST_STRING;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.MAP_STRING_OBJECT;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.MAP_STRING_STRING;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.MESSAGE_SOURCE;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.POPULATE_DATATABLES_CONFIG;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.POPULATE_ITEM_FOR_RENDER;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.POPULATE_PARAMETERS_MAP;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.PRINT_WRITER;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.QDSL_BOOLEAN_BUILDER;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.QDSL_JPA_QUERY;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.QDSL_PATH_BUILDER;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.QUERYDSL_UTILS_BEAN;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.REDIRECT_ATTRIBUTES;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.REDIRECT_MODEL;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.RENDER_UPDATE_FORMS_METHOD;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.REQUEST_DISPATCHER;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.REQUEST_METHOD;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.REQUEST_PARAM_NAME;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.RESPONSE_PARAM_NAME;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.SEARCH_RESULTS;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.SERVLET_EXCEPTION;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.SET_STRING;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.STRING_UTILS;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.STRING_WRITER;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.UI_MODEL;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.UPDATE_JSON_FORMS_METHOD;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.VALID;
import static org.gvnix.addon.datatables.addon.DatatablesConstants.WEB_REQUEST;
import static org.springframework.roo.model.JdkJavaType.LIST;
import static org.springframework.roo.model.SpringJavaType.MODEL;
import static org.springframework.roo.model.SpringJavaType.MODEL_ATTRIBUTE;
import static org.springframework.roo.model.SpringJavaType.REQUEST_MAPPING;
import static org.springframework.roo.model.SpringJavaType.RESPONSE_BODY;
import java.io.File;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.gvnix.addon.datatables.annotations.GvNIXDatatables;
import org.gvnix.addon.jpa.addon.query.JpaQueryMetadata;
import org.gvnix.addon.web.mvc.addon.batch.WebJpaBatchMetadata;
import org.gvnix.support.WebItdBuilderHelper;
import org.springframework.roo.addon.finder.FieldToken;
import org.springframework.roo.addon.finder.ReservedToken;
import org.springframework.roo.addon.finder.Token;
import org.springframework.roo.addon.web.mvc.controller.addon.details.DateTimeFormatDetails;
import org.springframework.roo.addon.web.mvc.controller.addon.details.FinderMetadataDetails;
import org.springframework.roo.addon.web.mvc.controller.addon.details.JavaTypeMetadataDetails;
import org.springframework.roo.addon.web.mvc.controller.addon.details.WebMetadataService;
import org.springframework.roo.addon.web.mvc.controller.addon.scaffold.WebScaffoldAnnotationValues;
import org.springframework.roo.addon.web.mvc.controller.annotations.scaffold.RooWebScaffold;
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.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.annotations.StringAttributeValue;
import org.springframework.roo.classpath.details.comments.CommentStructure;
import org.springframework.roo.classpath.details.comments.JavadocComment;
import org.springframework.roo.classpath.itd.AbstractItdTypeDetailsProvidingMetadataItem;
import org.springframework.roo.classpath.itd.InvocableMemberBodyBuilder;
import org.springframework.roo.classpath.scanner.MemberDetails;
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.model.SpringJavaType;
import org.springframework.roo.project.LogicalPath;
import org.springframework.roo.project.Path;
import org.springframework.roo.project.PathResolver;
import org.springframework.roo.project.ProjectOperations;
import org.springframework.roo.support.logging.HandlerUtils;
/**
* {@link GvNIXDatatables} metadata
*
* @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 DatatablesMetadata extends
AbstractItdTypeDetailsProvidingMetadataItem {
private static final String DATATABLES_MANAGER_PROVIDER = "org.gvnix.web.datatables.util.EntityManagerProvider";
private static final String ENDING = "\");";
private static final String ELSE = "} else {";
private static final String JSON_APPEND = "json.append(\",\");";
private static final String COLTYPE_NUM = "return \"{\\\"columnType\\\": \\\"number\\\"}\";";
private static final String DATATABLES_REDIRECT = "datatablesRedirect";
private static final String PARAMETERS_AS_BASE_SEARCH = "// URL parameters are used as base search filters";
private static final String APPLICATION_JSON = "application/json";
private static final String HEADERS = "headers";
private static final String SIZE_VAR = "size";
private static final String SORT_FIELD_NAME = "sortFieldName";
private static final String SORT_ORDER = "sortOrder";
private static final String PAGE_VAR = "page";
private static final String PARAMS_VAR = "params";
private static final String METHOD_VAR = "method";
private static final String ACCEPT_APPLICATION_JSON = "Accept=application/json";
private static final JavaSymbolName SET_BASE_FILTER_METHOD = new JavaSymbolName(
"setDatatablesBaseFilter");
private static final JavaSymbolName EXPORT_METHOD_NAME = new JavaSymbolName(
"export");
private static final JavaSymbolName RETRIEVE_DATA_METHOD_NAME = new JavaSymbolName(
"retrieveData");
private static final JavaSymbolName DATATABLES_MANAGER_PROVIDER_NAME = new JavaSymbolName(
"entityManagerProvider_dtt");
private static final Logger LOGGER = HandlerUtils
.getLogger(DatatablesMetadata.class);
// Constants
private static final String PROVIDES_TYPE_STRING = DatatablesMetadata.class
.getName();
private static final String PROVIDES_TYPE = MetadataIdentificationUtils
.create(PROVIDES_TYPE_STRING);
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);
}
/**
* Annotation values
*/
private final DatatablesAnnotationValues annotationValues;
/**
* Entity property which is its identifier (as roo only use one property,
* this includes the embedded pks)
*/
private final FieldMetadata entityIdentifier;
/**
* Related entity
*/
private final JavaType entity;
/**
* Related entity member details
*/
private final MemberDetails entityMemberDetails;
/**
* Entity name to use in var names
*/
private final String entityName;
/**
* Related entity plural
*/
private final String entityPlural;
/**
* If related entity has date properties
*/
private final Map<JavaSymbolName, DateTimeFormatDetails> entityDatePatterns;
/**
* Batch services metadata
*/
private final WebJpaBatchMetadata webJpaBatchMetadata;
/**
* Jpa Query metadata
*/
private final JpaQueryMetadata jpaQueryMetadata;
/**
* Field which holds conversionService
*/
private FieldMetadata conversionService;
/**
* field which holds EntityManagerProvider
*/
private FieldMetadata entityManagerProvider;
/**
* Field which holds messageSource
*/
private FieldMetadata messageSource;
/**
* Field which holds beanWrapper
*/
private FieldMetadata beanWrapper;
/**
* Field which holds DatatablesUtilsBean
*/
private FieldMetadata datatablesUtilsBean;
/**
* Field which holds QuerydslUtilsBean
*/
private FieldMetadata querydslUtilsBean;
/**
* Itd builder helper
*/
private final WebItdBuilderHelper helper;
private final WebScaffoldAnnotationValues webScaffoldAnnotationValues;
/**
* Information about finders
*/
private final Map<FinderMetadataDetails, QueryHolderTokens> findersRegistered;
/**
* Name to use for findAll method (name includes entity plural )
*/
private final JavaSymbolName findAllMethodName;
/**
* Name to use for renderItem method (name includes entity plural)
*/
private final JavaSymbolName renderItemsMethodName;
/**
* Name to use for findByParamters method (name includes entity plural)
*/
private final JavaSymbolName findByParametersMethodName;
/**
* JavaType for List entity elements
*/
private final JavaType entityListType;
/**
* Web metadata service to get controller information
*/
private final WebMetadataService webMetadataService;
private final ProjectOperations projectOperations;
private final JavaType entityIdentifierType;
private final JavaType entityIdArrayType;
private final String entityList;
public DatatablesMetadata(String identifier, JavaType aspectName,
PhysicalTypeMetadata governorPhysicalTypeMetadata,
DatatablesAnnotationValues annotationValues, JavaType entity,
MemberDetails entityMemberDetails,
List<FieldMetadata> identifierProperties, String entityPlural,
Map<JavaSymbolName, DateTimeFormatDetails> datePatterns,
JavaType webScaffoldAspectName,
WebJpaBatchMetadata webJpaBatchMetadata,
JpaQueryMetadata jpaQueryMetadata,
WebScaffoldAnnotationValues webScaffoldAnnotationValues,
Map<FinderMetadataDetails, QueryHolderTokens> findersRegistered,
WebMetadataService webMetadataService,
ProjectOperations projectOperations) {
super(identifier, aspectName, governorPhysicalTypeMetadata);
Validate.isTrue(isValid(identifier), "Metadata identification string '"
+ identifier + "' does not appear to be a valid");
this.annotationValues = annotationValues;
this.helper = new WebItdBuilderHelper(this,
governorPhysicalTypeMetadata,
builder.getImportRegistrationResolver());
// Roo only uses one property
this.entityIdentifier = identifierProperties.get(0);
this.entityIdentifierType = entityIdentifier.getFieldType();
this.entity = entity;
this.entityMemberDetails = entityMemberDetails;
this.entityName = entity.getSimpleTypeName();
this.entityPlural = entityPlural;
this.entityDatePatterns = datePatterns;
this.webJpaBatchMetadata = webJpaBatchMetadata;
this.jpaQueryMetadata = jpaQueryMetadata;
this.webScaffoldAnnotationValues = webScaffoldAnnotationValues;
// Prepare method names which includes entity plural
this.findAllMethodName = new JavaSymbolName(
"findAll".concat(StringUtils.capitalize(entityPlural)));
this.renderItemsMethodName = new JavaSymbolName(
"render".concat(StringUtils.capitalize(entityPlural)));
this.findByParametersMethodName = new JavaSymbolName("find".concat(
StringUtils.capitalize(entityPlural)).concat("ByParameters"));
this.entityListType = new JavaType(LIST.getFullyQualifiedTypeName(), 0,
DataType.TYPE, null, Arrays.asList(entity));
this.entityList = StringUtils.uncapitalize(entityPlural);
// this.entityIdListType = new
// JavaType(LIST.getFullyQualifiedTypeName(),
// 0, DataType.TYPE, null, Arrays.asList(entityIdentifierType));
this.entityIdArrayType = new JavaType(
entityIdentifierType.getFullyQualifiedTypeName(), 1,
DataType.TYPE, null, null);
// store finders information
if (findersRegistered != null) {
this.findersRegistered = Collections
.unmodifiableMap(findersRegistered);
}
else {
this.findersRegistered = null;
}
this.webMetadataService = webMetadataService;
this.projectOperations = projectOperations;
// Adding precedence declaration
// This aspect before webScaffold
builder.setDeclarePrecedence(aspectName, webScaffoldAspectName);
// Adding field definition
builder.addField(getConversionServiceField());
builder.addField(getMessageSourceField());
builder.addField(getBeanWrapperField());
builder.addField(getEntityManagerProvider());
builder.addField(getDatatablesUtilsBean());
builder.addField(getQuerydslUtilsBean());
// Adding methods
builder.addMethod(getListDatatablesRequestMethod());
builder.addMethod(getPopulateDatatablesConfig());
builder.addMethod(getListRooRequestMethod());
builder.addMethod(getPopulateParameterMapMethod());
builder.addMethod(getGetPropertyMapMethod());
builder.addMethod(getGetPropertyMapUrlMethod());
builder.addMethod(getSetDatatablesBaseFilterMethod(annotationValues));
builder.addMethod(getColumnTypeRequestMethod());
builder.addMethod(geti18nTextRequestMethod());
// Detail methods
builder.addMethod(getListDatatablesDetailMethod());
builder.addMethod(getCreateDatatablesDetailMethod());
builder.addMethod(getUpdateDatatablesDetailMethod());
builder.addMethod(getDeleteDatatablesDetailMethod());
// Add AJAX mode required methods
if (isAjax()) {
if (isStantardMode()) {
builder.addMethod(getFindAllMethod());
// Adding filters methods
builder.addMethod(getCheckFilterExpressionsMethod());
}
else {
if (isInlineEditing()) {
// InlineEditing not supported on non-standard mode
throw new IllegalArgumentException(aspectName
.getFullyQualifiedTypeName()
.concat(".@GvNIXDatatables: 'mode = ")
.concat(annotationValues.getMode())
.concat("' can't use inlineEditing"));
}
// Render mode requires this methods
builder.addMethod(getPopulateItemForRenderMethod());
builder.addMethod(getRenderItemsMethod());
builder.addMethod(getFindAllMethodRenderMode());
}
// add ajax request for finders
if (this.findersRegistered != null) {
for (Entry<FinderMetadataDetails, QueryHolderTokens> finder : this.findersRegistered
.entrySet()) {
if (finder.getValue() != null) {
builder.addMethod(getAjaxFinderMethod(finder.getKey(),
finder.getValue()));
}
}
}
// Export via AJAX methods
addAjaxExportMethods();
}
else if (!isStantardMode()) {
// Non-Standard view mode requires AJAX data mode
throw new IllegalArgumentException(aspectName
.getFullyQualifiedTypeName()
.concat(".@GvNIXDatatables: 'mode = ")
.concat(annotationValues.getMode())
.concat("' requires 'ajax = true'"));
}
else {
// DOM standard mode requires finder by parameters
builder.addMethod(getFindByParametersMethod());
}
if (isInlineEditing()) {
if (!hasJpaBatchSupport()) {
// InlineEditing requires batch support
throw new IllegalArgumentException(
aspectName
.getFullyQualifiedTypeName()
.concat(". Inline editing requires batch support. Run 'jpa batch add' command or 'web mvc batch add' command"));
}
builder.addMethod(getJsonFormsMethod(true));
builder.addMethod(getJsonFormsMethod(false));
builder.addMethod(getRenderUpdateFormsMethod());
builder.addMethod(getPopulateItemForRenderMethod());
}
// Create a representation of the desired output ITD
itdTypeDetails = builder.build();
}
/**
* Return method to obtain JSon forms to create or update, depending if the
* parameter {@code isCreateJsonForm} is true or false.
*
* @param isCreateJsonForm true to return the method to obtain the create
* JSon form, false to obtain the update one.
* @return
*/
private MethodMetadata getJsonFormsMethod(boolean isCreateJsonForm) {
// method name
JavaSymbolName methodName = UPDATE_JSON_FORMS_METHOD;
if (isCreateJsonForm) {
methodName = CREATE_JSON_FORM_METHOD;
}
// Define method parameter types
final List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
if (!isCreateJsonForm) {
parameterTypes.add(helper.createRequestParam(entityIdArrayType,
"id", null, null));
}
parameterTypes.add(AnnotatedJavaType
.convertFromJavaType(HTTP_SERVLET_REQUEST));
parameterTypes.add(AnnotatedJavaType
.convertFromJavaType(HTTP_SERVLET_RESPONSE));
parameterTypes.add(AnnotatedJavaType.convertFromJavaType(MODEL));
// 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
List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
// @RequestMapping
String requestMappingValue = "/datatables/updateforms";
if (isCreateJsonForm) {
requestMappingValue = "/datatables/createform";
}
AnnotationMetadataBuilder requestMappingAnnotation = helper
.getRequestMappingAnnotation(requestMappingValue, null, null,
APPLICATION_JSON, null, ACCEPT_APPLICATION_JSON);
annotations.add(requestMappingAnnotation);
// @ResponseBody
AnnotationMetadataBuilder responseBodyAnnotation = new AnnotationMetadataBuilder();
responseBodyAnnotation.setAnnotationType(SpringJavaType.RESPONSE_BODY);
annotations.add(responseBodyAnnotation);
// Define method throws types (none in this case)
List<JavaType> throwsTypes = new ArrayList<JavaType>();
throwsTypes.add(SERVLET_EXCEPTION);
throwsTypes.add(IO_EXCEPTION);
// Define method parameter names (none in this case)
List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
if (!isCreateJsonForm) {
parameterNames.add(IDS_PARAM_NAME);
}
parameterNames.add(REQUEST_PARAM_NAME);
parameterNames.add(RESPONSE_PARAM_NAME);
parameterNames.add(UI_MODEL);
// Create the method body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
if (isCreateJsonForm) {
buildCreateJsonFormMethodBody(bodyBuilder);
}
else {
buildUpdateJsonFormsMethodBody(bodyBuilder);
}
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
getId(), Modifier.PUBLIC, methodName, LIST_MAP_STRING_STRING,
parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
methodBuilder.setThrowsTypes(throwsTypes);
return methodBuilder.build(); // Build and return a MethodMetadata
// instance
}
/**
* Build code for the method to obtain the update JSon forms.
*
* @param bodyBuilder the InvocableMemberBodyBuilder
*/
private void buildUpdateJsonFormsMethodBody(
InvocableMemberBodyBuilder bodyBuilder) {
// if (ArrayUtils.isEmpty(ids)) {
bodyBuilder.appendFormalLine(String.format("if (%s.isEmpty(ids)) {",
helper.getFinalTypeName(ARRAY_UTILS),
IDS_PARAM_NAME.getSymbolName()));
bodyBuilder.indent();
// return new ArrayList<Map<String, String>>();
bodyBuilder.appendFormalLine(String.format("return new %s();",
helper.getFinalTypeName(ARRAYLIST_MAP_STRING_STRING)));
// }
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
bodyBuilder.appendFormalLine("");
// // Using PathBuilder, a cascading builder for Predicate expressions
bodyBuilder
.appendFormalLine("// Using PathBuilder, a cascading builder for Predicate expressions");
// PathBuilder<Vet> entity = new PathBuilder<Vet>(Vet.class, "entity");
String pathBuilder = helper.getFinalTypeName(new JavaType(
QDSL_PATH_BUILDER.getFullyQualifiedTypeName(), entity));
bodyBuilder.appendFormalLine(String.format(
"%s entity = new %s(%s.class, \"entity\");", pathBuilder,
pathBuilder, helper.getFinalTypeName(entity)));
// // URL parameters are used as base search filters
bodyBuilder.appendFormalLine(PARAMETERS_AS_BASE_SEARCH);
// Set<Long> set = new HashSet<Long>();
bodyBuilder.appendFormalLine(String.format("%s set = new %s();", helper
.getFinalTypeName(new JavaType(JdkJavaType.SET
.getFullyQualifiedTypeName(), entityIdentifierType)),
helper.getFinalTypeName(new JavaType(JdkJavaType.HASH_SET
.getFullyQualifiedTypeName(), entityIdentifierType))));
// set.addAll(Arrays.asList(ids));
bodyBuilder.appendFormalLine(String.format(
"set.addAll(%s.asList(%s));",
helper.getFinalTypeName(JdkJavaType.ARRAYS),
IDS_PARAM_NAME.getSymbolName()));
// BooleanBuilder filterBy =
// querydslUtilsBean_dtt.createPredicateByIn(entity,
// "id", set);
bodyBuilder.appendFormalLine(String.format(
"%s filterBy = %s.createPredicateByIn(entity, \"%s\", set);",
helper.getFinalTypeName(QDSL_BOOLEAN_BUILDER),
getQuerydslUtilsBean().getFieldName().getSymbolName(),
entityIdentifier.getFieldName().getSymbolName()));
// // Create a query with filter
bodyBuilder.appendFormalLine("// Create a query with filter");
// JPAQuery query = new
// JPAQuery(entityManagerProvider_dtt.getEntityManager(Vet.class));
bodyBuilder.appendFormalLine(String.format(
"%s query = new %s(%s.getEntityManager(%s.class));",
helper.getFinalTypeName(QDSL_JPA_QUERY),
helper.getFinalTypeName(QDSL_JPA_QUERY),
DATATABLES_MANAGER_PROVIDER_NAME,
helper.getFinalTypeName(entity)));
// query = query.from(entity);
bodyBuilder.appendFormalLine("query = query.from(entity);");
// // execute query
bodyBuilder.appendFormalLine("// execute query");
// List<Vet> vets = query.where(filterBy).list(entity);
bodyBuilder.appendFormalLine(String.format(
"%s %s = query.where(filterBy).list(entity);",
helper.getFinalTypeName(entityListType), entityList));
// List<Map<String, String>> udpateForms = renderUpdateForm(vets,
// request, response);
bodyBuilder.appendFormalLine(String.format(
"%s udpateForms = %s(%s, request, response);",
helper.getFinalTypeName(LIST_MAP_STRING_STRING),
RENDER_UPDATE_FORMS_METHOD.getSymbolName(), entityList,
REQUEST_PARAM_NAME.getSymbolName(),
RESPONSE_PARAM_NAME.getSymbolName()));
// return udpateForms;
bodyBuilder.appendFormalLine("return udpateForms;");
}
/**
* Build code for the method to obtain the create JSon form.
*
* @param bodyBuilder the InvocableMemberBodyBuilder
*/
private void buildCreateJsonFormMethodBody(
InvocableMemberBodyBuilder bodyBuilder) {
// // Prepare result
bodyBuilder.appendFormalLine("");
bodyBuilder.appendFormalLine("// Prepare result");
// List<Map<String, String>> result = new ArrayList<Map<String,
// String>>();
bodyBuilder.appendFormalLine(String.format("%s result = new %s();",
helper.getFinalTypeName(LIST_MAP_STRING_STRING),
helper.getFinalTypeName(ARRAYLIST_MAP_STRING_STRING)));
// String controllerPath = "vets";
bodyBuilder.appendFormalLine(String.format(
"String controllerPath = \"%s\";",
webScaffoldAnnotationValues.getPath()));
// String pageToUse = "update";
bodyBuilder.appendFormalLine("String pageToUse = \"create\";");
// String renderUrl = String.format("/WEB-INF/views/%s/%s.jspx",
// controllerPath, pageToUse);
bodyBuilder
.appendFormalLine("String renderUrl = String.format(\"/WEB-INF/views/%s/%s.jspx\", controllerPath, pageToUse);");
bodyBuilder.appendFormalLine("");
// Map<String, String> item = new HashMap<String, String>();
bodyBuilder.appendFormalLine(String.format("%s item = new %s();",
helper.getFinalTypeName(MAP_STRING_STRING),
helper.getFinalTypeName(HASHMAP_STRING_STRING)));
// final StringWriter buffer = new StringWriter();
bodyBuilder.appendFormalLine(String.format(
"final %s buffer = new %s();",
helper.getFinalTypeName(STRING_WRITER),
helper.getFinalTypeName(STRING_WRITER)));
bodyBuilder.appendFormalLine("");
// // Call JSP to render update form
bodyBuilder.appendFormalLine("// Call JSP to render update form");
// RequestDispatcher dispatcher =
// request.getRequestDispatcher(renderUrl);
bodyBuilder.appendFormalLine(String.format(
"%s dispatcher = %s.getRequestDispatcher(renderUrl);",
helper.getFinalTypeName(REQUEST_DISPATCHER),
REQUEST_PARAM_NAME.getSymbolName()));
bodyBuilder.appendFormalLine("");
// // spring from:input tag uses BindingResult to locate property
// editors
// // for each bean property. So, we add a request attribute (required
// key
// // id BindingResult.MODEL_KEY_PREFIX + object name) with a correctly
// // initialized bindingResult.
bodyBuilder
.appendFormalLine("// spring from:input tag uses BindingResult to locate property editors");
bodyBuilder
.appendFormalLine("// for each bean property. So, we add a request attribute (required key");
bodyBuilder
.appendFormalLine("// id BindingResult.MODEL_KEY_PREFIX + object name) with a correctly");
bodyBuilder.appendFormalLine("// initialized bindingResult.");
// Vet vet = new Vet();
bodyBuilder.appendFormalLine(String.format("%s %s = new %s();",
helper.getFinalTypeName(entity), entityName,
helper.getFinalTypeName(entity)));
// BeanPropertyBindingResult bindingResult = new
// BeanPropertyBindingResult(pet, "pet");
bodyBuilder.appendFormalLine(String.format(
"%s bindingResult = new %s(%s, \"%s\");",
helper.getFinalTypeName(BEAN_PROPERTY_BINDING_RESULT),
helper.getFinalTypeName(BEAN_PROPERTY_BINDING_RESULT),
entityName, entityName));
// bindingResult.initConversion(conversionService_dtt);
bodyBuilder.appendFormalLine(String.format(
"bindingResult.initConversion(%s);",
getConversionServiceField().getFieldName().getSymbolName()));
// request.setAttribute(BindingResult.MODEL_KEY_PREFIX + "pet",
// bindingResult);
bodyBuilder
.appendFormalLine(String
.format("%s.setAttribute(%s.MODEL_KEY_PREFIX + \"%s\", bindingResult);",
REQUEST_PARAM_NAME.getSymbolName(),
helper.getFinalTypeName(BINDING_RESULT),
entityName));
bodyBuilder.appendFormalLine("");
// populateItemForRender(request, vet, true);
bodyBuilder.appendFormalLine(String.format(
"populateItemForRender(%s, %s, true);",
REQUEST_PARAM_NAME.getSymbolName(), entityName));
bodyBuilder.appendFormalLine("");
// dispatcher.include(request, new HttpServletResponseWrapper(response)
// {
bodyBuilder.appendFormalLine(String.format(
"dispatcher.include(%s, new %s(response) {",
REQUEST_PARAM_NAME.getSymbolName(),
helper.getFinalTypeName(HTTP_SERVLET_RESPONSE_WRAPPER)));
bodyBuilder.indent();
bodyBuilder.appendFormalLine("");
String printWriter = helper.getFinalTypeName(PRINT_WRITER);
// private PrintWriter writer = new PrintWriter(buffer);
bodyBuilder.appendFormalLine(String.format(
"private %s writer = new PrintWriter(buffer);", printWriter,
printWriter));
bodyBuilder.appendFormalLine("");
// @Override
bodyBuilder.appendFormalLine("@Override");
// public PrintWriter getWriter() throws IOException {
bodyBuilder.appendFormalLine(String.format(
"public %s getWriter() throws %s {", printWriter,
helper.getFinalTypeName(IO_EXCEPTION)));
bodyBuilder.indent();
// return writer;
bodyBuilder.appendFormalLine("return writer;");
// }
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
// });
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("});");
// String render = buffer.toString();
bodyBuilder.appendFormalLine("String render = buffer.toString();");
bodyBuilder.appendFormalLine("");
// // Put rendered content into first column
bodyBuilder
.appendFormalLine("// Put rendered content into first column");
// item.put("form", render);
bodyBuilder.appendFormalLine("item.put(\"form\", render);");
// result.add(item);
bodyBuilder.appendFormalLine("result.add(item);");
bodyBuilder.appendFormalLine("");
// return result;
bodyBuilder.appendFormalLine("return result;");
}
/**
* Return method <code>renderUpdateForms</code>
*
* @return
*/
private MethodMetadata getRenderUpdateFormsMethod() {
// method name
JavaSymbolName methodName = RENDER_UPDATE_FORMS_METHOD;
// Define method parameter types
final List<AnnotatedJavaType> parameterTypes = Arrays.asList(
AnnotatedJavaType.convertFromJavaType(entityListType),
AnnotatedJavaType.convertFromJavaType(HTTP_SERVLET_REQUEST),
AnnotatedJavaType.convertFromJavaType(HTTP_SERVLET_RESPONSE));
// 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
List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
// Define method throws types (none in this case)
List<JavaType> throwsTypes = new ArrayList<JavaType>();
throwsTypes.add(SERVLET_EXCEPTION);
throwsTypes.add(IO_EXCEPTION);
// Define method parameter names (none in this case)
List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(new JavaSymbolName(entityList));
parameterNames.add(REQUEST_PARAM_NAME);
parameterNames.add(RESPONSE_PARAM_NAME);
// Create the method body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
buildRenderUpdateFormsMethodBody(bodyBuilder);
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
getId(), Modifier.PUBLIC, methodName, LIST_MAP_STRING_STRING,
parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
methodBuilder.setThrowsTypes(throwsTypes);
return methodBuilder.build(); // Build and return a MethodMetadata
// instance
}
private void buildRenderUpdateFormsMethodBody(
InvocableMemberBodyBuilder bodyBuilder) {
// // Prepare result
bodyBuilder.appendFormalLine("// Prepare result");
// List<Map<String, String>> result = new ArrayList<Map<String,
// String>>(vets.size());
bodyBuilder.appendFormalLine(String.format(
"%s result = new %s(%s.size());",
helper.getFinalTypeName(LIST_MAP_STRING_STRING),
helper.getFinalTypeName(ARRAYLIST_MAP_STRING_STRING),
entityList));
// String controllerPath = "vets";
bodyBuilder.appendFormalLine(String.format(
"String controllerPath = \"%s\";",
webScaffoldAnnotationValues.getPath()));
// String pageToUse = "update";
bodyBuilder.appendFormalLine("String pageToUse = \"update\";");
// String renderUrl = String.format("/WEB-INF/views/%s/%s.jspx",
// controllerPath, pageToUse);
bodyBuilder
.appendFormalLine("String renderUrl = String.format(\"/WEB-INF/views/%s/%s.jspx\", controllerPath, pageToUse);");
// // For every element
bodyBuilder.appendFormalLine("// For every element");
// for (Vet vet : vets) {
bodyBuilder.appendFormalLine(String.format("for (%s %s : %s) {",
helper.getFinalTypeName(entity), entityName, entityList));
bodyBuilder.indent();
// Map<String, String> item = new HashMap<String, String>();
bodyBuilder.appendFormalLine(String.format("%s item = new %s();",
helper.getFinalTypeName(MAP_STRING_STRING),
helper.getFinalTypeName(HASHMAP_STRING_STRING)));
// final StringWriter buffer = new StringWriter();
bodyBuilder.appendFormalLine(String.format(
"final %s buffer = new %s();",
helper.getFinalTypeName(STRING_WRITER),
helper.getFinalTypeName(STRING_WRITER)));
// // Call JSP to render update form
bodyBuilder.appendFormalLine("// Call JSP to render update form");
// RequestDispatcher dispatcher =
// request.getRequestDispatcher(renderUrl);
bodyBuilder.appendFormalLine(String.format(
"%s dispatcher = %s.getRequestDispatcher(renderUrl);",
helper.getFinalTypeName(REQUEST_DISPATCHER),
REQUEST_PARAM_NAME.getSymbolName()));
// populateItemForRender(request, vet, true);
bodyBuilder.appendFormalLine(String.format(
"populateItemForRender(%s, %s, true);",
REQUEST_PARAM_NAME.getSymbolName(), entityName));
// dispatcher.include(request, new HttpServletResponseWrapper(response)
// {
bodyBuilder.appendFormalLine(String.format(
"dispatcher.include(%s, new %s(response) {",
REQUEST_PARAM_NAME.getSymbolName(),
helper.getFinalTypeName(HTTP_SERVLET_RESPONSE_WRAPPER)));
bodyBuilder.indent();
bodyBuilder.appendFormalLine("");
String printWriter = helper.getFinalTypeName(PRINT_WRITER);
// private PrintWriter writer = new PrintWriter(buffer);
bodyBuilder.appendFormalLine(String.format(
"private %s writer = new PrintWriter(buffer);", printWriter,
printWriter));
bodyBuilder.appendFormalLine("");
// @Override
bodyBuilder.appendFormalLine("@Override");
// public PrintWriter getWriter() throws IOException {
bodyBuilder.appendFormalLine(String.format(
"public %s getWriter() throws %s {", printWriter,
helper.getFinalTypeName(IO_EXCEPTION)));
bodyBuilder.indent();
// return writer;
bodyBuilder.appendFormalLine("return writer;");
// }
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
// });
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("});");
// String render = buffer.toString();
bodyBuilder.appendFormalLine("String render = buffer.toString();");
// // Load item id
bodyBuilder.appendFormalLine("// Load item id");
String idAccessor = "get".concat(StringUtils
.capitalize(entityIdentifier.getFieldName().getSymbolName()));
// item.put("DT_RowId",
// conversionService_datatables.convert(vet.getId(), String.class));
bodyBuilder.appendFormalLine(String.format(
"item.put(\"DT_RowId\", %s.convert(%s.%s(), String.class));",
getConversionServiceField().getFieldName().getSymbolName(),
entityName, idAccessor));
// // Put rendered content into first column
bodyBuilder
.appendFormalLine("// Put rendered content into first column");
// item.put("form", render);
bodyBuilder.appendFormalLine("item.put(\"form\", render);");
// result.add(item);
bodyBuilder.appendFormalLine("result.add(item);");
// }
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
// return result;
bodyBuilder.appendFormalLine("return result;");
}
/**
* Gets <code>renderXXX</code> method. <br>
* This method renders the required jspx for item an store it in a List of
* Map(String,String)
*
* @return
*/
private MethodMetadata getRenderItemsMethod() {
JavaType entitySearchResult = new JavaType(
SEARCH_RESULTS.getFullyQualifiedTypeName(), 0, DataType.TYPE,
null, Arrays.asList(entity));
// Define method parameter types
List<AnnotatedJavaType> parameterTypes = AnnotatedJavaType
.convertFromJavaTypes(entitySearchResult, HTTP_SERVLET_REQUEST,
HTTP_SERVLET_RESPONSE);
// Check if a method with the same signature already exists in the
// target type
final MethodMetadata method = methodExists(renderItemsMethodName,
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>();
throwsTypes.add(SERVLET_EXCEPTION);
throwsTypes.add(IO_EXCEPTION);
// Define method parameter names
List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(new JavaSymbolName("searchResult"));
parameterNames.add(REQUEST_PARAM_NAME);
parameterNames.add(RESPONSE_PARAM_NAME);
// Create the method body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
buildRenderItemsMethodBody(bodyBuilder);
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
getId(), Modifier.PUBLIC, renderItemsMethodName,
LIST_MAP_STRING_STRING, parameterTypes, parameterNames,
bodyBuilder);
methodBuilder.setAnnotations(annotations);
methodBuilder.setThrowsTypes(throwsTypes);
return methodBuilder.build(); // Build and return a MethodMetadata
// instance
}
/**
* Builds the method body of <code>renderXXX</code> method. <br>
* This method renders the required jspx for item an store it in a List of
* Map(String,String)
*
* @param bodyBuilder
*/
private void buildRenderItemsMethodBody(
InvocableMemberBodyBuilder bodyBuilder) {
String entityTypeName = helper.getFinalTypeName(entity);
bodyBuilder.appendFormalLine("");
bodyBuilder.appendFormalLine("// Prepare result");
/*
* List<Pets> pets = searchResult.getResults();
*/
bodyBuilder.appendFormalLine(String.format(
"%s %s = searchResult.getResults();",
helper.getFinalTypeName(entityListType), entityList));
/*
* List<Map<String, String>> result = new ArrayList<Map<String,
* String>>();
*/
bodyBuilder.appendFormalLine(String.format(
"%s result = new %s(%s.size());",
helper.getFinalTypeName(LIST_MAP_STRING_STRING),
helper.getFinalTypeName(ARRAYLIST_MAP_STRING_STRING),
entityList));
bodyBuilder.appendFormalLine(String.format(
"String controllerPath = \"%s\";",
webScaffoldAnnotationValues.getPath()));
bodyBuilder.appendFormalLine(String.format(
"String pageToUse = \"%s\";", annotationValues.getMode()));
bodyBuilder
.appendFormalLine("String renderUrl = String.format(\"/WEB-INF/views/%s/%s.jspx\", controllerPath, pageToUse);");
bodyBuilder.appendFormalLine("");
bodyBuilder.appendFormalLine("// For every element");
// for (Pet pet : owners) {
bodyBuilder.appendFormalLine(String.format("for (%s %s: %s) {",
entityTypeName, entityName, entityList));
bodyBuilder.indent();
// Map<String, String> row = new HashMap<String, String>();
bodyBuilder.appendFormalLine(String.format("%s item = new %s();",
helper.getFinalTypeName(MAP_STRING_STRING),
helper.getFinalTypeName(HASHMAP_STRING_STRING)));
// final StringWriter buffer = new StringWriter();
bodyBuilder.appendFormalLine(String.format(
"final %s buffer = new %s();",
helper.getFinalTypeName(STRING_WRITER),
helper.getFinalTypeName(STRING_WRITER)));
// TODO Check it can get dispatcher outside of for
bodyBuilder.appendFormalLine("// Call JSP to render current entity");
// RequestDispatcher dispatcher =
// request.getRequestDispatcher("/WEB-INF/views/owners/show.jspx");
bodyBuilder.appendFormalLine(String.format(
"%s dispatcher = %s.getRequestDispatcher(renderUrl);",
helper.getFinalTypeName(REQUEST_DISPATCHER),
REQUEST_PARAM_NAME.getSymbolName()));
bodyBuilder.appendFormalLine("");
// populateItemForRender(request, pet, false);
bodyBuilder.appendFormalLine(String.format(
"populateItemForRender(%s, %s, false);",
REQUEST_PARAM_NAME.getSymbolName(), entityName));
// dispatcher.include(request, new HttpServletResponseWrapper(response)
// {
bodyBuilder.appendFormalLine(String.format(
"dispatcher.include(%s, new %s(%s) {",
REQUEST_PARAM_NAME.getSymbolName(),
helper.getFinalTypeName(HTTP_SERVLET_RESPONSE_WRAPPER),
RESPONSE_PARAM_NAME.getSymbolName()));
bodyBuilder.indent();
// private PrintWriter writer = new PrintWriter(buffer);
bodyBuilder.appendFormalLine(String.format(
"private %s writer = new %s(buffer);",
helper.getFinalTypeName(PRINT_WRITER),
helper.getFinalTypeName(PRINT_WRITER)));
// @Override
bodyBuilder.appendFormalLine("@Override");
// public PrintWriter getWriter() throws IOException {
bodyBuilder.appendFormalLine(String.format(
"public %s getWriter() throws %s {",
helper.getFinalTypeName(PRINT_WRITER),
helper.getFinalTypeName(IO_EXCEPTION)));
bodyBuilder.indent();
// return writer;
bodyBuilder.appendFormalLine("return writer;");
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("});");
bodyBuilder.appendFormalLine("");
// String render = buffer.toString();
bodyBuilder.appendFormalLine("String render = buffer.toString();");
bodyBuilder.appendFormalLine("// Load item id)");
// row.put("DT_RowId",
// conversionService_datatables.convert(owner.getId(), String.class));
bodyBuilder
.appendFormalLine(String
.format("item.put(\"DT_RowId\", %s.convert(%s.get%s(), String.class));",
getConversionServiceField().getFieldName()
.getSymbolName(), entityName,
StringUtils.capitalize(entityIdentifier
.getFieldName().getSymbolName())));
bodyBuilder
.appendFormalLine("// Put rendered content into first column (uses column index)");
// row.put(Integer.toString(rowIdx), showOwner);
bodyBuilder.appendFormalLine("item.put(\"0\", render);");
bodyBuilder.appendFormalLine("");
bodyBuilder.appendFormalLine("result.add(item);");
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
bodyBuilder.appendFormalLine("");
bodyBuilder.appendFormalLine("return result;");
}
/**
* Gets <code>getFindByParameters</code> method. <br>
* This method generates a item List based on a parameters received in the
* request. Used by DOM mode listDatatables.
*
* @return
*/
private MethodMetadata getFindByParametersMethod() {
// Define method parameter types
List<AnnotatedJavaType> parameterTypes = AnnotatedJavaType
.convertFromJavaTypes(entity, ENUMERATION_STRING);
// Check if a method with the same signature already exists in the
// target type
final MethodMetadata method = methodExists(findByParametersMethodName,
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(entityName));
parameterNames.add(new JavaSymbolName("propertyNames"));
// Create the method body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
buildFindByParametersMapMethodBody(bodyBuilder);
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
getId(), Modifier.PUBLIC, findByParametersMethodName,
entityListType, parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
methodBuilder.setThrowsTypes(throwsTypes);
return methodBuilder.build(); // Build and return a MethodMetadata
// instance
}
/**
* Builds body method for <code>getFindByParameters</code> method. <br>
* This method generates a item List based on a parameters received in the
* request. Used by DOM mode listDatatables.
*
* @param bodyBuilder
*/
private void buildFindByParametersMapMethodBody(
InvocableMemberBodyBuilder bodyBuilder) {
// Gets propertyMap
bodyBuilder.appendFormalLine("// Gets propertyMap");
// Map<String, Object> propertyMap = getPropertyMap(visit,
// propertyNames);
bodyBuilder.appendFormalLine(String.format(
"%s propertyMap = %s(%s, propertyNames);",
helper.getFinalTypeName(MAP_STRING_OBJECT),
GET_PROPERTY_MAP.getSymbolName(), entityName));
//
bodyBuilder.appendFormalLine("");
//
// // if there is a filter
bodyBuilder.appendFormalLine("// if there is a filter");
// if (!propertyMap.isEmpty()) {
bodyBuilder.appendFormalLine("if (!propertyMap.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 : propertyMap.keySet()) {");
bodyBuilder.indent();
// baseFilterPredicate.and(entity.get(key).eq(propertyMap.get(key)));
bodyBuilder
.appendFormalLine("baseFilterPredicate.and(entity.get(key).eq(propertyMap.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());
// JPAQuery query = new
// JPAQuery(entityManagerProvider_dtt.getEntityManager(Vet.class));
bodyBuilder.appendFormalLine(String.format(
"%s query = new %s(%s.getEntityManager(%s.class));",
helper.getFinalTypeName(QDSL_JPA_QUERY),
helper.getFinalTypeName(QDSL_JPA_QUERY),
DATATABLES_MANAGER_PROVIDER_NAME,
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)));
}
/**
* Gets <code>getPropertyMap</code> method. <br>
* This method returns a Map with bean properties which appears on a
* Enumeration (usually from httpRequest.getParametersNames())
*
* @return
*/
private MethodMetadata getGetPropertyMapMethod() {
// Define method parameter types
List<AnnotatedJavaType> parameterTypes = AnnotatedJavaType
.convertFromJavaTypes(entity, ENUMERATION_STRING);
// Check if a method with the same signature already exists in the
// target type
final MethodMetadata method = methodExists(GET_PROPERTY_MAP,
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(entityName));
parameterNames.add(new JavaSymbolName("propertyNames"));
// Create the method body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
buildGetPropertyMapMethodBody(bodyBuilder);
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
getId(), Modifier.PUBLIC, GET_PROPERTY_MAP, MAP_STRING_OBJECT,
parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
methodBuilder.setThrowsTypes(throwsTypes);
return methodBuilder.build(); // Build and return a MethodMetadata
// instance
}
/**
* Gets <code>getPropertyMap</code> method. <br>
* This method returns a Map with bean properties which appears on a
* Enumeration (usually from httpRequest.getParametersNames())
*
* @return
*/
private MethodMetadata getGetPropertyMapUrlMethod() {
// Define method parameter types
List<AnnotatedJavaType> parameterTypes = AnnotatedJavaType
.convertFromJavaTypes(entity, HTTP_SERVLET_REQUEST);
// Check if a method with the same signature already exists in the
// target type
final MethodMetadata method = methodExists(GET_PROPERTY_MAP,
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(entityName));
parameterNames.add(new JavaSymbolName("request"));
// Create the method body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
buildGetPropertyMapUrlMethodBody(bodyBuilder);
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
getId(), Modifier.PUBLIC, GET_PROPERTY_MAP, MAP_STRING_OBJECT,
parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
methodBuilder.setThrowsTypes(throwsTypes);
return methodBuilder.build(); // Build and return a MethodMetadata
// instance
}
/**
* Gets <code>setDatatablesBaseFilter</code> method. <br>
* This method is used to set baseFilters into datatables
*
* @param annotationValues
*
* @return
*/
private MethodMetadata getSetDatatablesBaseFilterMethod(
DatatablesAnnotationValues annotationValues) {
// 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(SET_BASE_FILTER_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("propertyMap"));
// Create the method body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
buildSetDatatablesBaseFilterMethodBody(bodyBuilder, annotationValues);
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
getId(), Modifier.PUBLIC, SET_BASE_FILTER_METHOD,
JavaType.VOID_PRIMITIVE, parameterTypes, parameterNames,
bodyBuilder);
methodBuilder.setAnnotations(annotations);
methodBuilder.setThrowsTypes(throwsTypes);
return methodBuilder.build(); // Build and return a MethodMetadata
// instance
}
/**
* Returns <code>listDatatablesDetail</code> method <br>
* This method is default list request handler for detail datatables
* controllers
*
* @return
*/
private MethodMetadata getListDatatablesDetailMethod() {
// Define method parameter types
List<AnnotatedJavaType> parameterTypes = AnnotatedJavaType
.convertFromJavaTypes(MODEL, HTTP_SERVLET_REQUEST);
// Include Item in parameters to use spring's binder to get baseFilter
// values
parameterTypes.add(new AnnotatedJavaType(entity,
new AnnotationMetadataBuilder(MODEL_ATTRIBUTE).build()));
// Check if a method with the same signature already exists in the
// target type
final MethodMetadata method = methodExists(new JavaSymbolName(
DatatablesConstants.LIST_DTTBLS_DET_MTHD_NAME), 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>();
// @RequestMapping
AnnotationMetadataBuilder methodAnnotation = new AnnotationMetadataBuilder();
methodAnnotation.setAnnotationType(REQUEST_MAPPING);
// @RequestMapping(... produces = "text/html")
methodAnnotation.addStringAttribute(
DatatablesConstants.RQST_MAP_ANN_PROD_NAME,
DatatablesConstants.RQST_MAP_ANN_VAL_HTML);
// @RequestMapping(... value ="/list")
methodAnnotation.addStringAttribute(
DatatablesConstants.RQST_MAP_ANN_VAL_NAME,
DatatablesConstants.RQST_MAP_ANN_LIST);
annotations.add(methodAnnotation);
// 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(UI_MODEL);
parameterNames.add(new JavaSymbolName(
DatatablesConstants.REQUEST_PARAMETER_NAME));
// Include Item in parameters to use spring's binder to get baseFilter
// values
parameterNames.add(new JavaSymbolName(StringUtils
.uncapitalize(entityName)));
// Add method javadoc (not generated to disk because #10229)
CommentStructure comments = new CommentStructure();
JavadocComment javadoc = new JavadocComment(
"Show only the list view fragment for entity as detail datatables into a master datatables.");
comments.addComment(javadoc, CommentStructure.CommentLocation.BEGINNING);
// Create the method body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
// [Code generated]
bodyBuilder
.appendFormalLine("// Do common datatables operations: get entity list filtered by request parameters");
if (!isAjax()) {
// listDatatables(uiModel, request, pet);
bodyBuilder.appendFormalLine(LIST_DATATABLES.getSymbolName()
.concat("(uiModel, request, ")
.concat(entity.getSimpleTypeName().toLowerCase())
.concat(");"));
}
else {
// listDatatables(uiModel, request);
bodyBuilder.appendFormalLine(LIST_DATATABLES.getSymbolName()
.concat("(uiModel, request);"));
}
bodyBuilder
.appendFormalLine("// Show only the list fragment (without footer, header, menu, etc.) ");
// return "forward:/WEB-INF/views/pets/list.jspx";
bodyBuilder.appendFormalLine("return \"forward:/WEB-INF/views/".concat(
webScaffoldAnnotationValues.getPath()).concat("/list.jspx\";"));
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
getId(), Modifier.PUBLIC, new JavaSymbolName(
DatatablesConstants.LIST_DTTBLS_DET_MTHD_NAME),
JavaType.STRING, parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
methodBuilder.setThrowsTypes(throwsTypes);
methodBuilder.setCommentStructure(comments);
return methodBuilder.build(); // Build and return a MethodMetadata
// instance
}
/**
* Returns <code>createDatatablesDetail</code> method <br>
* This method is default create request handler for detail datatables
* controllers
*
* @return
*/
private MethodMetadata getCreateDatatablesDetailMethod() {
// @RequestMapping(method = RequestMethod.POST, produces = "text/html",
// params = "datatablesRedirect")
// public String createDatatablesDetail(@RequestParam(value =
// "datatablesRedirect", required = true) String redirect,
// @Valid Pet pet, BindingResult bindingResult, Model uiModel,
// HttpServletRequest httpServletRequest) {
// Define method parameter types
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
parameterTypes.add(helper.createRequestParam(JavaType.STRING,
DATATABLES_REDIRECT, true, null));
parameterTypes.add(new AnnotatedJavaType(entity,
new AnnotationMetadataBuilder(VALID).build()));
parameterTypes.addAll(AnnotatedJavaType.convertFromJavaTypes(
new JavaType("org.springframework.validation.BindingResult"),
MODEL, REDIRECT_ATTRIBUTES, HTTP_SERVLET_REQUEST));
// Check if a method with the same signature already exists in the
// target type
final MethodMetadata method = methodExists(new JavaSymbolName(
"createDatatablesDetail"), 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>();
// @RequestMapping(method = RequestMethod.POST, produces = "text/html",
// params = "datatablesRedirect")
AnnotationMetadataBuilder requestMappingAnnotation = helper
.getRequestMappingAnnotation(null, null, null,
DatatablesConstants.RQST_MAP_ANN_VAL_HTML, null, null);
requestMappingAnnotation.addEnumAttribute(METHOD_VAR, REQUEST_METHOD,
"POST");
requestMappingAnnotation.addStringAttribute(PARAMS_VAR,
DATATABLES_REDIRECT);
annotations.add(requestMappingAnnotation);
// Define method throws types (none in this case)
List<JavaType> throwsTypes = new ArrayList<JavaType>();
// Define method parameter names
final List<JavaSymbolName> parameterNames = Arrays.asList(
new JavaSymbolName("redirect"), new JavaSymbolName(entity
.getSimpleTypeName().toLowerCase()),
new JavaSymbolName("bindingResult"), UI_MODEL, REDIRECT_MODEL,
new JavaSymbolName("httpServletRequest"));
// Add method javadoc (not generated to disk because #10229)
CommentStructure comments = new CommentStructure();
JavadocComment javadoc = new JavadocComment(
"Create an entity and redirect to given URL.");
comments.addComment(javadoc, CommentStructure.CommentLocation.BEGINNING);
// Create the method body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
buildCreateDatatablesDetailMethodBody(bodyBuilder);
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
getId(), Modifier.PUBLIC, new JavaSymbolName(
"createDatatablesDetail"), JavaType.STRING,
parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
methodBuilder.setThrowsTypes(throwsTypes);
methodBuilder.setCommentStructure(comments);
return methodBuilder.build(); // Build and return a MethodMetadata
// instance
}
/**
* Build method body for createDatatablesDetails
*
* @param bodyBuilder
*/
private void buildCreateDatatablesDetailMethodBody(
InvocableMemberBodyBuilder bodyBuilder) {
String entityParamName = entity.getSimpleTypeName().toLowerCase();
bodyBuilder
.appendFormalLine("// Do common create operations (check errors, populate, persist, ...)");
// String view = create(pet, bindingResult, uiModel,
// httpServletRequest);
bodyBuilder.appendFormalLine("String view = create(".concat(
entityParamName).concat(
", bindingResult, uiModel, httpServletRequest);"));
// if (bindingResult.hasErrors() || redirect == null ||
// redirect.trim().isEmpty()) {
// return view;
// }
bodyBuilder
.appendFormalLine("// If binding errors or no redirect, return common create error view (remain in create form)");
bodyBuilder
.appendFormalLine("if (bindingResult.hasErrors() || redirect == null || redirect.trim().isEmpty()) {");
bodyBuilder.indent();
bodyBuilder.appendFormalLine("return view;");
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
// String[] paramValues =
// httpServletRequest.getParameterValues("dtt_table_id_hash");
bodyBuilder
.appendFormalLine("String[] paramValues = httpServletRequest.getParameterValues(\"dtt_table_id_hash\");");
// if(paramValues != null && paramValues.length > 0) {
bodyBuilder
.appendFormalLine("if(paramValues != null && paramValues.length > 0) {");
bodyBuilder.indent();
// redirectModel.addFlashAttribute("dtt_table_id_hash", paramValues[0]);
bodyBuilder
.appendFormalLine("redirectModel.addFlashAttribute(\"dtt_table_id_hash\", paramValues[0]);");
bodyBuilder.indentRemove();
// }else{
bodyBuilder.appendFormalLine("}else{");
bodyBuilder.indent();
// redirectModel.addFlashAttribute("dtt_table_id_hash", "");
bodyBuilder
.appendFormalLine("redirectModel.addFlashAttribute(\"dtt_table_id_hash\", \"\");");
bodyBuilder.indentRemove();
// }
bodyBuilder.appendFormalLine("}");
// uiModel.addFlashAttribute(DatatablesUtilsBean.ROWS_ON_TOP_IDS_PARAM,
// pet.getId());
bodyBuilder.appendFormalLine(String.format(
"%s.addFlashAttribute(%s.ROWS_ON_TOP_IDS_PARAM, %s.%s());",
REDIRECT_MODEL.getSymbolName(), helper
.getFinalTypeName(DATATABLES_UTILS_BEAN),
entityParamName, helper
.getGetterMethodNameForField(entityIdentifier
.getFieldName())));
bodyBuilder
.appendFormalLine("// If create success, redirect to given URL: master datatables");
// return "redirect:".concat(redirect);
bodyBuilder.appendFormalLine("return \"redirect:\".concat(redirect);");
}
/**
* Returns <code>updateDatatablesDetail</code> method <br>
* This method is default update request handler for detail datatables
* controllers
*
* @return
*/
private MethodMetadata getUpdateDatatablesDetailMethod() {
// @RequestMapping(method = RequestMethod.PUT, produces = "text/html",
// params = "datatablesRedirect")
// public String updateDatatablesDetail(@RequestParam(value =
// "datatablesRedirect", required = true) String redirect,
// @Valid Pet pet, BindingResult bindingResult, Model uiModel,
// HttpServletRequest httpServletRequest) {
// Define method parameter types
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
parameterTypes.add(helper.createRequestParam(JavaType.STRING,
DATATABLES_REDIRECT, true, null));
parameterTypes.add(new AnnotatedJavaType(entity,
new AnnotationMetadataBuilder(VALID).build()));
parameterTypes.addAll(AnnotatedJavaType.convertFromJavaTypes(
BINDING_RESULT, MODEL, REDIRECT_ATTRIBUTES,
HTTP_SERVLET_REQUEST));
// Check if a method with the same signature already exists in the
// target type
final MethodMetadata method = methodExists(new JavaSymbolName(
"updateDatatablesDetail"), 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>();
// @RequestMapping(method = RequestMethod.PUT, produces = "text/html",
// params = "datatablesRedirect")
AnnotationMetadataBuilder requestMappingAnnotation = helper
.getRequestMappingAnnotation(null, null, null,
DatatablesConstants.RQST_MAP_ANN_VAL_HTML, null, null);
requestMappingAnnotation.addEnumAttribute(METHOD_VAR, REQUEST_METHOD,
"PUT");
requestMappingAnnotation.addStringAttribute(PARAMS_VAR,
DATATABLES_REDIRECT);
annotations.add(requestMappingAnnotation);
// Define method throws types (none in this case)
List<JavaType> throwsTypes = new ArrayList<JavaType>();
// Define method parameter names
final List<JavaSymbolName> parameterNames = Arrays.asList(
new JavaSymbolName("redirect"), new JavaSymbolName(entity
.getSimpleTypeName().toLowerCase()),
new JavaSymbolName("bindingResult"), UI_MODEL, REDIRECT_MODEL,
new JavaSymbolName("httpServletRequest"));
// Add method javadoc (not generated to disk because #10229)
CommentStructure comments = new CommentStructure();
JavadocComment javadoc = new JavadocComment(
"Update an entity and redirect to given URL.");
comments.addComment(javadoc, CommentStructure.CommentLocation.BEGINNING);
// Create the method body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
buildUpdateDatatablesDetailMethodBody(bodyBuilder);
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
getId(), Modifier.PUBLIC, new JavaSymbolName(
"updateDatatablesDetail"), JavaType.STRING,
parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
methodBuilder.setThrowsTypes(throwsTypes);
methodBuilder.setCommentStructure(comments);
return methodBuilder.build(); // Build and return a MethodMetadata
// instance
}
private void buildUpdateDatatablesDetailMethodBody(
InvocableMemberBodyBuilder bodyBuilder) {
String entityParamName = entity.getSimpleTypeName().toLowerCase();
bodyBuilder
.appendFormalLine("// Do common update operations (check errors, populate, merge, ...)");
// String view = update(pet, bindingResult, uiModel,
// httpServletRequest);
bodyBuilder.appendFormalLine("String view = update(".concat(
entityParamName).concat(
", bindingResult, uiModel, httpServletRequest);"));
// if (bindingResult.hasErrors() || redirect == null ||
// redirect.trim().isEmpty()) {
// return view;
// }
bodyBuilder
.appendFormalLine("// If binding errors or no redirect, return common update error view (remain in update form)");
bodyBuilder
.appendFormalLine("if (bindingResult.hasErrors() || redirect == null || redirect.trim().isEmpty()) {");
bodyBuilder.indent();
bodyBuilder.appendFormalLine("return view;");
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
// String[] paramValues =
// httpServletRequest.getParameterValues("dtt_table_id_hash");
bodyBuilder
.appendFormalLine("String[] paramValues = httpServletRequest.getParameterValues(\"dtt_table_id_hash\");");
// if(paramValues != null && paramValues.length > 0) {
bodyBuilder
.appendFormalLine("if(paramValues != null && paramValues.length > 0) {");
bodyBuilder.indent();
// redirectModel.addFlashAttribute("dtt_table_id_hash", paramValues[0]);
bodyBuilder
.appendFormalLine("redirectModel.addFlashAttribute(\"dtt_table_id_hash\", paramValues[0]);");
bodyBuilder.indentRemove();
// }else{
bodyBuilder.appendFormalLine("}else{");
bodyBuilder.indent();
// redirectModel.addFlashAttribute("dtt_table_id_hash", "");
bodyBuilder
.appendFormalLine("redirectModel.addFlashAttribute(\"dtt_table_id_hash\", \"\");");
bodyBuilder.indentRemove();
// }
bodyBuilder.appendFormalLine("}");
// uiModel.addFlashAttribute(DatatablesUtilsBean.ROWS_ON_TOP_IDS_PARAM,
// pet.getId());
bodyBuilder.appendFormalLine(String.format(
"%s.addFlashAttribute(%s.ROWS_ON_TOP_IDS_PARAM, %s.%s());",
REDIRECT_MODEL.getSymbolName(), helper
.getFinalTypeName(DATATABLES_UTILS_BEAN),
entityParamName, helper
.getGetterMethodNameForField(entityIdentifier
.getFieldName())));
bodyBuilder
.appendFormalLine("// If update success, redirect to given URL: master datatables");
// return "redirect:".concat(redirect);
bodyBuilder.appendFormalLine("return \"redirect:\".concat(redirect);");
}
/**
* Returns <code>deleteDatatablesDetail</code> method <br>
* This method is default delete request handler for detail datatables
* controllers
*
* @return
*/
private MethodMetadata getDeleteDatatablesDetailMethod() {
// @RequestMapping(value = "/{id}", method = RequestMethod.DELETE,
// produces = "text/html", params = "datatablesRedirect")
// public String deleteDatatablesDetail(@RequestParam(value =
// "datatablesRedirect", required = true) String redirect,
// @PathVariable("id") Long id, @RequestParam(value = "page", required =
// false) Integer page,
// @RequestParam(value = "size", required = false) Integer size, Model
// uiModel) {
// Define method parameter types
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
parameterTypes.add(helper.createRequestParam(JavaType.STRING,
DATATABLES_REDIRECT, true, null));
final List<AnnotationAttributeValue<?>> annotationAttributes = new ArrayList<AnnotationAttributeValue<?>>();
annotationAttributes.add(new StringAttributeValue(new JavaSymbolName(
"value"), "id"));
parameterTypes.add(new AnnotatedJavaType(entityIdentifier
.getFieldType(), new AnnotationMetadataBuilder(new JavaType(
"org.springframework.web.bind.annotation.PathVariable"),
annotationAttributes).build()));
parameterTypes.add(helper.createRequestParam(JavaType.INT_OBJECT,
PAGE_VAR, false, null));
parameterTypes.add(helper.createRequestParam(JavaType.INT_OBJECT,
SIZE_VAR, false, null));
parameterTypes.addAll(AnnotatedJavaType.convertFromJavaTypes(MODEL));
// Check if a method with the same signature already exists in the
// target type
final MethodMetadata method = methodExists(new JavaSymbolName(
"deleteDatatablesDetail"), 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>();
// @RequestMapping(value = "/{id}", method = RequestMethod.DELETE,
// produces = "text/html", params = "datatablesRedirect")
AnnotationMetadataBuilder requestMappingAnnotation = helper
.getRequestMappingAnnotation(null, null, null,
DatatablesConstants.RQST_MAP_ANN_VAL_HTML, null, null);
requestMappingAnnotation.addEnumAttribute(METHOD_VAR, REQUEST_METHOD,
"DELETE");
requestMappingAnnotation.addStringAttribute(PARAMS_VAR,
DATATABLES_REDIRECT);
requestMappingAnnotation.addStringAttribute("value", "/{id}");
annotations.add(requestMappingAnnotation);
// Define method throws types (none in this case)
List<JavaType> throwsTypes = new ArrayList<JavaType>();
// Define method parameter names
final List<JavaSymbolName> parameterNames = Arrays.asList(
new JavaSymbolName("redirect"), new JavaSymbolName("id"),
new JavaSymbolName(PAGE_VAR), new JavaSymbolName(SIZE_VAR),
UI_MODEL);
// Add method javadoc (not generated to disk because #10229)
CommentStructure comments = new CommentStructure();
JavadocComment javadoc = new JavadocComment(
"Delete an entity and redirect to given URL.");
comments.addComment(javadoc, CommentStructure.CommentLocation.BEGINNING);
// Create the method body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
bodyBuilder
.appendFormalLine("// Do common delete operations (find, remove, add pagination attributes, ...)");
// String view = delete(id, page, size, uiModel);
bodyBuilder
.appendFormalLine("String view = delete(id, page, size, uiModel);");
// if (redirect == null || redirect.trim().isEmpty()) {
// return view;
// }
bodyBuilder
.appendFormalLine("// If no redirect, return common list view");
bodyBuilder
.appendFormalLine("if (redirect == null || redirect.trim().isEmpty()) {");
bodyBuilder.indent();
bodyBuilder.appendFormalLine("return view;");
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
bodyBuilder
.appendFormalLine("// Redirect to given URL: master datatables");
// return "redirect:".concat(redirect);
bodyBuilder.appendFormalLine("return \"redirect:\".concat(redirect);");
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
getId(), Modifier.PUBLIC, new JavaSymbolName(
"deleteDatatablesDetail"), JavaType.STRING,
parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
methodBuilder.setThrowsTypes(throwsTypes);
methodBuilder.setCommentStructure(comments);
return methodBuilder.build(); // Build and return a MethodMetadata
// instance
}
/**
* Build body method <code>getPropertyMap</code> method. <br>
* This method returns a Map with bean properties which appears on a
* Enumeration (usually from httpRequest.getParametersNames())
*
* @return
*/
private void buildGetPropertyMapMethodBody(
InvocableMemberBodyBuilder bodyBuilder) {
// Map<String, Object> propertyValuesMap = new HashMap<String,
// Object>();
bodyBuilder.appendFormalLine(String.format(
"%s propertyValuesMap = new %s();",
helper.getFinalTypeName(MAP_STRING_OBJECT),
helper.getFinalTypeName(HASHMAP_STRING_OBJECT)));
//
bodyBuilder.appendFormalLine("");
// // If no entity or properties given, return empty Map
bodyBuilder
.appendFormalLine("// If no entity or properties given, return empty Map");
// if(entity == null || propertyNames == null) {
bodyBuilder.appendFormalLine(String.format(
"if(%s == null || propertyNames == null) {", entityName));
bodyBuilder.indent();
// return propertyValuesMap;
bodyBuilder.appendFormalLine("return propertyValuesMap;");
// }
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
bodyBuilder.appendFormalLine("");
// List<String> properties = new ArrayList<String>();
bodyBuilder.appendFormalLine(String.format("%s properties = new %s();",
helper.getFinalTypeName(LIST_STRING),
helper.getFinalTypeName(ARRAYLIST_STRING)));
// CollectionUtils.addAll(properties, propertyNames);
bodyBuilder.appendFormalLine(String.format(
"%s.addAll(properties, propertyNames);",
helper.getFinalTypeName(COLLECTION_UTILS)));
//
bodyBuilder.appendFormalLine("");
// // There must be at least one property name, otherwise return empty
// Map
bodyBuilder
.appendFormalLine("// There must be at least one property name, otherwise return empty Map");
// if(properties.isEmpty()) {
bodyBuilder.appendFormalLine("if (properties.isEmpty()) {");
bodyBuilder.indent();
// return propertyValuesMap;
bodyBuilder.appendFormalLine("return propertyValuesMap;");
// }
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
//
bodyBuilder.appendFormalLine("");
// // Iterate over given properties to get each property value
bodyBuilder
.appendFormalLine("// Iterate over given properties to get each property value");
// BeanWrapper entityBean = new BeanWrapperImpl(entity);
bodyBuilder.appendFormalLine(String.format(
"%s entityBean = new %s(%s);",
helper.getFinalTypeName(BEAN_WRAPPER),
helper.getFinalTypeName(BEAN_WRAPPER_IMP), entityName));
// for (String propertyName : properties) {
bodyBuilder
.appendFormalLine("for (String propertyName : properties) {");
bodyBuilder.indent();
// if (entityBean.isReadableProperty(propertyName)) {
bodyBuilder
.appendFormalLine("if (entityBean.isReadableProperty(propertyName)) {");
bodyBuilder.indent();
// Object propertyValue = null;
bodyBuilder.appendFormalLine("Object propertyValue = null;");
// try {
bodyBuilder.appendFormalLine("try {");
bodyBuilder.indent();
// propertyValue = entityBean.getPropertyValue(propertyName);
bodyBuilder
.appendFormalLine("propertyValue = entityBean.getPropertyValue(propertyName);");
// } catch (Exception e){
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("} catch (Exception e){");
bodyBuilder.indent();
// // TODO log warning
bodyBuilder.appendFormalLine("// TODO log warning");
// continue;
bodyBuilder.appendFormalLine("continue;");
// }
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
// propertyValuesMap.put(propertyName, propertyValue);
bodyBuilder
.appendFormalLine("propertyValuesMap.put(propertyName, propertyValue);");
// }
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
// }
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
// return propertyValuesMap;
bodyBuilder.appendFormalLine("return propertyValuesMap;");
}
/**
* Build body method <code>getPropertyMap</code> method. <br>
* This method returns a Map with bean properties which appears on a
* Enumeration (usually from httpRequest.getParametersNames())
*
* @return
*/
private void buildGetPropertyMapUrlMethodBody(
InvocableMemberBodyBuilder bodyBuilder) {
// URL parameters are used as base search filters
bodyBuilder.appendFormalLine(PARAMETERS_AS_BASE_SEARCH);
/*
* @SuppressWarnings("unchecked") Map<String, Object> propertyValuesMap
* = getPropertyMap(visit, request.getParameterNames());
*/
bodyBuilder
.appendFormalLine(String
.format("@SuppressWarnings(\"unchecked\") %s propertyValuesMap = getPropertyMap(%s, request.getParameterNames());",
helper.getFinalTypeName(MAP_STRING_OBJECT),
entityName));
/*
* // Add to the property map the parameters used as query operators
* Map<String, Object> params = new
* HashMap<String,Object>(populateParametersMap(request)); Set<String>
* keySet = params.keySet();
*/
bodyBuilder
.appendFormalLine("// Add to the property map the parameters used as query operators");
bodyBuilder.appendFormalLine(String.format(
"%s params = new %s(populateParametersMap(request));",
helper.getFinalTypeName(MAP_STRING_OBJECT),
helper.getFinalTypeName(HASHMAP_STRING_OBJECT)));
bodyBuilder.appendFormalLine(String.format(
"%s keySet = params.keySet();",
helper.getFinalTypeName(SET_STRING)));
/*
* for (String key : keySet) { if
* (key.startsWith(QuerydslUtilsBean.OPERATOR_PREFIX)) {
* propertyValuesMap.put(key, params.get(key)); } else if
* (DatatablesUtilsBean.ROWS_ON_TOP_IDS_PARAM.equals(key)) {
* propertyValuesMap.put(key, request.getParams().get(key)); } }
*/
bodyBuilder.appendFormalLine("for (String key : keySet) {");
bodyBuilder.indent();
bodyBuilder
.appendFormalLine(String
.format("if (datatablesUtilsBean_dtt.isSpecialFilterParameters(key)) {",
helper.getFinalTypeName(QUERYDSL_UTILS_BEAN)));
bodyBuilder.indent();
bodyBuilder
.appendFormalLine("propertyValuesMap.put(key, params.get(key));");
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
// return propertyValuesMap;
bodyBuilder.appendFormalLine("return propertyValuesMap;");
}
/**
* Build body method <code>setDatatablesBaseFilter</code> method. <br>
* This method returns a Map with bean properties which appears on a
* Enumeration (usually from httpRequest.getParametersNames())
*
* @param annotationValues2
*
* @return
*/
private void buildSetDatatablesBaseFilterMethodBody(
InvocableMemberBodyBuilder bodyBuilder,
DatatablesAnnotationValues annotationValues) {
// Add here your baseFilters to propertyMap.
bodyBuilder
.appendFormalLine("// Add here your baseFilters to propertyMap.");
String baseFilter = annotationValues.getBaseFilter();
if (baseFilter != null) {
for (String i : baseFilter.split("And")) {
String[] values = i.split("[A-Z][A-Z]+");
String operation = "";
for (BaseFilterOperationTypes op : BaseFilterOperationTypes
.values()) {
if (i.contains(op.toString()))
operation = op.toString();
}
if (operation.equals("")) {
LOGGER.log(Level.INFO, "Invalid operation for base filter.");
}
else {
String safevalue = "";
if (values.length > 1)
safevalue = values[1];
bodyBuilder.appendFormalLine("propertyMap.put(\""
+ values[0] + "\",\"" + safevalue + ENDING);
bodyBuilder.appendFormalLine("propertyMap.put(\"_operator_"
+ values[0] + "\",\"" + operation + ENDING);
}
}
}
}
/**
* Gets <code>populateParameterMap</code> method. This method transforms a
* HttpServlerRequest Map<String,String[]> into a Map<String,String>
*
* @return
*/
private MethodMetadata getPopulateParameterMapMethod() {
// Define method parameter types
List<AnnotatedJavaType> parameterTypes = AnnotatedJavaType
.convertFromJavaTypes(HTTP_SERVLET_REQUEST);
// Check if a method with the same signature already exists in the
// target type
final MethodMetadata method = methodExists(POPULATE_PARAMETERS_MAP,
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(
DatatablesConstants.REQUEST_PARAMETER_NAME));
// Create the method body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
buildPopulateParameterMapMethodBody(bodyBuilder);
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
getId(), Modifier.PUBLIC, POPULATE_PARAMETERS_MAP,
MAP_STRING_STRING, parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
methodBuilder.setThrowsTypes(throwsTypes);
return methodBuilder.build(); // Build and return a MethodMetadata
// instance
}
/**
* Build body method of <code>populateParameterMap</code> method. This
* method transforms a HttpServlerRequest Map<String,String[]> into a
* Map<String,String>
*
* @param bodyBuilder
*/
private void buildPopulateParameterMapMethodBody(
InvocableMemberBodyBuilder bodyBuilder) {
// Map<String, Object> params;
bodyBuilder.appendFormalLine(String.format("%s params;",
helper.getFinalTypeName(MAP_STRING_OBJECT)));
// if (request == null) {
bodyBuilder.appendFormalLine("if (request == null) {");
bodyBuilder.indent();
// params = Collections.emptyMap();
bodyBuilder.appendFormalLine(String.format("params = %s.emptyMap();",
helper.getFinalTypeName(COLLECTIONS)));
// } else {
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine(ELSE);
bodyBuilder.indent();
// params = new HashMap<String, Object>(request.getParameterMap());
bodyBuilder.appendFormalLine(String.format(
"params = new %s(request.getParameterMap());",
helper.getFinalTypeName(HASHMAP_STRING_OBJECT)));
// }
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
//
bodyBuilder.appendFormalLine("");
// Map<String, String> allParams = new HashMap<String,
// String>(params.size());
bodyBuilder.appendFormalLine(String.format(
"%s allParams = new %s(params.size());",
helper.getFinalTypeName(MAP_STRING_STRING),
helper.getFinalTypeName(HASHMAP_STRING_STRING)));
//
bodyBuilder.appendFormalLine("");
// String value;
bodyBuilder.appendFormalLine("String value;");
// String objValue;
bodyBuilder.appendFormalLine("Object objValue;");
// for (String key : params.keySet()) {
bodyBuilder.appendFormalLine("for (String key : params.keySet()) {");
bodyBuilder.indent();
bodyBuilder.appendFormalLine("objValue = params.get(key);");
// if (objValue instanceof String[]) {
bodyBuilder.appendFormalLine("if (objValue instanceof String[]) {");
bodyBuilder.indent();
// value = ((String[]) entry.getValue())[0];
bodyBuilder.appendFormalLine("value = ((String[]) objValue)[0];");
// } else {
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine(ELSE);
bodyBuilder.indent();
// value = (String) entry.getValue();
bodyBuilder.appendFormalLine("value = (String) objValue;");
// }
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
// allParams.put(entry.getKey(), value);
bodyBuilder.appendFormalLine("allParams.put(key, value);");
// }
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
// return allParams;
bodyBuilder.appendFormalLine("return allParams;");
}
/**
* Gets a method to manage AJAX data request of a datatables which draw the
* result of a Roo Dynamic finder.
*
* @param finderMethod
* @param queryHolder
* @return
*/
private MethodMetadata getAjaxFinderMethod(
FinderMetadataDetails finderMethod, QueryHolderTokens queryHolder) {
// Define method parameter types
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
// Add datatable request parameters
parameterTypes.add(new AnnotatedJavaType(DATATABLES_CRITERIA_TYPE,
new AnnotationMetadataBuilder(DATATABLES_PARAMS).build()));
// Prepares @RequestParam method parameters based on
// finder information
List<AnnotatedJavaType> finderParamTypes = finderMethod
.getFinderMethodMetadata().getParameterTypes();
List<JavaSymbolName> finderParamNames = finderMethod
.getFinderMethodMetadata().getParameterNames();
JavaType paramType;
for (int i = 0; i < finderParamTypes.size(); i++) {
paramType = finderParamTypes.get(i).getJavaType();
if (paramType.isBoolean()) {
// Boolean's false value is omitted on request, so must be
// optional (by default will get false)
parameterTypes.add(helper.createRequestParam(paramType,
finderParamNames.get(i).getSymbolName(), false, null));
}
else if (paramType.getFullyQualifiedTypeName().equals(
new JavaType(Date.class).getFullyQualifiedTypeName())) {
AnnotationMetadata dateTimeFormatAnnotation = finderMethod
.getFinderMethodParamFields().get(i)
.getAnnotation(SpringJavaType.DATE_TIME_FORMAT);
parameterTypes.add(helper.createDateTimeRequestParam(paramType,
finderParamNames.get(i).getSymbolName(), null, null,
dateTimeFormatAnnotation));
}
else {
parameterTypes.add(helper.createRequestParam(paramType,
finderParamNames.get(i).getSymbolName(), null, null));
}
}
if (!isStantardMode()) {
// For render mode request and response are needed to
// perform internal request for item render
parameterTypes.add(AnnotatedJavaType
.convertFromJavaType(HTTP_SERVLET_REQUEST));
parameterTypes.add(AnnotatedJavaType
.convertFromJavaType(HTTP_SERVLET_RESPONSE));
}
JavaSymbolName methodName = new JavaSymbolName(
finderMethod.getFinderName());
// Check if a method with the same signature already exists in the
// target type
final MethodMetadata method = methodExists(methodName, parameterTypes);
if (method != null) {
// If it already exists, just return the method and omit its
// generation via the ITD
return method;
}
// get Finder-name value
String finderNameValue = finderMethod.getFinderName();
finderNameValue = finderNameValue.substring(finderNameValue
.indexOf("By"));
// Define method annotations
List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
AnnotationMetadataBuilder methodAnnotation = new AnnotationMetadataBuilder();
methodAnnotation.setAnnotationType(REQUEST_MAPPING);
methodAnnotation.addStringAttribute(HEADERS, ACCEPT_APPLICATION_JSON);
methodAnnotation.addStringAttribute(
DatatablesConstants.RQST_MAP_ANN_VAL_NAME, "/datatables/ajax");
methodAnnotation.addStringAttribute(PARAMS_VAR,
"ajax_find=".concat(finderNameValue));
methodAnnotation.addStringAttribute(
DatatablesConstants.RQST_MAP_ANN_PROD_NAME, APPLICATION_JSON);
annotations.add(methodAnnotation);
annotations.add(new AnnotationMetadataBuilder(RESPONSE_BODY));
// Define method throws types (none in this case)
List<JavaType> throwsTypes = new ArrayList<JavaType>();
if (!isStantardMode()) {
// On render mode internal render request
// can throw ServletException or IOException
throwsTypes.add(SERVLET_EXCEPTION);
throwsTypes.add(IO_EXCEPTION);
}
// Define method parameter names
List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(CRITERIA_PARAM_NAME);
for (JavaSymbolName paramName : finderParamNames) {
parameterNames.add(paramName);
}
if (!isStantardMode()) {
// For render mode request and response are needed to
// perform internal request for item render
parameterNames.add(REQUEST_PARAM_NAME);
parameterNames.add(RESPONSE_PARAM_NAME);
}
// Create the method body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
buildFinderAjaxMethodBody(bodyBuilder, finderMethod, queryHolder);
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
getId(), Modifier.PUBLIC, methodName, FIND_ALL_RETURN,
parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
methodBuilder.setThrowsTypes(throwsTypes);
return methodBuilder.build(); // Build and return a MethodMetadata
// instance
}
/**
* Build body method to manage AJAX data request of a datatables which draw
* the result of a Roo Dynamic finder.
*
* @param bodyBuilder
* @param finderMethod
* @param queryHolder
*/
private void buildFinderAjaxMethodBody(
InvocableMemberBodyBuilder bodyBuilder,
FinderMetadataDetails finderMethod, QueryHolderTokens queryHolder) {
// BooleanBuilder baseFilterPredicate = new BooleanBuilder();
bodyBuilder.appendFormalLine(String.format("%s baseSearch = new %s();",
helper.getFinalTypeName(QDSL_BOOLEAN_BUILDER),
helper.getFinalTypeName(QDSL_BOOLEAN_BUILDER)));
bodyBuilder.appendFormalLine("");
bodyBuilder
.appendFormalLine("// Base Search. Using BooleanBuilder, a cascading builder for");
bodyBuilder.appendFormalLine("// Predicate expressions");
String path_builder = helper.getFinalTypeName(QDSL_PATH_BUILDER);
String entity_class = helper.getFinalTypeName(entity);
// PathBuilder<Pet> entity = new PathBuilder<Pet>(Pet.class, "entity");
bodyBuilder.appendFormalLine(String.format(
"%s<%s> entity = new %s<%s>(%s.class, \"entity\");",
path_builder, entity_class, path_builder, entity_class,
entity_class));
bodyBuilder.appendFormalLine("");
// Build code to generate QueryDsl predicate to include base filter
// on Datatables.findByCriteria
buildFinderAjaxBaseSearchMethodBody(bodyBuilder, finderMethod,
queryHolder);
bodyBuilder.appendFormalLine("");
// Build Datatables.findByCriteria call code
buildFindByCriteriaCallMethodBody(bodyBuilder, true);
// Build code for response based on SearchResult
if (isStantardMode()) {
// Build code to delegate on Datatables.populateDataSearch
buildPopulateDataSearchCallMethodBody(bodyBuilder);
}
else {
// Build code to call RenderItem method
buildPopulateDataSearchCallRenderModeMethodBody(bodyBuilder);
}
}
/**
* Builds code to create a QueryDsl predicate which implements a Roo dynamic
* filter condition
*
* @param bodyBuilder
* @param finderMethod
* @param queryHolder
*/
private void buildFinderAjaxBaseSearchMethodBody(
InvocableMemberBodyBuilder bodyBuilder,
FinderMetadataDetails finderMethod, QueryHolderTokens queryHolder) {
FieldToken lastFieldToken = null;
// flag set when a FieldTocken is located
boolean isNewField = true;
// Flag set when a condition is generated
// but not included yet
boolean isConditionApplied = false;
// Flag set if condition value is "Between"
boolean isBetweenCondition = false;
// Checks if there is any operator "And" or "Or" and holds it
boolean isOperatorApplied = false;
String op = "";
// Helper which can generated the expression
// required for generate the predicate
FinderToDslHelper fHelper = new FinderToDslHelper(finderMethod,
queryHolder, helper);
// Holds current expression
StringBuilder expBuilder = null;
// Holds condition if exists
StringBuilder condition = null;
for (final Token token : queryHolder.getTokens()) {
if (token instanceof ReservedToken) {
// Current token isn't a field
final String reservedToken = token.getValue();
if (lastFieldToken == null) {
// Any operator must be preceded by refereed field
// XXX Throw a "wrong format" exception?
continue;
}
// prepare field name
final String fieldName = lastFieldToken.getField()
.getFieldName().getSymbolName();
// Add PathBuilder to expression
expBuilder = new StringBuilder("entity");
// XXX Currently ManyToMany and OneToMany
// properties are not supported by Roo finders
if (!lastFieldToken.getField().getFieldType()
.isCommonCollectionType()) {
// If previous token was a field
// include Path getter
if (isNewField) {
JavaType fieldType = fHelper
.getFieldTypeOfFinder(fieldName);
Validate.notNull(
fieldType,
"Field type not found for '%s' field in '%s' finder",
fieldName, finderMethod.getFinderName());
expBuilder.append(fHelper.getDslGetterFor(fieldName,
fieldType));
if (reservedToken.equalsIgnoreCase("Like")) {
// Add function toLower (and cast to string if it's
// needed)
expBuilder.append(fHelper
.getToLowerOperatorFor(fieldType));
}
// Mark as field getter is already processed
isNewField = false;
// Mark as condition is no included
isConditionApplied = false;
isOperatorApplied = false;
}
// Reserved is an operator "and" or "or" given
if (reservedToken.equalsIgnoreCase("And")
|| reservedToken.equalsIgnoreCase("Or")) {
// Last token isnt "between"
if (!isBetweenCondition) {
if (reservedToken.equalsIgnoreCase("And")) {
if (!isConditionApplied) {
// Use .eq() operator if condition not
// applied
expBuilder.append(fHelper
.getEqualExpression(fieldName));
// Creating Basesearch expression
createBaseSearchExpressionWithNullCheck(
bodyBuilder, fHelper,
lastFieldToken, expBuilder, "and");
}
else {
// If there is a held condition,
// create the full expression
createBaseSearchExpressionWithNullCheck(
bodyBuilder, fHelper,
lastFieldToken, condition, "and");
}
}
if (reservedToken.equalsIgnoreCase("Or")) {
if (!isConditionApplied) {
// Use .eq() operator if condition not
// applied
expBuilder.append(fHelper
.getEqualExpression(fieldName));
// Creating Basesearch expression
createBaseSearchExpressionWithNullCheck(
bodyBuilder, fHelper,
lastFieldToken, expBuilder, "or");
}
else {
createBaseSearchExpressionWithNullCheck(
// Use held condition if a condition
// was applied
bodyBuilder, fHelper,
lastFieldToken, condition, "or");
}
}
}
// Hold given operator to create the expression if
// necessary
op = reservedToken.toLowerCase();
condition = null;
isOperatorApplied = true;
// Reset flags to next operation
isConditionApplied = false;
isBetweenCondition = false;
}
else {
// Reserved token is a condition
if (reservedToken.equalsIgnoreCase("Between")) {
// use .between(minField,maxField) expression
createBaseSearchExpressionWithNullCheck(
bodyBuilder, fHelper, lastFieldToken,
expBuilder, "between");
isBetweenCondition = true;
isOperatorApplied = true;
}
else if (reservedToken.equalsIgnoreCase("Like")) {
// use .like() expression
expBuilder.append(fHelper
.getLikeExpression(fieldName));
}
else if (reservedToken.equalsIgnoreCase("IsNotNull")) {
// builder.append(" IS NOT NULL ");
// use isNotNull() expression
expBuilder.append(".isNotNull()");
}
else if (reservedToken.equalsIgnoreCase("IsNull")) {
// builder.append(" IS NULL ");
// use isNull() expression
expBuilder.append(".isNull()");
}
else if (reservedToken.equalsIgnoreCase("Not")) {
// builder.append(" IS NOT ");
// use not() expression
expBuilder.append(".not()");
}
else if (reservedToken.equalsIgnoreCase("NotEquals")) {
// builder.append(" != ");
expBuilder.append(fHelper
.getNotEqualExpression(fieldName));
}
else if (reservedToken.equalsIgnoreCase("LessThan")) {
// builder.append(" < ");
expBuilder.append(fHelper
.getLessThanExpression(fieldName));
}
else if (reservedToken
.equalsIgnoreCase("LessThanEquals")) {
// builder.append(" <= ");
expBuilder.append(fHelper
.getLessThanEqualsExpression(fieldName));
}
else if (reservedToken.equalsIgnoreCase("GreaterThan")) {
// builder.append(" > ");
expBuilder.append(fHelper
.getGreaterThanExpression(fieldName));
}
else if (reservedToken
.equalsIgnoreCase("GreaterThanEquals")) {
// builder.append(" >= ");
expBuilder
.append(fHelper
.getGreaterThanEqualseExpression(fieldName));
}
else if (reservedToken.equalsIgnoreCase("Equals")) {
// builder.append(" = ");
expBuilder.append(fHelper
.getEqualExpression(fieldName));
}
if (expBuilder != null) {
// Hold current expression with condition applied
// to create the full expression with an operator
condition = expBuilder;
}
isConditionApplied = true;
isNewField = false;
}
}
else {
// Create the expression if lastToken is Collection type
String colType = lastFieldToken.getField().getFieldType()
.getSimpleTypeName().toString();
op = reservedToken.toLowerCase();
expBuilder.append(String.format(
".getCollection(\"%s\", %s.class).contains(%s)",
fieldName, colType, fieldName));
createBaseSearchExpressionWithNullCheck(bodyBuilder,
fHelper, lastFieldToken, expBuilder, op);
isOperatorApplied = true;
isNewField = false;
}
}
else {
// Current token is a field
lastFieldToken = (FieldToken) token;
isNewField = true;
}
}
if (isNewField) {
// New field is located but no operation
// has found. generate an expression using
// equals operator
expBuilder = new StringBuilder("entity");
String fieldName = lastFieldToken.getField().getFieldName()
.getSymbolName();
JavaType fieldType = fHelper.getFieldTypeOfFinder(fieldName);
if (lastFieldToken != null
&& !lastFieldToken.getField().getFieldType()
.isCommonCollectionType()) {
expBuilder
.append(fHelper.getDslGetterFor(fieldName, fieldType));
expBuilder.append(fHelper.getEqualExpression(fieldName));
}
else if (lastFieldToken.getField().getFieldType()
.isCommonCollectionType()) {
String colType = lastFieldToken.getField().getFieldType()
.getSimpleTypeName().toString();
expBuilder.append(String.format(
".getCollection(\"%s\", %s.class).contains(%s)",
fieldName, colType, fieldName));
}
isConditionApplied = true;
}
// Create the whole expression if it's not alreeady created
if (!isBetweenCondition) {
if (!isOperatorApplied) {
// Use default operator if it isnt applied
createBaseSearchExpressionWithNullCheck(bodyBuilder, fHelper,
lastFieldToken, expBuilder, "and");
}
else {
// Use hold operator
createBaseSearchExpressionWithNullCheck(bodyBuilder, fHelper,
lastFieldToken, expBuilder, op);
}
}
}
private void createBaseSearchExpressionWithNullCheck(
InvocableMemberBodyBuilder bodyBuilder, FinderToDslHelper fHelper,
FieldToken lastFieldToken, StringBuilder expBuilder,
String operation) {
// Getting fieldName and fieldType
String fieldName = lastFieldToken.getField().getFieldName()
.getSymbolName();
JavaType fieldType = lastFieldToken.getField().getFieldType();
// Booleans doesn't need null validation
if (JavaType.BOOLEAN_PRIMITIVE.equals(fieldType)
|| JavaType.BOOLEAN_OBJECT.equals(fieldType)) {
bodyBuilder.appendFormalLine(fHelper.getDslAnd(expBuilder
.toString()));
}
else {
String nullExpression = "";
String dslOperation = "";
String dslOperationNull = "";
String nullValidation = "";
if ("and".equals(operation)) {
nullExpression = String.format("entity%s.isNull()",
fHelper.getDslGetterFor(fieldName, fieldType));
dslOperation = fHelper.getDslAnd(expBuilder.toString());
dslOperationNull = fHelper.getDslAnd(nullExpression);
nullValidation = String.format("if(%s != null){", fieldName);
}
else if ("or".equals(operation)) {
nullExpression = String.format("entity%s.isNull()",
fHelper.getDslGetterFor(fieldName, fieldType));
dslOperation = fHelper.getDslOr(expBuilder.toString());
dslOperationNull = fHelper.getDslOr(nullExpression);
nullValidation = String.format("if(%s != null){", fieldName);
}
else if ("between".equals(operation)) {
// Getting min max variables
String capitalized = StringUtils.capitalize(fieldName);
String min = "min".concat(capitalized);
String max = "max".concat(capitalized);
// Generating expression
expBuilder.append(fHelper.getBetweenExpression(fieldName));
nullExpression = String.format("entity%s.isNull()",
fHelper.getDslGetterFor(fieldName, fieldType));
dslOperation = fHelper.getDslAnd(expBuilder.toString());
dslOperationNull = fHelper.getDslAnd(nullExpression);
nullValidation = String.format("if(%s != null && %s != null){",
min, max);
}
if (fieldType.isCommonCollectionType()) {
String colType = fieldType.getSimpleTypeName().toString();
nullExpression = String.format(
"entity.getCollection(\"%s\", %s.class).isEmpty()",
fieldName, colType);
dslOperation = fHelper.getDslAnd(expBuilder.toString());
dslOperationNull = fHelper.getDslAnd(nullExpression);
nullValidation = String.format("if(%s != null){", fieldName);
}
// There is an expression not included in predicate yet.
// Include it using "and" join
if (expBuilder != null && StringUtils.isNotBlank(nullExpression)) {
bodyBuilder.appendFormalLine(nullValidation);
// filterCondition.and( {exp});
bodyBuilder.indent();
bodyBuilder.appendFormalLine(dslOperation);
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}else{");
bodyBuilder.indent();
bodyBuilder.appendFormalLine(dslOperationNull);
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
}
}
}
/**
* Gets <code>populateDatatablesConfig</code> method <br>
* This method insert on Model all configuration properties which will need
* ".tagx" to render final page. <br>
* This properties are:
* <ul>
* <li><em>datatablesHasBatchSupport</em> informs if there is batch entity
* operations support on controller (used for multi-row delete operation)</li>
* <li><em>datatablesUseAjax</em> informs datatables data mode (
* <em>true</em> : AJAX <em>false</em> DOM)</li>
* <li><em>finderNameParam</em> sets the name of parameter that will contain
* the {@code finderName} (only for AJAX mode)</li>
* <li><em>datatablesStandardMode</em> informs render mode (<em>true</em>
* for standard datatable view; <em>false</em> for single-item-page,
* one-cell-per-item or render-jspx datatable modes)</li>
* </ul>
*
* @return
*/
private MethodMetadata getPopulateDatatablesConfig() {
// Define method parameter types
List<AnnotatedJavaType> parameterTypes = AnnotatedJavaType
.convertFromJavaTypes(MODEL);
// Check if a method with the same signature already exists in the
// target type
final MethodMetadata method = methodExists(POPULATE_DATATABLES_CONFIG,
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>();
AnnotationMetadataBuilder annotation = new AnnotationMetadataBuilder(
MODEL_ATTRIBUTE);
// @ModelAttribute
annotations.add(annotation);
// 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(UI_MODEL);
// Create the method body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
bodyBuilder.appendFormalLine(String.format(
"uiModel.addAttribute(\"datatablesHasBatchSupport\", %s);",
hasJpaBatchSupport()));
bodyBuilder.appendFormalLine(String.format(
"uiModel.addAttribute(\"datatablesUseAjax\",%s);", isAjax()));
bodyBuilder.appendFormalLine(String.format(
"uiModel.addAttribute(\"datatablesInlineEditing\",%s);",
isInlineEditing()));
bodyBuilder.appendFormalLine(String.format(
"uiModel.addAttribute(\"datatablesInlineCreating\",%s);",
isInlineEditing()));
// TODO
bodyBuilder.appendFormalLine(String.format(
"uiModel.addAttribute(\"datatablesSecurityApplied\",%s);",
isSecurityApplied()));
bodyBuilder.appendFormalLine(String.format(
"uiModel.addAttribute(\"datatablesStandardMode\",%s);",
isStantardMode()));
if (isAjax()) {
bodyBuilder
.appendFormalLine("uiModel.addAttribute(\"finderNameParam\",\"ajax_find\");");
}
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
getId(), Modifier.PUBLIC, POPULATE_DATATABLES_CONFIG,
JavaType.VOID_PRIMITIVE, parameterTypes, parameterNames,
bodyBuilder);
methodBuilder.setAnnotations(annotations);
methodBuilder.setThrowsTypes(throwsTypes);
return methodBuilder.build(); // Build and return a MethodMetadata
// instance
}
/**
* Gets <code>populateItemForRender</code> method <br>
* This methods prepares request attributes to render a entity item in
* non-standard render mode. User can make push-in of this method to
* customize the parameters received on target .jspx view.
*
* @return
*/
private MethodMetadata getPopulateItemForRenderMethod() {
// Define method parameter types
List<AnnotatedJavaType> parameterTypes = AnnotatedJavaType
.convertFromJavaTypes(HTTP_SERVLET_REQUEST, entity,
JavaType.BOOLEAN_PRIMITIVE);
// Check if a method with the same signature already exists in the
// target type
final MethodMetadata method = methodExists(POPULATE_ITEM_FOR_RENDER,
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(REQUEST_PARAM_NAME);
parameterNames.add(new JavaSymbolName(StringUtils
.uncapitalize(entityName)));
parameterNames.add(new JavaSymbolName("editing"));
// Create the method body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
buildPopulateItemForRenderMethodBody(bodyBuilder);
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
getId(), Modifier.PUBLIC, POPULATE_ITEM_FOR_RENDER,
JavaType.VOID_PRIMITIVE, parameterTypes, parameterNames,
bodyBuilder);
methodBuilder.setAnnotations(annotations);
methodBuilder.setThrowsTypes(throwsTypes);
return methodBuilder.build(); // Build and return a MethodMetadata
// instance
}
/**
* Gets <code>checkFilterExpressions</code> method <br>
* This methods checks if the current filter expression is appropieta for
* the property type.
*
* @return If is correct, return true, if not, return false,
*/
private MethodMetadata getCheckFilterExpressionsMethod() {
// Define method parameter types
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
parameterTypes.add(AnnotatedJavaType.convertFromJavaType(WEB_REQUEST));
parameterTypes.add(helper.createRequestParam(JavaType.STRING,
"property", false, null));
parameterTypes.add(helper.createRequestParam(JavaType.STRING,
"expression", false, null));
// Check if a method with the same signature already exists in the
// target type
final MethodMetadata method = methodExists(CHECK_FILTER_EXPRESSIONS,
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>();
AnnotationMetadataBuilder methodAnnotation = new AnnotationMetadataBuilder();
methodAnnotation.setAnnotationType(REQUEST_MAPPING);
methodAnnotation.addStringAttribute(HEADERS, ACCEPT_APPLICATION_JSON);
methodAnnotation.addStringAttribute(PARAMS_VAR, "checkFilters");
annotations.add(methodAnnotation);
annotations.add(new AnnotationMetadataBuilder(RESPONSE_BODY));
// 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(REQUEST_PARAM_NAME);
parameterNames.add(new JavaSymbolName("property"));
parameterNames.add(new JavaSymbolName("expression"));
// Create the method body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
buildCheckFilterExpressionMethodBody(bodyBuilder);
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
getId(), Modifier.PUBLIC, CHECK_FILTER_EXPRESSIONS,
CHECK_FILTERS_RETURN, parameterTypes, parameterNames,
bodyBuilder);
methodBuilder.setAnnotations(annotations);
methodBuilder.setThrowsTypes(throwsTypes);
return methodBuilder.build(); // Build and return a MethodMetadata
// instance
}
/**
* Build standard body method for <code>populateItemForRender</code> method <br>
* This methods prepares request attributes to render a entity item in
* non-standard render mode. User can make push-in of this method to
* customize the parameters received on target .jspx view.
*
* @param bodyBuilder
*/
private void buildPopulateItemForRenderMethodBody(
InvocableMemberBodyBuilder bodyBuilder) {
// Model uiModel = new ExtendedModelMap();
bodyBuilder.appendFormalLine(String.format("%s uiModel = new %s();",
MODEL, EXTENDED_MODEL_MAP));
bodyBuilder.appendFormalLine("");
// request.setAttribute("pet", pet);
bodyBuilder.appendFormalLine(String.format(
"%s.setAttribute(\"%s\", %s);",
REQUEST_PARAM_NAME.getSymbolName(),
StringUtils.uncapitalize(entityName),
StringUtils.uncapitalize(entityName)
));
// request.setAttribute("itemId",
// conversion_service.convert(pet.getId(), String.class);
bodyBuilder
.appendFormalLine(String
.format("%s.setAttribute(\"itemId\", %s.convert(%s.get%s(),String.class));",
REQUEST_PARAM_NAME.getSymbolName(),
getConversionServiceField().getFieldName()
.getSymbolName(), StringUtils
.uncapitalize(entityName),
StringUtils.capitalize(entityIdentifier
.getFieldName().getSymbolName())));
bodyBuilder.appendFormalLine("");
// if (editing) {
bodyBuilder.appendFormalLine("if (editing) {");
bodyBuilder.indent();
// // spring from:input tag uses BindingResult to locate property
// editors for each bean
// // property. So, we add a request attribute (required key id
// BindingResult.MODEL_KEY_PREFIX + object name)
// // with a correctly initialized bindingResult.
bodyBuilder
.appendFormalLine("// spring from:input tag uses BindingResult to locate property editors for each bean");
bodyBuilder
.appendFormalLine("// property. So, we add a request attribute (required key id BindingResult.MODEL_KEY_PREFIX + object name)");
bodyBuilder
.appendFormalLine("// with a correctly initialized bindingResult.");
// BeanPropertyBindingResult bindindResult = new
// BeanPropertyBindingResult(vet, "vet");
bodyBuilder.appendFormalLine(String.format(
"%s bindindResult = new %s(%s, \"%s\");",
helper.getFinalTypeName(BEAN_PROPERTY_BINDING_RESULT),
helper.getFinalTypeName(BEAN_PROPERTY_BINDING_RESULT),
StringUtils.uncapitalize(entityName),
StringUtils.uncapitalize(entityName)));
// bindindResult.initConversion(conversionService_datatables);
bodyBuilder.appendFormalLine(String.format(
"bindindResult.initConversion(%s);",
getConversionServiceField().getFieldName().getSymbolName()));
// request.setAttribute(BindingResult.MODEL_KEY_PREFIX +
// "vet",bindindResult);
bodyBuilder.appendFormalLine(String.format(
"%s.setAttribute(%s.MODEL_KEY_PREFIX + \"%s\",bindindResult);",
REQUEST_PARAM_NAME.getSymbolName(),
helper.getFinalTypeName(SpringJavaType.BINDING_RESULT),
StringUtils.uncapitalize(entityName)));
// // Add date time patterns and enums to populate inputs
bodyBuilder
.appendFormalLine("// Add date time patterns and enums to populate inputs");
// populateEditForm(uiModel, vet);
bodyBuilder.appendFormalLine(String.format(
"populateEditForm(uiModel, %s);",
StringUtils.uncapitalize(entityName)));
if (!entityDatePatterns.isEmpty()) {
// } else {
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine(ELSE);
bodyBuilder.indent();
// // Add date time patterns
bodyBuilder.appendFormalLine("// Add date time patterns");
// Add date patterns (if any)
// Delegates on Roo standard populate date patterns method
// addDateTimeFormatPatterns(uiModel);
bodyBuilder.appendFormalLine("addDateTimeFormatPatterns(uiModel);");
}
// }
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
bodyBuilder.appendFormalLine("");
// Load uiModel attributes into request
bodyBuilder.appendFormalLine("// Load uiModel attributes into request");
// Map<String,Object> modelMap = uiModel.asMap();
bodyBuilder.appendFormalLine(String.format(
"%s modelMap = uiModel.asMap();",
helper.getFinalTypeName(MAP_STRING_OBJECT)));
// for (Entry<String,Object> entry : uiModel.asMap().entrySet()){
bodyBuilder.appendFormalLine(String.format(
"for (%s key : modelMap.keySet()){",
helper.getFinalTypeName(JavaType.STRING)));
bodyBuilder.indent();
// request.setAttribute(entry.getKey(), entry.getValue());
bodyBuilder
.appendFormalLine("request.setAttribute(key, modelMap.get(key));");
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
}
/**
* Build standard body method for <code>checkFilterExpression</code> method <br>
* This methods checks if the current filter expression is appropieta for
* the property type.
*
* @param bodyBuilder
*/
private void buildCheckFilterExpressionMethodBody(
InvocableMemberBodyBuilder bodyBuilder) {
// HttpHeaders headers = new HttpHeaders();
// headers.add("Content-Type", "application/json; charset=utf-8");
bodyBuilder.appendFormalLine(String.format("%s headers = new %s();",
helper.getFinalTypeName(SpringJavaType.HTTP_HEADERS),
helper.getFinalTypeName(SpringJavaType.HTTP_HEADERS)));
bodyBuilder
.appendFormalLine("headers.add(\"Content-Type\", \"application/json; charset=utf-8\");");
// if(beanWrapper_dtt == null){
bodyBuilder.appendFormalLine("if(beanWrapper_dtt == null){");
bodyBuilder.indent();
// beanWrapper_dtt = new BeanWrapperImpl(XXX.class);
bodyBuilder.appendFormalLine(String.format(
"beanWrapper_dtt = new %s(%s.class);", helper
.getFinalTypeName(new JavaType(
"org.springframework.beans.BeanWrapperImpl")),
helper.getFinalTypeName(entity)));
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
// Class type = beanWrapper_dtt.getPropertyType(property);
bodyBuilder
.appendFormalLine("Class type = beanWrapper_dtt.getPropertyType(property);");
// boolean response =
// datatablesUtilsBean_dtt.checkFilterExpressions(type,
// expression);
bodyBuilder
.appendFormalLine("boolean response = datatablesUtilsBean_dtt.checkFilterExpressions(type,expression);");
// return new ResponseEntity<String>(
// String.format("{ \"response\": %s, \"property\": \"%s\"}",
// response, property), headers, HttpStatus.OK);
String returnStatement = "return new ResponseEntity<String>(String.format(\"{ \\\"response\\\": %s, \\\"property\\\": \\\"%s\\\"}\",response, property), headers, ";
bodyBuilder.appendFormalLine(returnStatement.concat(String.format(
"%s.OK);", SpringJavaType.HTTP_STATUS)));
}
/**
* Returns <code>geti18nText</code> method <br>
* This method returns column type after AJAX request
*
* @return
*/
private MethodMetadata geti18nTextRequestMethod() {
// Define method parameter types
final List<AnnotatedJavaType> parameterTypes = Arrays.asList(
new AnnotatedJavaType(MODEL), AnnotatedJavaType
.convertFromJavaType(HTTP_SERVLET_REQUEST), helper
.createRequestParam(JavaType.STRING, "_locale_", false,
null));
// Check if a method with the same signature already exists in the
// target type
final MethodMetadata method = methodExists(GET_I18N_TEXT,
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>();
// @RequestMapping
AnnotationMetadataBuilder methodAnnotation = new AnnotationMetadataBuilder();
methodAnnotation.setAnnotationType(REQUEST_MAPPING);
// @RequestMapping(headers = "Accept=application/json"...
methodAnnotation.addStringAttribute(HEADERS, ACCEPT_APPLICATION_JSON);
// @RequestMapping(params = "geti18nText"...
methodAnnotation.addStringAttribute(PARAMS_VAR, "geti18nText");
// @ResponseBody
annotations.add(new AnnotationMetadataBuilder(RESPONSE_BODY));
annotations.add(methodAnnotation);
// 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(UI_MODEL);
parameterNames.add(new JavaSymbolName(
DatatablesConstants.REQUEST_PARAMETER_NAME));
parameterNames.add(new JavaSymbolName("locale"));
// Create the method body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
buildGeti18nTextMethodBody(bodyBuilder);
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
getId(), Modifier.PUBLIC, GET_I18N_TEXT, JavaType.STRING,
parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
methodBuilder.setThrowsTypes(throwsTypes);
return methodBuilder.build(); // Build and return a MethodMetadata
// instance
}
/**
* Build method body for <code>Geti18nText</code> method
*
* @param bodyBuilder
*/
private void buildGeti18nTextMethodBody(
InvocableMemberBodyBuilder bodyBuilder) {
// TODO Auto-generated method stub
bodyBuilder.appendFormalLine("// Getting current locale");
bodyBuilder.appendFormalLine(String.format(
"%s defaultLocale = new Locale(locale);",
helper.getFinalTypeName(new JavaType("java.util.Locale"))));
bodyBuilder.appendFormalLine("// Building JSON response");
bodyBuilder
.appendFormalLine("StringBuilder json = new StringBuilder();");
bodyBuilder.appendFormalLine("json.append(\"{\");");
bodyBuilder
.appendFormalLine("json.append(\"\\\"all_isnull\\\": \\\"\" + messageSource_dtt.getMessage(\"global.filters.operations.all.isnull\", null, defaultLocale) + \"\\\"\");");
bodyBuilder.appendFormalLine(JSON_APPEND);
bodyBuilder
.appendFormalLine("json.append(\"\\\"all_notnull\\\": \\\"\" + messageSource_dtt.getMessage(\"global.filters.operations.all.notnull\", null, defaultLocale) + \"\\\"\");");
bodyBuilder.appendFormalLine(JSON_APPEND);
bodyBuilder
.appendFormalLine("json.append(\"\\\"boolean_false\\\": \\\"\" + messageSource_dtt.getMessage(\"global.filters.operations.boolean.false\", null, defaultLocale) + \"\\\"\");");
bodyBuilder.appendFormalLine(JSON_APPEND);
bodyBuilder
.appendFormalLine("json.append(\"\\\"boolean_true\\\": \\\"\" + messageSource_dtt.getMessage(\"global.filters.operations.boolean.true\", null, defaultLocale) + \"\\\"\");");
bodyBuilder.appendFormalLine(JSON_APPEND);
bodyBuilder
.appendFormalLine("json.append(\"\\\"date_between\\\": \\\"\" + messageSource_dtt.getMessage(\"global.filters.operations.date.between\", null, defaultLocale) + \"\\\"\");");
bodyBuilder.appendFormalLine(JSON_APPEND);
bodyBuilder
.appendFormalLine("json.append(\"\\\"date_date\\\": \\\"\" + messageSource_dtt.getMessage(\"global.filters.operations.date.date\", null, defaultLocale) + \"\\\"\");");
bodyBuilder.appendFormalLine(JSON_APPEND);
bodyBuilder
.appendFormalLine("json.append(\"\\\"date_day\\\": \\\"\" + messageSource_dtt.getMessage(\"global.filters.operations.date.day\", null, defaultLocale) + \"\\\"\");");
bodyBuilder.appendFormalLine(JSON_APPEND);
bodyBuilder
.appendFormalLine("json.append(\"\\\"date_month\\\": \\\"\" + messageSource_dtt.getMessage(\"global.filters.operations.date.month\", null, defaultLocale) + \"\\\"\");");
bodyBuilder.appendFormalLine(JSON_APPEND);
bodyBuilder
.appendFormalLine("json.append(\"\\\"date_year\\\": \\\"\" + messageSource_dtt.getMessage(\"global.filters.operations.date.year\", null, defaultLocale) + \"\\\"\");");
bodyBuilder.appendFormalLine(JSON_APPEND);
bodyBuilder
.appendFormalLine("json.append(\"\\\"number_between\\\": \\\"\" + messageSource_dtt.getMessage(\"global.filters.operations.number.between\", null, defaultLocale) + \"\\\"\");");
bodyBuilder.appendFormalLine(JSON_APPEND);
bodyBuilder
.appendFormalLine("json.append(\"\\\"string_contains\\\": \\\"\" + messageSource_dtt.getMessage(\"global.filters.operations.string.contains\", null, defaultLocale) + \"\\\"\");");
bodyBuilder.appendFormalLine(JSON_APPEND);
bodyBuilder
.appendFormalLine("json.append(\"\\\"string_ends\\\": \\\"\" + messageSource_dtt.getMessage(\"global.filters.operations.string.ends\", null, defaultLocale) + \"\\\"\");");
bodyBuilder.appendFormalLine(JSON_APPEND);
bodyBuilder
.appendFormalLine("json.append(\"\\\"string_isempty\\\": \\\"\" + messageSource_dtt.getMessage(\"global.filters.operations.string.isempty\", null, defaultLocale) + \"\\\"\");");
bodyBuilder.appendFormalLine(JSON_APPEND);
bodyBuilder
.appendFormalLine("json.append(\"\\\"string_isnotempty\\\": \\\"\" + messageSource_dtt.getMessage(\"global.filters.operations.string.isnotempty\", null, defaultLocale) + \"\\\"\");");
bodyBuilder.appendFormalLine(JSON_APPEND);
bodyBuilder
.appendFormalLine("json.append(\"\\\"string_starts\\\": \\\"\" + messageSource_dtt.getMessage(\"global.filters.operations.string.starts\", null, defaultLocale) + \"\\\"\");");
bodyBuilder.appendFormalLine(JSON_APPEND);
bodyBuilder
.appendFormalLine("json.append(\"\\\"button_find\\\": \\\"\" + messageSource_dtt.getMessage(\"button_find\", null, defaultLocale) + \"\\\"\");");
bodyBuilder.appendFormalLine(JSON_APPEND);
bodyBuilder
.appendFormalLine("json.append(\"\\\"help_all_isnull\\\": \\\"\" + messageSource_dtt.getMessage(\"help.all.isnull\", null, defaultLocale) + \"\\\"\");");
bodyBuilder.appendFormalLine(JSON_APPEND);
bodyBuilder
.appendFormalLine("json.append(\"\\\"help_all_notnull\\\": \\\"\" + messageSource_dtt.getMessage(\"help.all.notnull\", null, defaultLocale) + \"\\\"\");");
bodyBuilder.appendFormalLine(JSON_APPEND);
bodyBuilder
.appendFormalLine("json.append(\"\\\"help_boolean_false\\\": \\\"\" + messageSource_dtt.getMessage(\"help.boolean.false\", null, defaultLocale) + \"\\\"\");");
bodyBuilder.appendFormalLine(JSON_APPEND);
bodyBuilder
.appendFormalLine("json.append(\"\\\"help_boolean_true\\\": \\\"\" + messageSource_dtt.getMessage(\"help.boolean.true\", null, defaultLocale) + \"\\\"\");");
bodyBuilder.appendFormalLine(JSON_APPEND);
bodyBuilder
.appendFormalLine("json.append(\"\\\"help_date_between\\\": \\\"\" + messageSource_dtt.getMessage(\"help.date.between\", null, defaultLocale) + \"\\\"\");");
bodyBuilder.appendFormalLine(JSON_APPEND);
bodyBuilder
.appendFormalLine("json.append(\"\\\"help_date_date\\\": \\\"\" + messageSource_dtt.getMessage(\"help.date.date\", null, defaultLocale) + \"\\\"\");");
bodyBuilder.appendFormalLine(JSON_APPEND);
bodyBuilder
.appendFormalLine("json.append(\"\\\"help_date_day\\\": \\\"\" + messageSource_dtt.getMessage(\"help.date.day\", null, defaultLocale) + \"\\\"\");");
bodyBuilder.appendFormalLine(JSON_APPEND);
bodyBuilder
.appendFormalLine("json.append(\"\\\"help_date_month\\\": \\\"\" + messageSource_dtt.getMessage(\"help.date.month\", null, defaultLocale) + \"\\\"\");");
bodyBuilder.appendFormalLine(JSON_APPEND);
bodyBuilder
.appendFormalLine("json.append(\"\\\"help_date_year\\\": \\\"\" + messageSource_dtt.getMessage(\"help.date.year\", null, defaultLocale) + \"\\\"\");");
bodyBuilder.appendFormalLine(JSON_APPEND);
bodyBuilder
.appendFormalLine("json.append(\"\\\"help_number_between\\\": \\\"\" + messageSource_dtt.getMessage(\"help.number.between\", null, defaultLocale) + \"\\\"\");");
bodyBuilder.appendFormalLine(JSON_APPEND);
bodyBuilder
.appendFormalLine("json.append(\"\\\"help_number_eq\\\": \\\"\" + messageSource_dtt.getMessage(\"help.number.eq\", null, defaultLocale) + \"\\\"\");");
bodyBuilder.appendFormalLine(JSON_APPEND);
bodyBuilder
.appendFormalLine("json.append(\"\\\"help_number_neq\\\": \\\"\" + messageSource_dtt.getMessage(\"help.number.neq\", null, defaultLocale) + \"\\\"\");");
bodyBuilder.appendFormalLine(JSON_APPEND);
bodyBuilder
.appendFormalLine("json.append(\"\\\"help_number_gt\\\": \\\"\" + messageSource_dtt.getMessage(\"help.number.gt\", null, defaultLocale) + \"\\\"\");");
bodyBuilder.appendFormalLine(JSON_APPEND);
bodyBuilder
.appendFormalLine("json.append(\"\\\"help_number_lt\\\": \\\"\" + messageSource_dtt.getMessage(\"help.number.lt\", null, defaultLocale) + \"\\\"\");");
bodyBuilder.appendFormalLine(JSON_APPEND);
bodyBuilder
.appendFormalLine("json.append(\"\\\"help_number_goe\\\": \\\"\" + messageSource_dtt.getMessage(\"help.number.goe\", null, defaultLocale) + \"\\\"\");");
bodyBuilder.appendFormalLine(JSON_APPEND);
bodyBuilder
.appendFormalLine("json.append(\"\\\"help_number_loe\\\": \\\"\" + messageSource_dtt.getMessage(\"help.number.loe\", null, defaultLocale) + \"\\\"\");");
bodyBuilder.appendFormalLine(JSON_APPEND);
bodyBuilder
.appendFormalLine("json.append(\"\\\"help_string_contains\\\": \\\"\" + messageSource_dtt.getMessage(\"help.string.contains\", null, defaultLocale) + \"\\\"\");");
bodyBuilder.appendFormalLine(JSON_APPEND);
bodyBuilder
.appendFormalLine("json.append(\"\\\"help_string_ends\\\": \\\"\" + messageSource_dtt.getMessage(\"help.string.ends\", null, defaultLocale) + \"\\\"\");");
bodyBuilder.appendFormalLine(JSON_APPEND);
bodyBuilder
.appendFormalLine("json.append(\"\\\"help_string_isempty\\\": \\\"\" + messageSource_dtt.getMessage(\"help.string.isempty\", null, defaultLocale) + \"\\\"\");");
bodyBuilder.appendFormalLine(JSON_APPEND);
bodyBuilder
.appendFormalLine("json.append(\"\\\"help_string_isnotempty\\\": \\\"\" + messageSource_dtt.getMessage(\"help.string.isnotempty\", null, defaultLocale) + \"\\\"\");");
bodyBuilder.appendFormalLine(JSON_APPEND);
bodyBuilder
.appendFormalLine("json.append(\"\\\"help_string_starts\\\": \\\"\" + messageSource_dtt.getMessage(\"help.string.starts\", null, defaultLocale) + \"\\\"\");");
bodyBuilder.appendFormalLine("json.append(\"}\");");
bodyBuilder.appendFormalLine("// return JSON with locale strings");
bodyBuilder.appendFormalLine("return json.toString();");
}
/**
* Returns <code>getColumnType</code> method <br>
* This method is to return column type after AJAX request
*
* @return
*/
private MethodMetadata getColumnTypeRequestMethod() {
// Define method parameter types
final List<AnnotatedJavaType> parameterTypes = Arrays.asList(
new AnnotatedJavaType(MODEL), AnnotatedJavaType
.convertFromJavaType(HTTP_SERVLET_REQUEST), helper
.createRequestParam(JavaType.STRING, "_columnName_",
false, null));
// Check if a method with the same signature already exists in the
// target type
final MethodMetadata method = methodExists(GET_COLUMN_TYPE,
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>();
// @RequestMapping
AnnotationMetadataBuilder methodAnnotation = new AnnotationMetadataBuilder();
methodAnnotation.setAnnotationType(REQUEST_MAPPING);
// @RequestMapping(headers = "Accept=application/json"...
methodAnnotation.addStringAttribute(HEADERS, ACCEPT_APPLICATION_JSON);
// @RequestMapping(params = "getColumnType"...
methodAnnotation.addStringAttribute(PARAMS_VAR, "getColumnType");
// @ResponseBody
annotations.add(new AnnotationMetadataBuilder(RESPONSE_BODY));
annotations.add(methodAnnotation);
// 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(UI_MODEL);
parameterNames.add(new JavaSymbolName(
DatatablesConstants.REQUEST_PARAMETER_NAME));
parameterNames.add(new JavaSymbolName("columnName"));
// Create the method body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
buildGetColumnTypeMethodBody(bodyBuilder);
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
getId(), Modifier.PUBLIC, GET_COLUMN_TYPE, JavaType.STRING,
parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
methodBuilder.setThrowsTypes(throwsTypes);
return methodBuilder.build(); // Build and return a MethodMetadata
// instance
}
/**
* Build method body for <code>GetColumnType</code> method
*
* @param bodyBuilder
*/
private void buildGetColumnTypeMethodBody(
InvocableMemberBodyBuilder bodyBuilder) {
JavaSymbolName entity = new JavaSymbolName(entityName);
// Getting all declared fields
bodyBuilder.appendFormalLine("// Getting all declared fields");
// boolean fieldExists = false;
bodyBuilder.appendFormalLine("boolean fieldExists = false;");
// Field attr = null;
bodyBuilder.appendFormalLine(String.format("%s attr = null;", helper
.getFinalTypeName(new JavaType("java.lang.reflect.Field"))));
// for(Field field : Owner.class.getDeclaredFields()){
bodyBuilder.appendFormalLine(String.format(
"for(Field field : %s.class.getDeclaredFields()){",
entity.getSymbolNameCapitalisedFirstLetter()));
bodyBuilder.indent();
// if(field.getName().equals(columnName)){
bodyBuilder.appendFormalLine("if(field.getName().equals(columnName)){");
bodyBuilder.indent();
// attr = field;
bodyBuilder.appendFormalLine("attr = field;");
// fieldExists = true;
bodyBuilder.appendFormalLine("fieldExists = true;");
// break;
bodyBuilder.appendFormalLine("break;");
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
// // If current field not exists on entity, find on superclass
bodyBuilder
.appendFormalLine("// If current field not exists on entity, find on superclass");
// if(!fieldExists){
bodyBuilder.appendFormalLine("if(!fieldExists){");
bodyBuilder.indent();
// if(Owner.class.getSuperclass() != null){
bodyBuilder.appendFormalLine(String.format(
"if(%s.class.getSuperclass() != null){",
entity.getSymbolNameCapitalisedFirstLetter()));
bodyBuilder.indent();
// for(Field field : Owner.class.getSuperclass().getDeclaredFields()){
bodyBuilder
.appendFormalLine(String
.format("for(Field field : %s.class.getSuperclass().getDeclaredFields()){",
entity.getSymbolNameCapitalisedFirstLetter()));
bodyBuilder.indent();
// if(field.getName().equals(columnName)){
bodyBuilder.appendFormalLine("if(field.getName().equals(columnName)){");
bodyBuilder.indent();
// attr = field;
bodyBuilder.appendFormalLine("attr = field;");
// fieldExists = true;
bodyBuilder.appendFormalLine("fieldExists = true;");
// break;
bodyBuilder.appendFormalLine("break;");
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
// if(fieldExists){
bodyBuilder.appendFormalLine("if(fieldExists){");
bodyBuilder.indent();
bodyBuilder.appendFormalLine("// Getting field type");
bodyBuilder.appendFormalLine("Object fieldType = null;");
bodyBuilder.appendFormalLine("if (attr != null) {");
bodyBuilder.indent();
bodyBuilder.appendFormalLine("fieldType = attr.getType();");
bodyBuilder.appendFormalLine("String type = fieldType.toString();");
bodyBuilder.appendFormalLine("// Returning value based on type");
bodyBuilder.appendFormalLine("if (\"String\".equals(type)){");
bodyBuilder.indent();
bodyBuilder
.appendFormalLine("return \"{\\\"columnType\\\": \\\"string\\\"}\";");
bodyBuilder.indentRemove();
bodyBuilder
.appendFormalLine("} else if (\"float\".equals(type) || type.contains(\"Float\")){");
bodyBuilder.indent();
bodyBuilder.appendFormalLine(COLTYPE_NUM);
bodyBuilder.indentRemove();
bodyBuilder
.appendFormalLine("} else if (\"short\".equals(type) || type.contains(\"Short\")){");
bodyBuilder.indent();
bodyBuilder.appendFormalLine(COLTYPE_NUM);
bodyBuilder.indentRemove();
bodyBuilder
.appendFormalLine("} else if (\"long\".equals(type) || type.contains(\"Long\")){");
bodyBuilder.indent();
bodyBuilder.appendFormalLine(COLTYPE_NUM);
bodyBuilder.indentRemove();
bodyBuilder
.appendFormalLine("} else if (\"double\".equals(type) || type.contains(\"Double\")){");
bodyBuilder.indent();
bodyBuilder.appendFormalLine(COLTYPE_NUM);
bodyBuilder.indentRemove();
bodyBuilder
.appendFormalLine("} else if (\"int\".equals(type) || type.contains(\"Integer\")){");
bodyBuilder.indent();
bodyBuilder.appendFormalLine(COLTYPE_NUM);
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("} else if (\"Date\".equals(type)){");
bodyBuilder.indent();
bodyBuilder
.appendFormalLine("return \"{\\\"columnType\\\": \\\"date\\\"}\";");
bodyBuilder.indentRemove();
bodyBuilder
.appendFormalLine("} else if (\"boolean\".equals(type) || type.contains(\"Boolean\")){");
bodyBuilder.indent();
bodyBuilder
.appendFormalLine("return \"{\\\"columnType\\\": \\\"boolean\\\"}\";");
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine(ELSE);
bodyBuilder.indent();
bodyBuilder.appendFormalLine("// Returning by default");
bodyBuilder
.appendFormalLine("return \"{\\\"columnType\\\": \\\"undefined\\\"}\";");
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
bodyBuilder.appendFormalLine("// Returning by default");
bodyBuilder
.appendFormalLine("return \"{\\\"columnType\\\": \\\"undefined\\\"}\";");
}
/**
* Returns <code>listDatatables</code> method <br>
* This method is default list request handler for datatables controllers
*
* @return
*/
private MethodMetadata getListDatatablesRequestMethod() {
// Define method parameter types
List<AnnotatedJavaType> parameterTypes = AnnotatedJavaType
.convertFromJavaTypes(MODEL, HTTP_SERVLET_REQUEST);
if (!isAjax()) {
// In DOM mode we include Item in parameters to use
// spring's binder to get baseFilter values
parameterTypes.add(new AnnotatedJavaType(entity,
new AnnotationMetadataBuilder(MODEL_ATTRIBUTE).build()));
}
// Check if a method with the same signature already exists in the
// target type
final MethodMetadata method = methodExists(LIST_DATATABLES,
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>();
// @RequestMapping
AnnotationMetadataBuilder methodAnnotation = new AnnotationMetadataBuilder();
methodAnnotation.setAnnotationType(REQUEST_MAPPING);
// @RequestMapping(method = RequestMethod.GET...
methodAnnotation.addEnumAttribute(METHOD_VAR, REQUEST_METHOD, "GET");
// @RequestMapping(... produces = "text/html")
methodAnnotation.addStringAttribute(
DatatablesConstants.RQST_MAP_ANN_PROD_NAME,
DatatablesConstants.RQST_MAP_ANN_VAL_HTML);
annotations.add(methodAnnotation);
// 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(UI_MODEL);
parameterNames.add(new JavaSymbolName(
DatatablesConstants.REQUEST_PARAMETER_NAME));
if (!isAjax()) {
// In DOM mode we include Item in parameters to use
// spring's binder to get baseFilter values
parameterNames.add(new JavaSymbolName(entityName));
}
// Create the method body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
if (isAjax()) {
buildListDatatablesRequesMethodAjaxBody(bodyBuilder);
}
else {
buildListDatatablesRequesMethodDomBody(bodyBuilder);
}
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
getId(), Modifier.PUBLIC, LIST_DATATABLES, JavaType.STRING,
parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
methodBuilder.setThrowsTypes(throwsTypes);
return methodBuilder.build(); // Build and return a MethodMetadata
// instance
}
/**
* Build method body for <code>listDatatables</code> method for DOM mode
*
* @param bodyBuilder
*/
private void buildListDatatablesRequesMethodDomBody(
InvocableMemberBodyBuilder bodyBuilder) {
// // Get parentId parameter for details
bodyBuilder.appendFormalLine("// Get parentId parameter for details");
// if (request.getParameterMap().containsKey("_dt_parentId")){
bodyBuilder
.appendFormalLine("if (request.getParameterMap().containsKey(\"_dt_parentId\")){");
bodyBuilder.indent();
// uiModel.addAttribute("parentId",request.getParameter("_dt_parentId"));
bodyBuilder
.appendFormalLine("uiModel.addAttribute(\"parentId\",request.getParameter(\"_dt_parentId\"));");
// }
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
String listVarName = StringUtils.uncapitalize(entityPlural);
bodyBuilder
.appendFormalLine("// Get data (filtered by received parameters) and put it on pageContext");
// List<Visit> visits =
// findByParameters(visit,request.getParameterNames());
bodyBuilder
.appendFormalLine(String
.format("@SuppressWarnings(\"unchecked\") %s %s = %s(%s, request != null ? request.getParameterNames() : null);",
helper.getFinalTypeName(entityListType),
listVarName,
findByParametersMethodName.getSymbolName(),
entityName));
// uiModel.addAttribute("pets",pets);
bodyBuilder.appendFormalLine(String.format(
"%s.addAttribute(\"%s\",%s);", UI_MODEL.getSymbolName(),
entityPlural.toLowerCase(), listVarName));
buildListDatatablesRequestMethodDetailBody(bodyBuilder);
// return "pets/list";
bodyBuilder.appendFormalLine(String.format("return \"%s/list\";",
webScaffoldAnnotationValues.getPath()));
}
/**
* Build method body for <code>listDatatables</code> method for AJAX mode
*
* @param bodyBuilder
*/
private void buildListDatatablesRequesMethodAjaxBody(
InvocableMemberBodyBuilder bodyBuilder) {
// [Code generated] Map<String, String> params =
// populateParameterMap(request);
bodyBuilder.appendFormalLine(String.format("%s params = %s(request);",
helper.getFinalTypeName(MAP_STRING_STRING),
POPULATE_PARAMETERS_MAP.getSymbolName()));
// [Code generated] // Get parentId information for details render
bodyBuilder
.appendFormalLine("// Get parentId information for details render");
// [Code generated] String parentId = params.remove("_dt_parentId");
bodyBuilder
.appendFormalLine("String parentId = params.remove(\"_dt_parentId\");");
// [Code generated] if (!params.isEmpty()) {
bodyBuilder.appendFormalLine(String.format(
"if (%s.isNotBlank(parentId)) {",
helper.getFinalTypeName(STRING_UTILS)));
bodyBuilder.indent();
// [Code generated] uiModel.addAttribute("parentId", parentId);
bodyBuilder
.appendFormalLine("uiModel.addAttribute(\"parentId\", parentId);");
// [Code generated] }
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
// [Code generated] String rowOnTopIds =
// params.remove("dtt_row_on_top_ids");
bodyBuilder
.appendFormalLine("String rowOnTopIds = params.remove(\"dtt_row_on_top_ids\");");
// [Code generated] if (StringUtils.isNotBlank(rowOnTopIds)) {
bodyBuilder.appendFormalLine(String.format(
"if (%s.isNotBlank(rowOnTopIds)) {",
helper.getFinalTypeName(STRING_UTILS)));
bodyBuilder.indent();
// [Code generated] uiModel.addAttribute("dtt_row_on_top_ids",
// rowOnTopIds);
bodyBuilder
.appendFormalLine("uiModel.addAttribute(\"dtt_row_on_top_ids\", rowOnTopIds);");
bodyBuilder.indentRemove();
// [Code generated] }
bodyBuilder.appendFormalLine("}");
// [Code generated] String tableHashId =
// params.remove("dtt_parent_table_id_hash");
bodyBuilder
.appendFormalLine("String tableHashId = params.remove(\"dtt_parent_table_id_hash\");");
// [Code generated] if (StringUtils.isNotBlank(tableHashId)) {
bodyBuilder.appendFormalLine(String.format(
"if (%s.isNotBlank(tableHashId)) {",
helper.getFinalTypeName(STRING_UTILS)));
bodyBuilder.indent();
// [Code generated] uiModel.addAttribute("dtt_parent_table_id_hash",
// tableHashId);
bodyBuilder
.appendFormalLine("uiModel.addAttribute(\"dtt_parent_table_id_hash\", tableHashId);");
bodyBuilder.indentRemove();
// [Code generated] }
bodyBuilder.appendFormalLine("}");
// [Code generated] if (!params.isEmpty()) {
bodyBuilder.appendFormalLine("if (!params.isEmpty()) {");
bodyBuilder.indent();
// [Code generated] uiModel.addAttribute("baseFilter", params);
bodyBuilder
.appendFormalLine("uiModel.addAttribute(\"baseFilter\", params);");
// [Code generated] }
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
buildListDatatablesRequestMethodDetailBody(bodyBuilder);
// [Code generated] return "pets/list";
bodyBuilder.appendFormalLine(String.format("return \"%s/list\";",
webScaffoldAnnotationValues.getPath()));
}
/**
* Build method body for <code>listDatatables</code> method for AJAX mode
*
* @param bodyBuilder
*/
private void buildListDatatablesRequestMethodDetailBody(
InvocableMemberBodyBuilder bodyBuilder) {
String[] fieldNames = getDetailFields();
if (fieldNames.length > 0) {
bodyBuilder
.appendFormalLine("// Add attribute available into view with information about each detail datatables ");
bodyBuilder.appendFormalLine("Map<String, String> details;");
bodyBuilder
.appendFormalLine("List<Map<String, String>> detailsInfo = new ArrayList<Map<String, String>>("
.concat(String.valueOf(fieldNames.length)).concat(
");"));
List<FieldMetadata> entityFields = entityMemberDetails.getFields();
// For each fields
for (int i = 0; i < fieldNames.length; i++) {
String fieldName = fieldNames[i];
boolean found = false;
for (FieldMetadata entityField : entityFields) {
if (entityField.getFieldName().getSymbolName()
.equals(fieldName)) {
found = true;
buildFieldDetailInfoMethodBody(bodyBuilder, entityField);
}
}
if (!found) {
throw new IllegalStateException(
String.format(
"%s: Can't create datatables detail information: property %s.%s not found",
getAspectName().getFullyQualifiedTypeName(),
entity.getFullyQualifiedTypeName(),
fieldName));
}
}
bodyBuilder
.appendFormalLine("uiModel.addAttribute(\"detailsInfo\", detailsInfo);");
}
}
/**
* Build method code to load detailsInfo with a property information
*
* @param bodyBuilder
* @param entityField
*/
private void buildFieldDetailInfoMethodBody(
InvocableMemberBodyBuilder bodyBuilder, FieldMetadata entityField) {
AnnotationMetadata entityFieldOneToManyAnnotation = entityField
.getAnnotation(new JavaType("javax.persistence.OneToMany"));
// Check property annotation (@OneToMany)
if (entityFieldOneToManyAnnotation == null) {
throw new IllegalStateException(
String.format(
"%s: Can't create datatables detail information: property %s.%s is not OneToMany",
getAspectName().getFullyQualifiedTypeName(), entity
.getFullyQualifiedTypeName(), entityField
.getFieldName().getSymbolName()));
}
if (entityFieldOneToManyAnnotation.getAttribute("mappedBy") == null) {
throw new IllegalStateException(
String.format(
"%s: Can't create datatables detail information: property %s.%s has no mappedBy information",
getAspectName().getFullyQualifiedTypeName(), entity
.getFullyQualifiedTypeName(), entityField
.getFieldName().getSymbolName()));
}
String entityFieldOneToManyAnnotationMappedBy = null;
// Check @OneToMay mappedBy value
try {
entityFieldOneToManyAnnotationMappedBy = entityFieldOneToManyAnnotation
.getAttribute("mappedBy").getValue().toString();
}
catch (Exception e) {
throw new IllegalStateException(
String.format(
"%s: Can't create datatables detail information: property %s.%s has invalid mappedBy information",
getAspectName().getFullyQualifiedTypeName(), entity
.getFullyQualifiedTypeName(), entityField
.getFieldName().getSymbolName()));
}
// Get type of list (entity): if not a list, do
// nothing
JavaType entityFieldBaseType = entityField.getFieldType().getBaseType();
// Get target entity based on property type: ej Set<Pet> --> Pet
if (entityFieldBaseType == null) {
throw new IllegalStateException(
String.format(
"%s: Can't create datatables detail information: property %s.%s can't identify target entity",
getAspectName().getFullyQualifiedTypeName(), entity
.getFullyQualifiedTypeName(), entityField
.getFieldName().getSymbolName()));
}
// Locate target entity metadata
JavaTypeMetadataDetails javaTypeMetadataDetails = webMetadataService
.getJavaTypeMetadataDetails(entityFieldBaseType,
entityMemberDetails,
entityIdentifier.getDeclaredByMetadataId());
// Check if metadata found
if (javaTypeMetadataDetails == null) {
throw new IllegalStateException(
String.format(
"%s: Can't create datatables detail information: property %s.%s can't get target entity metadata",
getAspectName().getFullyQualifiedTypeName(), entity
.getFullyQualifiedTypeName(), entityField
.getFieldName().getSymbolName()));
}
// Generate datailInfo code for current property
bodyBuilder
.appendFormalLine("details = new HashMap<String, String>();");
bodyBuilder
.appendFormalLine("// Base path for detail datatables entity (to get detail datatables fragment URL)");
bodyBuilder.appendFormalLine("details.put(\"path\", \"".concat(
javaTypeMetadataDetails.getControllerPath()).concat(ENDING));
bodyBuilder.appendFormalLine("details.put(\"property\", \"".concat(
entityField.getFieldName().getSymbolName()).concat(ENDING));
bodyBuilder
.appendFormalLine("// Property name in detail entity with the relation to master entity");
bodyBuilder.appendFormalLine("details.put(\"mappedBy\", \"".concat(
entityFieldOneToManyAnnotationMappedBy).concat(ENDING));
bodyBuilder.appendFormalLine("detailsInfo.add(details);");
}
/**
* Redefines {@code list} Roo webScaffod method to delegate on
* {@link #LIST_DATATABLES}
*
* @return
*/
private MethodMetadata getListRooRequestMethod() {
// public String OwnerController.list(
// @RequestParam(value = "page", required = false) Integer page,
// @RequestParam(value = "size", required = false) Integer size,
/** Added on 1.2.6.RELEASE Roo Version */
// @RequestParam(value = "sortFieldName", required = false) String
// sortFieldName,
// @RequestParam(value = "sortOrder", required = false) String sortOrder
/** Added on 1.2.6.RELEASE Roo Version */
// Model uiModel) {
// Define method parameter types
final List<AnnotatedJavaType> parameterTypes = Arrays.asList(
helper.createRequestParam(JavaType.INT_OBJECT, PAGE_VAR, false,
null), helper.createRequestParam(JavaType.INT_OBJECT,
SIZE_VAR, false, null), helper.createRequestParam(
JavaType.STRING, SORT_FIELD_NAME, false, null), helper
.createRequestParam(JavaType.STRING, SORT_ORDER, false,
null), new AnnotatedJavaType(MODEL));
// Check if a method with the same signature already exists in the
// target type
final MethodMetadata method = methodExists(LIST_ROO, 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>();
// @RequestMapping(produces = "text/html")
annotations.add(helper.getRequestMappingAnnotation(null, null, null,
DatatablesConstants.RQST_MAP_ANN_VAL_HTML, null, null));
// Define method throws types (none in this case)
List<JavaType> throwsTypes = new ArrayList<JavaType>();
// Define method parameter names
final List<JavaSymbolName> parameterNames = Arrays.asList(
new JavaSymbolName(PAGE_VAR), new JavaSymbolName(SIZE_VAR),
new JavaSymbolName(SORT_FIELD_NAME), new JavaSymbolName(
SORT_ORDER), UI_MODEL);
// Create the method body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
bodyBuilder
.appendFormalLine("// overrides the standard Roo list method and");
bodyBuilder.appendFormalLine("// delegates on datatables list method");
// return listDatatables(uiModel);
if (isAjax()) {
bodyBuilder.appendFormalLine(String.format(
"return %s(uiModel, null);",
LIST_DATATABLES.getSymbolName()));
}
else {
bodyBuilder.appendFormalLine(String.format(
"return %s(uiModel, null, null);",
LIST_DATATABLES.getSymbolName()));
}
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
getId(), Modifier.PUBLIC, LIST_ROO, JavaType.STRING,
parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
methodBuilder.setThrowsTypes(throwsTypes);
return methodBuilder.build(); // Build and return a MethodMetadata
// instance
}
/**
* Returns <code>findAllMethod</code> method <br>
* This method handles datatables AJAX request for data which are no related
* to a Roo Dynamic finder.
*
* @return
*/
private MethodMetadata getFindAllMethod() {
// Define method parameter types
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
parameterTypes.add(new AnnotatedJavaType(DATATABLES_CRITERIA_TYPE,
new AnnotationMetadataBuilder(DATATABLES_PARAMS).build()));
parameterTypes.add(new AnnotatedJavaType(entity,
new AnnotationMetadataBuilder(MODEL_ATTRIBUTE).build()));
parameterTypes.addAll(AnnotatedJavaType
.convertFromJavaTypes(HTTP_SERVLET_REQUEST));
// Check if a method with the same signature already exists in the
// target type
final MethodMetadata method = methodExists(findAllMethodName,
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>();
AnnotationMetadataBuilder methodAnnotation = new AnnotationMetadataBuilder();
methodAnnotation.setAnnotationType(REQUEST_MAPPING);
methodAnnotation.addStringAttribute(HEADERS, ACCEPT_APPLICATION_JSON);
methodAnnotation.addStringAttribute(
DatatablesConstants.RQST_MAP_ANN_VAL_NAME, "/datatables/ajax");
methodAnnotation.addStringAttribute(
DatatablesConstants.RQST_MAP_ANN_PROD_NAME, APPLICATION_JSON);
annotations.add(methodAnnotation);
annotations.add(new AnnotationMetadataBuilder(RESPONSE_BODY));
// 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(CRITERIA_PARAM_NAME);
parameterNames.add(new JavaSymbolName(StringUtils
.uncapitalize(entityName)));
parameterNames.add(REQUEST_PARAM_NAME);
// Create the method body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
buildFindAllDataMethodBody(bodyBuilder);
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
getId(), Modifier.PUBLIC, findAllMethodName, FIND_ALL_RETURN,
parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
methodBuilder.setThrowsTypes(throwsTypes);
return methodBuilder.build(); // Build and return a MethodMetadata
// instance
}
/**
* Returns <code>findAll</code> method for render-a-view visualization mode. <br>
* This method handles datatables AJAX request for data which are no related
* to a Roo Dynamic finder.
*
* @return
*/
private MethodMetadata getFindAllMethodRenderMode() {
// Define method parameter types
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
parameterTypes.add(new AnnotatedJavaType(DATATABLES_CRITERIA_TYPE,
new AnnotationMetadataBuilder(DATATABLES_PARAMS).build()));
parameterTypes.add(new AnnotatedJavaType(entity,
new AnnotationMetadataBuilder(MODEL_ATTRIBUTE).build()));
parameterTypes.add(AnnotatedJavaType
.convertFromJavaType(HTTP_SERVLET_REQUEST));
parameterTypes.add(AnnotatedJavaType
.convertFromJavaType(HTTP_SERVLET_RESPONSE));
// Check if a method with the same signature already exists in the
// target type
final MethodMetadata method = methodExists(findAllMethodName,
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>();
AnnotationMetadataBuilder methodAnnotation = new AnnotationMetadataBuilder();
methodAnnotation.setAnnotationType(REQUEST_MAPPING);
methodAnnotation.addStringAttribute(HEADERS, ACCEPT_APPLICATION_JSON);
methodAnnotation.addStringAttribute(
DatatablesConstants.RQST_MAP_ANN_VAL_NAME, "/datatables/ajax");
methodAnnotation.addStringAttribute(
DatatablesConstants.RQST_MAP_ANN_PROD_NAME, APPLICATION_JSON);
annotations.add(methodAnnotation);
annotations.add(new AnnotationMetadataBuilder(RESPONSE_BODY));
// Define method throws types (none in this case)
List<JavaType> throwsTypes = new ArrayList<JavaType>();
throwsTypes.add(SERVLET_EXCEPTION);
throwsTypes.add(IO_EXCEPTION);
// Define method parameter names
List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(CRITERIA_PARAM_NAME);
parameterNames.add(new JavaSymbolName(StringUtils
.uncapitalize(entityName)));
parameterNames.add(REQUEST_PARAM_NAME);
parameterNames.add(RESPONSE_PARAM_NAME);
// Create the method body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
buildFindAllMethodBodyRenderMode(bodyBuilder);
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
getId(), Modifier.PUBLIC, findAllMethodName, FIND_ALL_RETURN,
parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
methodBuilder.setThrowsTypes(throwsTypes);
return methodBuilder.build(); // Build and return a MethodMetadata
// instance
}
/**
* Build method body for <code>findAll</code> method for render-a-view
* visualization mode
*
* @param bodyBuilder
*/
private void buildFindAllMethodBodyRenderMode(
InvocableMemberBodyBuilder bodyBuilder) {
// Build call to FindByCriteria
buildFindByCriteriaCallMethodBody(bodyBuilder, false);
buildPopulateDataSearchCallRenderModeMethodBody(bodyBuilder);
}
/**
* Build method-code to call Datatables.populateDataSearch method.
*
* @param bodyBuilder
*/
private void buildPopulateDataSearchCallRenderModeMethodBody(
InvocableMemberBodyBuilder bodyBuilder) {
bodyBuilder.appendFormalLine(String.format(
"%s rows = %s(searchResult, %s, %s);",
helper.getFinalTypeName(LIST_MAP_STRING_STRING),
renderItemsMethodName.getSymbolName(),
REQUEST_PARAM_NAME.getSymbolName(),
RESPONSE_PARAM_NAME.getSymbolName()));
/*
* DataSet<Map<String, String>> dataSet = new DataSet<Map<String,
* String>>(rows, totalRecords, recordsFound);
*/
bodyBuilder.appendFormalLine(String.format(
"%s dataSet = new %s(rows, totalRecords, recordsFound); ",
helper.getFinalTypeName(DATA_SET_MAP_STRING_STRING),
helper.getFinalTypeName(DATA_SET_MAP_STRING_STRING)));
// return DatatablesResponse.build(dataSet,criterias);
bodyBuilder.appendFormalLine(String.format(
"return %s.build(dataSet,%s);",
helper.getFinalTypeName(DATATABLES_RESPONSE),
CRITERIA_PARAM_NAME.getSymbolName()));
}
/**
* Build method-code to call Datatables.findByCriteria method. <br>
* Generated code will depend on entity has JPAQuery metadata and if there
* is a base search.
*
* @param bodyBuilder
* @param baseSearch
* @return
*/
private String buildFindByCriteriaCallMethodBody(
InvocableMemberBodyBuilder bodyBuilder, boolean baseSearch) {
final String entityTypeName = helper.getFinalTypeName(entity);
JavaType searchResult = new JavaType(
SEARCH_RESULTS.getFullyQualifiedTypeName(), 0, DataType.TYPE,
null, Arrays.asList(entity));
if (jpaQueryMetadata != null) {
String filterByInfo = String.format("%s.%s()", entityTypeName,
jpaQueryMetadata.getFilterByMethodName().getSymbolName());
String orderByInfo = String.format("%s.%s()", entityTypeName,
jpaQueryMetadata.getOrderByMethodName().getSymbolName());
// SearchResults<Pet> searchResult =
// datatablesUtilsBean_dtt.findByCriteria(entity, criterias,
// baseSearch);
if (baseSearch) {
bodyBuilder
.appendFormalLine(String
.format("%s searchResult = %s.findByCriteria(entity, %s, baseSearch);",
helper.getFinalTypeName(searchResult),
getDatatablesUtilsBeanName(),
CRITERIA_PARAM_NAME.getSymbolName()));
}
else {
bodyBuilder.appendFormalLine(PARAMETERS_AS_BASE_SEARCH);
// Map<String, Object> baseSearchValuesMap = getPropertyMap(pet,
// request);
bodyBuilder
.appendFormalLine(String
.format("%s baseSearchValuesMap = getPropertyMap(%s, request);",
helper.getFinalTypeName(MAP_STRING_OBJECT),
new JavaSymbolName(StringUtils
.uncapitalize(entityName))));
// setVisitFilters(baseSearchValuesMap);
bodyBuilder
.appendFormalLine("setDatatablesBaseFilter(baseSearchValuesMap);");
// SearchResults<Pet> searchResult =
// datatablesUtilsBean_dtt.findByCriteria(Pet.class,
// Pet.getFilterByAssociations(),
// Pet.getOrderByAssociations(), criteria, baseSearchValuesMap);
bodyBuilder
.appendFormalLine(String
.format("%s searchResult = %s.findByCriteria(%s.class, %s, %s, %s, baseSearchValuesMap);",
helper.getFinalTypeName(searchResult),
getDatatablesUtilsBeanName(),
entityTypeName, filterByInfo,
orderByInfo,
CRITERIA_PARAM_NAME.getSymbolName()));
}
}
else {
// SearchResults<Pet> searchResult =
// datatablesUtilsBean_dtt.findByCriteria(entity, criterias,
// baseSearch);
if (baseSearch) {
bodyBuilder
.appendFormalLine(String
.format("%s searchResult = %s.findByCriteria(entity, %s, baseSearch);",
helper.getFinalTypeName(searchResult),
getDatatablesUtilsBeanName(),
CRITERIA_PARAM_NAME.getSymbolName()));
}
else {
bodyBuilder.appendFormalLine(PARAMETERS_AS_BASE_SEARCH);
// Map<String, Object> baseSearchValuesMap = getPropertyMap(pet,
// request);
bodyBuilder
.appendFormalLine(String
.format("%s baseSearchValuesMap = getPropertyMap(%s, request);",
helper.getFinalTypeName(MAP_STRING_OBJECT),
StringUtils.uncapitalize(entityName)));
// setVisitFilters(baseSearchValuesMap);
bodyBuilder
.appendFormalLine("setDatatablesBaseFilter(baseSearchValuesMap);");
// SearchResults<Pet> searchResult =
// datatablesUtilsBean_dtt.findByCriteria(Pet.class,
// criterias, baseSearch);
bodyBuilder
.appendFormalLine(String
.format("%s searchResult = %s.findByCriteria(%s.class, %s, baseSearchValuesMap);",
helper.getFinalTypeName(searchResult),
getDatatablesUtilsBeanName(),
entityTypeName,
CRITERIA_PARAM_NAME.getSymbolName()));
}
}
bodyBuilder.appendFormalLine("");
bodyBuilder.appendFormalLine("// Get datatables required counts");
// long totalRecords = searchResult.getTotalCount();
bodyBuilder
.appendFormalLine("long totalRecords = searchResult.getTotalCount();");
// long recordsFound = findResult.getResultsCount();
bodyBuilder
.appendFormalLine("long recordsFound = searchResult.getResultsCount();");
return entityTypeName;
}
private String getDatatablesUtilsBeanName() {
return getDatatablesUtilsBean().getFieldName().getSymbolName();
}
/**
* Build method body for <code>findAll</code> method
*
* @param bodyBuilder
*/
private void buildFindAllDataMethodBody(
InvocableMemberBodyBuilder bodyBuilder) {
// Build call to FindByCriteria
buildFindByCriteriaCallMethodBody(bodyBuilder, false);
buildPopulateDataSearchCallMethodBody(bodyBuilder);
}
/**
* Build method-code to perform a call to Datatables.populateDateSet method
*
* @param bodyBuilder
*/
private void buildPopulateDataSearchCallMethodBody(
InvocableMemberBodyBuilder bodyBuilder) {
bodyBuilder.appendFormalLine("");
bodyBuilder.appendFormalLine("// Entity pk field name");
// String pkFieldName = "id";
bodyBuilder.appendFormalLine(String.format(
"String pkFieldName = \"%s\";", entityIdentifier.getFieldName()
.getSymbolName()));
String dateFormatVarName = getCodeToAddDateTimeFormatPatterns(bodyBuilder);
bodyBuilder.appendFormalLine("");
/*
* DataSet<Map<String, String>> dataSet =
* datatablesUtilsBean_dtt.populateDataSet(searchResult.getResult(),
* pkFieldName, totalRecords, recordsFound, criterias.getColumnDefs(),
* datePattern);
*/
bodyBuilder
.appendFormalLine(String
.format("%s dataSet = %s.populateDataSet(searchResult.getResults(), pkFieldName, totalRecords, recordsFound, criterias.getColumnDefs(), %s); ",
helper.getFinalTypeName(DATA_SET_MAP_STRING_STRING),
getDatatablesUtilsBeanName(), dateFormatVarName));
// return DatatablesResponse.build(dataSet,criterias);
bodyBuilder.appendFormalLine(String.format(
"return %s.build(dataSet,%s);",
helper.getFinalTypeName(DATATABLES_RESPONSE),
CRITERIA_PARAM_NAME.getSymbolName()));
}
/**
* Create metadata for auto-wired convertionService field.
*
* @return a FieldMetadata object
*/
public FieldMetadata getConversionServiceField() {
if (conversionService == null) {
JavaSymbolName curName = new JavaSymbolName("conversionService_dtt");
// Check if field exist
FieldMetadata currentField = governorTypeDetails
.getDeclaredField(curName);
if (currentField != null && !isConversionServiceField(currentField)) {
// No compatible field: look for new name
currentField = null;
JavaSymbolName newName = new JavaSymbolName(
"conversionService_dt");
currentField = governorTypeDetails.getDeclaredField(newName);
while (currentField != null
&& !isConversionServiceField(currentField)) {
newName = new JavaSymbolName(newName.getSymbolName()
.concat("_"));
currentField = governorTypeDetails
.getDeclaredField(newName);
}
curName = newName;
}
if (currentField != null) {
conversionService = currentField;
}
else {
// create field
List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>(
1);
annotations.add(new AnnotationMetadataBuilder(AUTOWIRED));
// Using the FieldMetadataBuilder to create the field
// definition.
final FieldMetadataBuilder fieldBuilder = new FieldMetadataBuilder(
getId(), Modifier.PUBLIC, annotations, curName, // Field
CONVERSION_SERVICE); // Field type
conversionService = fieldBuilder.build(); // Build and return a
// FieldMetadata
// instance
}
}
return conversionService;
}
private FieldMetadata getEntityManagerProvider() {
if (entityManagerProvider == null) {
JavaSymbolName curName = DATATABLES_MANAGER_PROVIDER_NAME;
// Check if field exist
FieldMetadata currentField = governorTypeDetails
.getDeclaredField(curName);
if (currentField != null
&& !isEntityManagerProviderField(currentField)) {
// No compatible field: look for new name
currentField = null;
JavaSymbolName newName = new JavaSymbolName("entityManagerProv");
currentField = governorTypeDetails.getDeclaredField(newName);
while (currentField != null
&& !isConversionServiceField(currentField)) {
newName = new JavaSymbolName(newName.getSymbolName()
.concat("_"));
currentField = governorTypeDetails
.getDeclaredField(newName);
}
curName = newName;
}
if (currentField != null) {
entityManagerProvider = currentField;
}
else {
// create field
JavaType backingType = new JavaType(DATATABLES_MANAGER_PROVIDER);
// AutoWired
List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
annotations.add(new AnnotationMetadataBuilder(AUTOWIRED));
// Using the FieldMetadataBuilder to create the field
// definition.
final FieldMetadataBuilder fieldBuilder = new FieldMetadataBuilder(
getId(), Modifier.PRIVATE, annotations, curName,
backingType);
entityManagerProvider = fieldBuilder.build();
}
}
return entityManagerProvider;
}
/**
* Create metadata for auto-wired messageSource field.
*
* @return a FieldMetadata object
*/
public FieldMetadata getMessageSourceField() {
if (messageSource == null) {
JavaSymbolName curName = new JavaSymbolName("messageSource_dtt");
// Check if field exist
FieldMetadata currentField = governorTypeDetails
.getDeclaredField(curName);
if (currentField != null && !isMessageSourceField(currentField)) {
// No compatible field: look for new name
currentField = null;
JavaSymbolName newName = new JavaSymbolName("messageSource_dt");
currentField = governorTypeDetails.getDeclaredField(newName);
while (currentField != null
&& !isConversionServiceField(currentField)) {
newName = new JavaSymbolName(newName.getSymbolName()
.concat("_"));
currentField = governorTypeDetails
.getDeclaredField(newName);
}
curName = newName;
}
if (currentField != null) {
messageSource = currentField;
}
else {
// create field
List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>(
1);
annotations.add(new AnnotationMetadataBuilder(AUTOWIRED));
// Using the FieldMetadataBuilder to create the field
// definition.
final FieldMetadataBuilder fieldBuilder = new FieldMetadataBuilder(
getId(), Modifier.PUBLIC, annotations, curName, // Field
MESSAGE_SOURCE); // Field type
messageSource = fieldBuilder.build(); // Build and return a
// FieldMetadata
// instance
}
}
return messageSource;
}
/**
* Create metadata for DatatablesUtilsBean field.
*
* @return a FieldMetadata object
*/
public FieldMetadata getDatatablesUtilsBean() {
if (datatablesUtilsBean == null) {
JavaSymbolName curName = new JavaSymbolName(
"datatablesUtilsBean_dtt");
// Check if field exist
FieldMetadata currentField = governorTypeDetails
.getDeclaredField(curName);
if (currentField != null && !isDatatablesUtilsBean(currentField)) {
// No compatible field: look for new name
currentField = null;
JavaSymbolName newName = new JavaSymbolName(
"datatablesUtilsBean_dt");
currentField = governorTypeDetails.getDeclaredField(newName);
while (currentField != null
&& !isDatatablesUtilsBean(currentField)) {
newName = new JavaSymbolName(newName.getSymbolName()
.concat("_"));
currentField = governorTypeDetails
.getDeclaredField(newName);
}
curName = newName;
}
if (currentField != null) {
datatablesUtilsBean = currentField;
}
else {
// create field
List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>(
1);
annotations.add(new AnnotationMetadataBuilder(AUTOWIRED));
// Using the FieldMetadataBuilder to create the field
// definition.
final FieldMetadataBuilder fieldBuilder = new FieldMetadataBuilder(
getId(), Modifier.PUBLIC, annotations, curName, // Field
DATATABLES_UTILS_BEAN); // Field type
datatablesUtilsBean = fieldBuilder.build(); // Build and
// return a
// FieldMetadata
// instance
}
}
return datatablesUtilsBean;
}
/**
* Create metadata for QuerydslUtilsBean field
*
* @return FieldMetadata
*/
public FieldMetadata getQuerydslUtilsBean() {
if (querydslUtilsBean == null) {
JavaSymbolName curName = new JavaSymbolName("querydslUtilsBean_dtt");
// Check if field exist
FieldMetadata currentField = governorTypeDetails
.getDeclaredField(curName);
if (currentField != null && !isQuerydslUtilsBean(currentField)) {
// No compatible field: look for new name
currentField = null;
JavaSymbolName newName = new JavaSymbolName(
"querydslUtilsBean_dt");
currentField = governorTypeDetails.getDeclaredField(newName);
while (currentField != null
&& !isQuerydslUtilsBean(currentField)) {
newName = new JavaSymbolName(newName.getSymbolName()
.concat("_"));
currentField = governorTypeDetails
.getDeclaredField(newName);
}
curName = newName;
}
if (currentField != null) {
querydslUtilsBean = currentField;
}
else {
// create field
List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>(
1);
annotations.add(new AnnotationMetadataBuilder(AUTOWIRED));
// Using the FieldMetadataBuilder to create the field
// definition.
final FieldMetadataBuilder fieldBuilder = new FieldMetadataBuilder(
getId(), Modifier.PUBLIC, annotations, curName, // Field
QUERYDSL_UTILS_BEAN); // Field type
querydslUtilsBean = fieldBuilder.build(); // Build and return
// a
// FieldMetadata
// instance
}
}
return querydslUtilsBean;
}
/**
* Create metadata for beanWrapper field.
*
* @return a FieldMetadata object
*/
public FieldMetadata getBeanWrapperField() {
if (beanWrapper == null) {
JavaSymbolName curName = new JavaSymbolName("beanWrapper_dtt");
// Check if field exist
FieldMetadata currentField = governorTypeDetails
.getDeclaredField(curName);
if (currentField != null && !isBeanWrapperField(currentField)) {
// No compatible field: look for new name
currentField = null;
JavaSymbolName newName = new JavaSymbolName("beanWrapper_dt");
currentField = governorTypeDetails.getDeclaredField(newName);
while (currentField != null
&& !isConversionServiceField(currentField)) {
newName = new JavaSymbolName(newName.getSymbolName()
.concat("_"));
currentField = governorTypeDetails
.getDeclaredField(newName);
}
curName = newName;
}
if (currentField != null) {
beanWrapper = currentField;
}
else {
// create field
List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>(
1);
// Using the FieldMetadataBuilder to create the field
// definition.
final FieldMetadataBuilder fieldBuilder = new FieldMetadataBuilder(
getId(), Modifier.PUBLIC, annotations, curName, // Field
BEAN_WRAPPER); // Field type
beanWrapper = fieldBuilder.build(); // Build and return a
// FieldMetadata
// instance
}
}
return beanWrapper;
}
private boolean isConversionServiceField(FieldMetadata field) {
return field != null && field.getAnnotation(AUTOWIRED) != null
&& field.getFieldType().equals(CONVERSION_SERVICE);
}
private boolean isEntityManagerProviderField(FieldMetadata field) {
return field != null
&& field.getAnnotation(AUTOWIRED) != null
&& field.getFieldName()
.equals(DATATABLES_MANAGER_PROVIDER_NAME);
}
private boolean isMessageSourceField(FieldMetadata field) {
return field != null && field.getAnnotation(AUTOWIRED) != null
&& field.getFieldType().equals(MESSAGE_SOURCE);
}
private boolean isDatatablesUtilsBean(FieldMetadata field) {
return field != null && field.getAnnotation(AUTOWIRED) != null
&& field.getFieldType().equals(DATATABLES_UTILS_BEAN);
}
private boolean isQuerydslUtilsBean(FieldMetadata field) {
return field != null && field.getAnnotation(AUTOWIRED) != null
&& field.getFieldType().equals(QUERYDSL_UTILS_BEAN);
}
private boolean isBeanWrapperField(FieldMetadata field) {
return field != null && field.getFieldType().equals(BEAN_WRAPPER);
}
/**
* Add the methods needed to support export via AJAX.
*/
private void addAjaxExportMethods() {
builder.addMethod(getExportCsvMethod());
builder.addMethod(getExportPdfMethod());
builder.addMethod(getExportXlsMethod());
builder.addMethod(getExportXlsxMethod());
builder.addMethod(getExportXmlMethod());
builder.addMethod(getExportMethod());
builder.addMethod(getRetrieveDataMethod());
}
/**
* Returns <code>exportCsv</code> method for render-a-view visualization
* mode.
* <p />
* This method handles datatables AJAX request for export data to a CSV
* file.
*
* @return
*/
private MethodMetadata getExportCsvMethod() {
String exportType = "csv";
JavaType exportTypeJavaType = DATATABLES_CSV_EXPORT;
return getExportFormatMethod(exportType, exportTypeJavaType);
}
/**
* Returns <code>exportPdf</code> method for render-a-view visualization
* mode.
* <p />
* This method handles datatables AJAX request for export data to a PDF
* file.
*
* @return
*/
private MethodMetadata getExportPdfMethod() {
String exportType = "pdf";
JavaType exportTypeJavaType = DATATABLES_PDF_EXPORT;
return getExportFormatMethod(exportType, exportTypeJavaType);
}
/**
* Returns <code>exportXls</code> method for render-a-view visualization
* mode.
* <p />
* This method handles datatables AJAX request for export data to a XLS
* file.
*
* @return
*/
private MethodMetadata getExportXlsMethod() {
String exportType = "xls";
JavaType exportTypeJavaType = DATATABLES_XLS_EXPORT;
return getExportFormatMethod(exportType, exportTypeJavaType);
}
/**
* Returns <code>exportXlsx</code> method for render-a-view visualization
* mode.
* <p />
* This method handles datatables AJAX request for export data to a XLSX
* file.
*
* @return
*/
private MethodMetadata getExportXlsxMethod() {
String exportType = "xlsx";
JavaType exportTypeJavaType = DATATABLES_XLSX_EXPORT;
return getExportFormatMethod(exportType, exportTypeJavaType);
}
/**
* Returns <code>exportXml</code> method for render-a-view visualization
* mode.
* <p />
* This method handles datatables AJAX request for export data to a XML
* file.
*
* @return
*/
private MethodMetadata getExportXmlMethod() {
String exportType = "xml";
JavaType exportTypeJavaType = DATATABLES_XML_EXPORT;
return getExportFormatMethod(exportType, exportTypeJavaType);
}
/**
* Returns export method for a specific format for a render-a-view
* visualization mode.
* <p />
* This method handles datatables AJAX request for export data to a format
* specified in the @{code exportType} parameter.
*
* @param exportType the export type: csv, xml, pdf, etc.
* @param exportTypeJavaType the @{code JavaType} of the export type.
* @return
*/
private MethodMetadata getExportFormatMethod(String exportType,
JavaType exportTypeJavaType) {
String exportTypeUpperCase = StringUtils.upperCase(exportType);
String exportTypeCapitalized = StringUtils.capitalize(exportType);
/*
* @RequestMapping(value = "/exportcsv", produces = "text/csv") public
* void PetController.exportCsv(
*
* @DatatablesParams DatatablesCriterias criterias,
*
* @ModelAttribute Pet pet, HttpServletRequest request,
* HttpServletResponse response) throws ServletException, IOException,
* ExportException { ... }
*/
// Define method parameter types
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
parameterTypes.add(new AnnotatedJavaType(DATATABLES_CRITERIA_TYPE,
new AnnotationMetadataBuilder(DATATABLES_PARAMS).build()));
parameterTypes.add(new AnnotatedJavaType(entity,
new AnnotationMetadataBuilder(MODEL_ATTRIBUTE).build()));
parameterTypes.add(AnnotatedJavaType
.convertFromJavaType(HTTP_SERVLET_REQUEST));
parameterTypes.add(AnnotatedJavaType
.convertFromJavaType(HTTP_SERVLET_RESPONSE));
// Building method name
JavaSymbolName methodName = new JavaSymbolName(
"export".concat(exportTypeCapitalized));
// Check if a method with the same signature already exists in the
// target type
final MethodMetadata method = methodExists(methodName, 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>();
AnnotationMetadataBuilder methodAnnotation = new AnnotationMetadataBuilder();
methodAnnotation.setAnnotationType(REQUEST_MAPPING);
methodAnnotation.addStringAttribute(
DatatablesConstants.RQST_MAP_ANN_VAL_NAME,
"/export".concat(exportType));
methodAnnotation.addStringAttribute(
DatatablesConstants.RQST_MAP_ANN_PROD_NAME,
"text/".concat(exportType));
annotations.add(methodAnnotation);
// Define method throws types (none in this case)
List<JavaType> throwsTypes = new ArrayList<JavaType>();
throwsTypes.add(SERVLET_EXCEPTION);
throwsTypes.add(IO_EXCEPTION);
throwsTypes.add(DATATABLES_EXPORT_EXCEPTION);
// Define method parameter names
List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(CRITERIA_PARAM_NAME);
parameterNames.add(new JavaSymbolName(StringUtils
.uncapitalize(entityName)));
parameterNames.add(REQUEST_PARAM_NAME);
parameterNames.add(RESPONSE_PARAM_NAME);
// Create the method body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
/*
* export(criterias, pet, ExportType.CSV, new CsvExport(), request,
* response);
*/
String format = "export(%s, %s, %s.".concat(exportTypeUpperCase)
.concat(", new %s(), %s, %s);");
bodyBuilder.appendFormalLine(String.format(format,
CRITERIA_PARAM_NAME.getSymbolName(),
StringUtils.uncapitalize(entityName),
helper.getFinalTypeName(DATATABLES_EXPORT_TYPE),
helper.getFinalTypeName(exportTypeJavaType),
REQUEST_PARAM_NAME.getSymbolName(),
RESPONSE_PARAM_NAME.getSymbolName()));
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
getId(), Modifier.PUBLIC, methodName, JavaType.VOID_PRIMITIVE,
parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
methodBuilder.setThrowsTypes(throwsTypes);
return methodBuilder.build(); // Build and return a MethodMetadata
// instance
}
/**
* Returns <code>export</code> method for a render-a-view visualization
* mode.
* <p />
* This is a private method that handles datatables AJAX request for a
* specific format.
*
* @return
*/
private MethodMetadata getExportMethod() {
/*
* private void export(DatatablesCriterias criterias, Pet pet,
* ExportType exportType, DatatablesExport datatablesExport,
* HttpServletRequest request, HttpServletResponse response) throws
* ExportException { ... }
*/
// Define method parameter types
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
parameterTypes.add(AnnotatedJavaType
.convertFromJavaType(DATATABLES_CRITERIA_TYPE));
parameterTypes.add(AnnotatedJavaType.convertFromJavaType(entity));
parameterTypes.add(AnnotatedJavaType
.convertFromJavaType(DATATABLES_EXPORT_TYPE));
parameterTypes.add(AnnotatedJavaType
.convertFromJavaType(DATATABLES_EXPORT));
parameterTypes.add(AnnotatedJavaType
.convertFromJavaType(HTTP_SERVLET_REQUEST));
parameterTypes.add(AnnotatedJavaType
.convertFromJavaType(HTTP_SERVLET_RESPONSE));
// Check if a method with the same signature already exists in the
// target type
final MethodMetadata method = methodExists(EXPORT_METHOD_NAME,
parameterTypes);
if (method != null) {
// If it already exists, just return the method and omit its
// generation via the ITD
return method;
}
// Define method throws types (none in this case)
List<JavaType> throwsTypes = new ArrayList<JavaType>();
throwsTypes.add(DATATABLES_EXPORT_EXCEPTION);
// Define method parameter names
List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(CRITERIA_PARAM_NAME);
parameterNames.add(new JavaSymbolName(StringUtils
.uncapitalize(entityName)));
parameterNames.add(DATATABLES_EXPORT_TYPE_NAME);
parameterNames.add(DATATABLES_EXPORT_NAME);
parameterNames.add(REQUEST_PARAM_NAME);
parameterNames.add(RESPONSE_PARAM_NAME);
// Create the method body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
/*
* // Does the export process as is explained in
* http://dandelion.github.
* io/datatables/tutorials/export/controller-based-exports.html // 1.
* Retrieve the data List<Map<String, String>> data =
* retrieveData(criterias, pet, request);
*/
bodyBuilder
.appendFormalLine("// Does the export process as is explained in http://dandelion.github.io/datatables/tutorials/export/controller-based-exports.html");
bodyBuilder.appendFormalLine("// 1. Retrieve the data");
String format = "%s data = retrieveData(%s, %s, %s);";
bodyBuilder.appendFormalLine(String.format(format, helper
.getFinalTypeName(LIST_MAP_STRING_STRING), CRITERIA_PARAM_NAME
.getSymbolName(),
new JavaSymbolName(StringUtils.uncapitalize(entityName)),
REQUEST_PARAM_NAME.getSymbolName()));
/*
* // 2. Build an instance of "ExportConf". ExportConf exportConf = new
* ExportConf.Builder(exportType).header(true)
* .exportClass(datatablesExport).autoSize(true)
* .fileName(pet.getClass().getSimpleName()).build();
*/
bodyBuilder
.appendFormalLine("// 2. Build an instance of \"ExportConf\"");
format = "%s exportConf = new %s.Builder(%s).header(true).exportClass(%s).autoSize(true).fileName(%s.getClass().getSimpleName()).build();";
bodyBuilder.appendFormalLine(String.format(format,
helper.getFinalTypeName(DATATABLES_EXPORT_CONF),
helper.getFinalTypeName(DATATABLES_EXPORT_CONF),
DATATABLES_EXPORT_TYPE_NAME.getSymbolName(),
DATATABLES_EXPORT_NAME.getSymbolName(),
StringUtils.uncapitalize(entityName)));
/*
* // 3. Build an instance of "HtmlTable" HtmlTable table =
* datatablesUtilsBean_dtt.makeHtmlTable(data, criterias, exportConf, request);
*/
bodyBuilder
.appendFormalLine("// 3. Build an instance of \"HtmlTable\"");
format = "%s table = %s.makeHtmlTable(data, %s, exportConf, %s);";
bodyBuilder.appendFormalLine(String.format(format,
helper.getFinalTypeName(DATATABLES_HTML_TABLE),
getDatatablesUtilsBeanName(),
CRITERIA_PARAM_NAME.getSymbolName(),
REQUEST_PARAM_NAME.getSymbolName()));
/*
* // 4. Render the generated export file
* ExportUtils.renderExport(table, exportConf, response);
*/
bodyBuilder.appendFormalLine("// 4. Render the generated export file");
format = "%s.renderExport(table, exportConf, %s);";
bodyBuilder.appendFormalLine(String.format(format,
helper.getFinalTypeName(DATATABLES_EXPORT_UTILS),
RESPONSE_PARAM_NAME.getSymbolName()));
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
getId(), Modifier.PUBLIC, EXPORT_METHOD_NAME,
JavaType.VOID_PRIMITIVE, parameterTypes, parameterNames,
bodyBuilder);
methodBuilder.setThrowsTypes(throwsTypes);
return methodBuilder.build(); // Build and return a MethodMetadata
// instance
}
/**
* Returns <code>retrieveData</code> method for a render-a-view
* visualization mode.
*
* @return
*/
private MethodMetadata getRetrieveDataMethod() {
/*
* private List<Map<String, String>> retrieveData( DatatablesCriterias
* criterias, Pet pet, HttpServletRequest request) { ... }
*/
// Define method parameter types
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
parameterTypes.add(AnnotatedJavaType
.convertFromJavaType(DATATABLES_CRITERIA_TYPE));
parameterTypes.add(AnnotatedJavaType.convertFromJavaType(entity));
parameterTypes.add(AnnotatedJavaType
.convertFromJavaType(HTTP_SERVLET_REQUEST));
// Check if a method with the same signature already exists in the
// target type
final MethodMetadata method = methodExists(RETRIEVE_DATA_METHOD_NAME,
parameterTypes);
if (method != null) {
// If it already exists, just return the method and omit its
// generation via the ITD
return method;
}
// Define method parameter names
List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(CRITERIA_PARAM_NAME);
parameterNames.add(new JavaSymbolName(entityName));
parameterNames.add(REQUEST_PARAM_NAME);
// Create the method body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
/*
* // Cloned criteria in order to not paginate the results
* DatatablesCriterias noPaginationCriteria = new DatatablesCriterias(
* criterias.getSearch(), 0, null, criterias.getColumnDefs(),
* criterias.getSortingColumnDefs(), criterias.getInternalCounter());
*/
bodyBuilder
.appendFormalLine("// Cloned criteria in order to not paginate the results");
String format = "%s noPaginationCriteria = new %s(%s.getSearch(), 0, null, %s.getColumnDefs(), %s.getSortingColumnDefs(), %s.getInternalCounter());";
String datatablesCriteriaType = helper
.getFinalTypeName(DATATABLES_CRITERIA_TYPE);
String criteriaParamName = CRITERIA_PARAM_NAME.getSymbolName();
bodyBuilder.appendFormalLine(String.format(format,
datatablesCriteriaType, datatablesCriteriaType,
criteriaParamName, criteriaParamName, criteriaParamName,
criteriaParamName));
/*
* // Do the search to obtain the data Map<String, Object>
* baseSearchValuesMap = getPropertyMap(XXX, request);
* setDatatablesBaseFilter(baseSearchValuesMap);
*/
bodyBuilder.appendFormalLine("// Do the search to obtain the data");
bodyBuilder
.appendFormalLine(String
.format("Map<String, Object> baseSearchValuesMap = getPropertyMap(%s, %s);",
new JavaSymbolName(entityName),
REQUEST_PARAM_NAME));
bodyBuilder
.appendFormalLine("setDatatablesBaseFilter(baseSearchValuesMap);");
/*
* SearchResults<Visit> searchResult = datatablesUtilsBean_dtt.findByCriteria(
* Visit.class, noPaginationCriteria,
* baseSearchValuesMap); org.springframework.ui.Model uiModel = new
* org.springframework.ui.ExtendedModelMap();
*/
format = "%s searchResult = %s.findByCriteria(%s.class, noPaginationCriteria, baseSearchValuesMap);";
String entityTypeName = helper.getFinalTypeName(entity);
bodyBuilder.appendFormalLine(String.format(format, new JavaType(
SEARCH_RESULTS.getFullyQualifiedTypeName(), 0, DataType.TYPE,
null, Arrays.asList(entity)), getDatatablesUtilsBeanName(),
entityTypeName, DATATABLES_MANAGER_PROVIDER_NAME,
entityTypeName));
String dateFormatVarName = getCodeToAddDateTimeFormatPatterns(bodyBuilder);
/*
* // Use ConversionService with the obtained data return
* datatablesUtilsBean_dtt.populateDataSet(searchResult.getResults(), "id",
* searchResult.getTotalCount(), searchResult.getResultsCount(),
* criterias.getColumnDefs(), null) .getRows();
*/
bodyBuilder
.appendFormalLine("// Use ConversionService with the obtained data");
format = "return %s.populateDataSet(searchResult.getResults(), \"id\", searchResult.getTotalCount(), searchResult.getResultsCount(), %s.getColumnDefs(), %s).getRows();";
bodyBuilder.appendFormalLine(String.format(format,
getDatatablesUtilsBeanName(),
CRITERIA_PARAM_NAME.getSymbolName(), dateFormatVarName));
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
getId(), Modifier.PRIVATE, RETRIEVE_DATA_METHOD_NAME,
LIST_MAP_STRING_STRING, parameterTypes, parameterNames,
bodyBuilder);
return methodBuilder.build(); // Build and return a MethodMetadata
// instance
}
/**
* Add the Java code to call tje dateformat method named
* "addDateTimeFormatPatterns(uiModel)".
*
* @param bodyBuilder the InvocableMemberBodyBuilder
* @return the name of the date format variable.
*/
private String getCodeToAddDateTimeFormatPatterns(
InvocableMemberBodyBuilder bodyBuilder) {
// Call to dateformat method named "addDateTimeFormatPatterns(uiModel)"
String dateFormatVarName = "null";
if (entityDatePatterns != null && !entityDatePatterns.isEmpty()) {
// Model uiModel = new ExtendedModelMap();
bodyBuilder.appendFormalLine(String.format(
"%s uiModel = new %s();", MODEL, EXTENDED_MODEL_MAP));
// addDateTimeFormatPatterns(uiModel);
bodyBuilder.appendFormalLine("addDateTimeFormatPatterns(uiModel);");
// Map<String, Object> datePattern = uiModel.asMap();
bodyBuilder.appendFormalLine(String.format(
"%s datePattern = uiModel.asMap();",
helper.getFinalTypeName(MAP_STRING_OBJECT)));
dateFormatVarName = "datePattern";
}
return dateFormatVarName;
}
/**
* Informs if a method is already defined on class
*
* @param methodName
* @param paramTypes
* @return
*/
private MethodMetadata methodExists(JavaSymbolName methodName,
List<AnnotatedJavaType> paramTypes) {
return MemberFindingUtils.getDeclaredMethod(governorTypeDetails,
methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(paramTypes));
}
// Typically, no changes are required beyond this point
public final 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("ajax", String.valueOf(annotationValues.isAjax()));
builder.append("itdTypeDetails", itdTypeDetails);
return builder.toString();
}
/**
* @return related JPA entity
*/
public final JavaType getEntity() {
return entity;
}
/**
* @return {@link GvNIXDatatables} annotation values
*/
public final DatatablesAnnotationValues getAnnotationValues() {
return annotationValues;
}
/**
* @return {@link RooWebScaffold} annotation values
*/
public final WebScaffoldAnnotationValues getWebScaffoldAnnotationValues() {
return webScaffoldAnnotationValues;
}
/**
* @return controllers use AJAX data mode or not (DOM)
*/
public final boolean isAjax() {
return annotationValues.isAjax();
}
/**
* @return controller entity properties for detail datatables
*/
public final String[] getDetailFields() {
return annotationValues.getDetailFields();
}
/**
* @return informs if controllers has JPA-Batch-operations support available
*/
public final boolean hasJpaBatchSupport() {
return webJpaBatchMetadata != null;
}
/**
* @return datatables shows a standard list or use render-a-view mode
*/
public final boolean isStantardMode() {
return annotationValues.isStandardMode();
}
/**
* @return information about dynamic finder registered on the controller
*/
public final Map<FinderMetadataDetails, QueryHolderTokens> getFindersRegistered() {
return findersRegistered;
}
/**
* @return informs if user can edit data inline (inside the table row)
*/
public final boolean isInlineEditing() {
return annotationValues.isInlineEditing();
}
/**
* @return informs if Spring Security is applied to the project
*/
private boolean isSecurityApplied() {
PathResolver pathResolver = projectOperations.getPathResolver();
String appSecurityXMLPath = pathResolver.getIdentifier(
LogicalPath.getInstance(Path.SPRING_CONFIG_ROOT, ""),
"applicationContext-security.xml");
if (new File(appSecurityXMLPath).exists()) {
return true;
}
return false;
}
}