package org.springframework.roo.addon.web.mvc.thymeleaf.addon;
import static org.springframework.roo.model.SpringJavaType.DELETE_MAPPING;
import static org.springframework.roo.model.SpringJavaType.GET_MAPPING;
import static org.springframework.roo.model.SpringJavaType.INIT_BINDER;
import static org.springframework.roo.model.SpringJavaType.POST_MAPPING;
import static org.springframework.roo.model.SpringJavaType.REQUEST_PARAM;
import static org.springframework.roo.model.SpringJavaType.RESPONSE_ENTITY;
import static org.springframework.roo.model.SpringletsJavaType.SPRINGLETS_DATATABLES;
import static org.springframework.roo.model.SpringletsJavaType.SPRINGLETS_GLOBAL_SEARCH;
import static org.springframework.roo.model.SpringletsJavaType.SPRINGLETS_NOT_FOUND_EXCEPTION;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.tuple.Pair;
import org.jsoup.helper.Validate;
import org.springframework.roo.addon.jpa.addon.entity.JpaEntityMetadata;
import org.springframework.roo.addon.jpa.addon.entity.JpaEntityMetadata.RelationInfo;
import org.springframework.roo.addon.jpa.annotations.entity.JpaRelationType;
import org.springframework.roo.addon.layers.service.addon.ServiceMetadata;
import org.springframework.roo.addon.web.mvc.controller.addon.ControllerMetadata;
import org.springframework.roo.addon.web.mvc.controller.addon.RelationInfoExtended;
import org.springframework.roo.addon.web.mvc.controller.annotations.ControllerType;
import org.springframework.roo.addon.web.mvc.thymeleaf.annotations.RooThymeleaf;
import org.springframework.roo.addon.web.mvc.views.AbstractViewMetadata;
import org.springframework.roo.classpath.PhysicalTypeIdentifier;
import org.springframework.roo.classpath.PhysicalTypeIdentifierNamingUtils;
import org.springframework.roo.classpath.PhysicalTypeMetadata;
import org.springframework.roo.classpath.details.ClassOrInterfaceTypeDetails;
import org.springframework.roo.classpath.details.ConstructorMetadata;
import org.springframework.roo.classpath.details.ConstructorMetadataBuilder;
import org.springframework.roo.classpath.details.FieldMetadata;
import org.springframework.roo.classpath.details.FieldMetadataBuilder;
import org.springframework.roo.classpath.details.MethodMetadata;
import org.springframework.roo.classpath.details.MethodMetadataBuilder;
import org.springframework.roo.classpath.details.annotations.AnnotatedJavaType;
import org.springframework.roo.classpath.details.annotations.AnnotationAttributeValue;
import org.springframework.roo.classpath.details.annotations.AnnotationMetadata;
import org.springframework.roo.classpath.details.annotations.AnnotationMetadataBuilder;
import org.springframework.roo.classpath.details.comments.CommentStructure;
import org.springframework.roo.classpath.details.comments.CommentStructure.CommentLocation;
import org.springframework.roo.classpath.details.comments.JavadocComment;
import org.springframework.roo.classpath.itd.InvocableMemberBodyBuilder;
import org.springframework.roo.metadata.MetadataIdentificationUtils;
import org.springframework.roo.model.JavaSymbolName;
import org.springframework.roo.model.JavaType;
import org.springframework.roo.model.JdkJavaType;
import org.springframework.roo.model.Jsr303JavaType;
import org.springframework.roo.model.SpringEnumDetails;
import org.springframework.roo.model.SpringJavaType;
import org.springframework.roo.model.SpringletsJavaType;
import org.springframework.roo.project.LogicalPath;
/**
* Metadata for {@link RooThymeleaf}.
*
* @author Juan Carlos GarcÃa
* @author Jose Manuel Vivó
* @author Sergio Clares
* @since 2.0
*/
public class ThymeleafMetadata extends AbstractViewMetadata {
// Method names
protected static final JavaSymbolName CREATE_METHOD_NAME = new JavaSymbolName("create");
protected static final JavaSymbolName LIST_METHOD_NAME = new JavaSymbolName("list");
protected static final JavaSymbolName DELETE_METHOD_NAME = new JavaSymbolName("delete");
protected static final JavaSymbolName DELETE_BATCH_METHOD_NAME =
new JavaSymbolName("deleteBatch");
protected static final JavaSymbolName LIST_URI_METHOD_NAME = new JavaSymbolName("listURI");
protected static final JavaSymbolName LIST_DATATABLES_METHOD_NAME = new JavaSymbolName(
"datatables");
protected static final JavaSymbolName LIST_DATATABLES_BY_IDS_IN_METHOD_NAME = new JavaSymbolName(
"datatablesByIdsIn");
protected static final JavaSymbolName LIST_DATATABLES_DETAILS_METHOD_NAME = new JavaSymbolName(
"datatables");
protected static final JavaSymbolName LIST_DATATABLES_BY_IDS_IN_DETAILS_METHOD_NAME =
new JavaSymbolName("datatablesByIdsIn");
protected static final JavaSymbolName SELECT2_METHOD_NAME = new JavaSymbolName("select2");
protected static final JavaSymbolName SHOW_URI_METHOD_NAME = new JavaSymbolName("showURI");
protected static final JavaSymbolName SHOW_METHOD_NAME = new JavaSymbolName("show");
protected static final JavaSymbolName SHOW_INLINE_METHOD_NAME = new JavaSymbolName("showInline");
protected static final JavaSymbolName CREATE_FORM_METHOD_NAME = new JavaSymbolName("createForm");
protected static final JavaSymbolName EDIT_FORM_METHOD_NAME = new JavaSymbolName("editForm");
protected static final JavaSymbolName UPDATE_METHOD_NAME = new JavaSymbolName("update");
protected static final JavaSymbolName EXPORT_METHOD_NAME = new JavaSymbolName("export");
protected static final JavaSymbolName EXPORT_CSV_METHOD_NAME = new JavaSymbolName("exportCsv");
protected static final JavaSymbolName EXPORT_PDF_METHOD_NAME = new JavaSymbolName("exportPdf");
protected static final JavaSymbolName EXPORT_XLS_METHOD_NAME = new JavaSymbolName("exportXls");
protected static final JavaSymbolName ADD_COLUMN_TO_REPORT_BUILDER_METHOD_NAME =
new JavaSymbolName("addColumnToReportBuilder");
protected static final JavaSymbolName FIN_ONE_FOR_UPDATE_METHOD_NAME = new JavaSymbolName(
"findOneForUpdate");
private static final AnnotatedJavaType PAGEABLE_PARAM = new AnnotatedJavaType(
SpringJavaType.PAGEABLE);
private static final JavaSymbolName PAGEABLE_PARAM_NAME = new JavaSymbolName("pageable");
private static final AnnotatedJavaType DATATABLES_PAGEABLE_PARAM = new AnnotatedJavaType(
SpringletsJavaType.SPRINGLETS_DATATABLES_PAGEABLE);
private static final JavaSymbolName DATATABLES_PAGEABLE_PARAM_NAME = new JavaSymbolName(
"pageable");
private static final AnnotatedJavaType GLOBAL_SEARCH_PARAM = new AnnotatedJavaType(
SPRINGLETS_GLOBAL_SEARCH);
private static final JavaSymbolName GLOBAL_SEARCH_PARAM_NAME = new JavaSymbolName("search");
private static final AnnotatedJavaType MODEL_PARAM = new AnnotatedJavaType(SpringJavaType.MODEL);
private static final JavaSymbolName MODEL_PARAM_NAME = new JavaSymbolName("model");
private static final JavaSymbolName FORM_BEAN_PARAM_NAME = new JavaSymbolName("formBean");
private static final AnnotatedJavaType LOCALE_PARAM = new AnnotatedJavaType(JdkJavaType.LOCALE);
private static final JavaSymbolName LOCALE_PARAM_NAME = new JavaSymbolName("locale");
private static final AnnotationMetadataBuilder RESPONSE_BODY_ANNOTATION =
new AnnotationMetadataBuilder(SpringJavaType.RESPONSE_BODY);
private static final JavaType JODA_DATETIME_FORMAT_JAVA_TYPE = new JavaType(
"org.joda.time.format.DateTimeFormat");
private static final JavaSymbolName MESSAGE_SOURCE = new JavaSymbolName("messageSource");
private static final JavaSymbolName CONVERSION_SERVICE_FIELD_NAME = new JavaSymbolName(
"conversionService");
private static final AnnotationMetadata ANN_METADATA_MODEL_ATTRIBUTE = AnnotationMetadataBuilder
.getInstance(SpringJavaType.MODEL_ATTRIBUTE);
private static final AnnotatedJavaType STRING_ARRAY_PARAM = new AnnotatedJavaType(
JavaType.STRING_ARRAY);
private static final AnnotatedJavaType DATATABLES_COLUMNS_PARAM = new AnnotatedJavaType(
SpringletsJavaType.SPRINGLETS_DATATABLES_COLUMNS);
private static final JavaSymbolName DATATABLES_COLUMNS_PARAM_NAME = new JavaSymbolName(
"datatablesColumns");
private static final JavaSymbolName RESPONSE_PARAM_NAME = new JavaSymbolName("response");
private static final AnnotatedJavaType STRING_PARAM = new AnnotatedJavaType(JavaType.STRING);
private static final JavaSymbolName FILE_NAME_PARAM_NAME = new JavaSymbolName("fileName");
private static final JavaSymbolName EXPORTER_PARAM_NAME = new JavaSymbolName("exporter");
private static final JavaSymbolName HTTP_METHOD_PARAM_NAME = new JavaSymbolName("method");
private static final JavaSymbolName VERSION_PARAM_NAME = new JavaSymbolName("version");
private static final AnnotationMetadata ANN_METADATA_VALID = AnnotationMetadataBuilder
.getInstance(Jsr303JavaType.VALID);
// Static Types
private static final JavaType JR_EXCEPTION = new JavaType(
"net.sf.jasperreports.engine.JRException");
private static final JavaType COLUMN_BUILDER_EXCEPTION = new JavaType(
"ar.com.fdvs.dj.domain.builders.ColumnBuilderException");
private static final JavaType IO_EXCEPTION = new JavaType("java.io.IOException");
private static final JavaType CLASS_NOT_FOUND_EXCEPTION = new JavaType(
"java.lang.ClassNotFoundException");
private static final JavaType FAST_REPORT_BUILDER = new JavaType(
"ar.com.fdvs.dj.domain.builders.FastReportBuilder");
private static final JavaType JR_DATA_SOURCE = new JavaType(
"net.sf.jasperreports.engine.JRDataSource");
private static final JavaType JR_BEAN_COLLECTION_DATA_SOURCE = new JavaType(
"net.sf.jasperreports.engine.data.JRBeanCollectionDataSource");
private static final JavaType JASPER_PRINT = new JavaType(
"net.sf.jasperreports.engine.JasperPrint");
private static final JavaType DYNAMIC_JASPER_HELPER = new JavaType(
"ar.com.fdvs.dj.core.DynamicJasperHelper");
private static final JavaType CLASSIC_LAYOUT_MANAGER = new JavaType(
"ar.com.fdvs.dj.core.layout.ClassicLayoutManager");
private static final JavaType STRING_UTILS_APACHE = new JavaType(
"org.apache.commons.lang3.StringUtils");
private static final String PROVIDES_TYPE_STRING = ThymeleafMetadata.class.getName();
private static final String PROVIDES_TYPE = MetadataIdentificationUtils
.create(PROVIDES_TYPE_STRING);
private static final JavaSymbolName DRAW_PARAM_NAME = new JavaSymbolName("draw");
private static final String LINK_BUILDER_ARGUMENT_NAME = "linkBuilder";
private final boolean readOnly;
private final ControllerMetadata controllerMetadata;
private final ControllerType type;
private final ConstructorMetadata constructor;
private final ServiceMetadata serviceMetadata;
private final JavaType entity;
private final String entityPlural;
private final String entityLabel;
private final List<Pair<RelationInfo, JpaEntityMetadata>> compositionRelationOneToOne;
private final String entityItemName;
private final JpaEntityMetadata entityMetadata;
private final JavaType itemController;
private final JavaType detailItemController;
private final JavaType detailCollectionController;
private final String entityIdentifierPlural;
private final String entityIdentifier;
private final Map<String, String> mvcMethodNames;
private final JavaType relatedCollectionController;
private final JavaType relatedItemController;
private final JavaType relatedCollectionLinkFactory;
private final JavaType relatedItemLinkFactory;
// Common method
private final MethodMetadata initBinderMethod;
// Collection Methods
private final MethodMetadata createFormMethod;
private final MethodMetadata createMethod;
private final MethodMetadata listMethod;
private final MethodMetadata listDatatablesMethod;
private final MethodMetadata listDatatablesByIdsInMethod;
private final MethodMetadata select2Method;
private final MethodMetadata deleteBatchMethod;
// Item Methods
private final MethodMetadata modelAttributeMethod;
private final MethodMetadata editFormMethod;
private final MethodMetadata updateMethod;
private final MethodMetadata deleteMethod;
private final MethodMetadata showMethod;
private final MethodMetadata showInlineMethod;
private final MethodMetadata populateFormMethod;
private final MethodMetadata populateFormatsMethod;
// Details Methods
private final Map<RelationInfo, MethodMetadata> modelAttributeDetailsMethod;
private final MethodMetadata listDatatablesDetailsMethod;
private final MethodMetadata listDatatablesByIdsInDetailsMethod;
private final MethodMetadata createFormDetailsMethod;
private final MethodMetadata createDetailsMethod;
private final MethodMetadata removeFromDetailsMethod;
private final MethodMetadata removeFromDetailsBatchMethod;
// Finder Methods
private final Map<String, MethodMetadata> finderFormMethods;
private final Map<String, MethodMetadata> finderListMethods;
private final Map<String, MethodMetadata> finderDatatableMethods;
// Export Methods
private final MethodMetadata exportMethod;
private final MethodMetadata exportCsvMethod;
private final MethodMetadata exportPdfMethod;
private final MethodMetadata exportXlsMethod;
private final MethodMetadata addColumnToReportBuilderMethod;
private final List<MethodMetadata> exportMethods;
// TODO
// private final Map<String, MethodMetadata> finderListMethods;
// ????
private final List<MethodMetadata> allMethods;
private final FieldMetadata messageSourceField;
private final FieldMetadata methodLinkBuilderFactoryField;
private final FieldMetadata conversionServiceField;
private final String viewsPath;
private final JavaType collectionController;
private final List<FieldMetadata> dateTimeFields;
private final List<FieldMetadata> enumFields;
private final Map<JavaType, List<FieldMetadata>> formBeansDateTimeFields;
private final Map<JavaType, List<FieldMetadata>> formBeansEnumFields;
private final MethodMetadata editFormDetailMethod;
private final MethodMetadata updateDetailMethod;
private final MethodMetadata deleteDetailMethod;
private final MethodMetadata showDetailMethod;
private final MethodMetadata showDetailInlineMethod;
private final String ITEM_LINK = "itemLink";
private final String COLLECTION_LINK = "collectionLink";
private final String entityPluralUncapitalized;
private final List<FieldMetadata> entityValidFields;
private final Map<String, JavaType> jasperReportsMap;
public static String createIdentifier(final JavaType javaType, final LogicalPath path) {
return PhysicalTypeIdentifierNamingUtils.createIdentifier(PROVIDES_TYPE_STRING, javaType, path);
}
public static String createIdentifier(ClassOrInterfaceTypeDetails details) {
final LogicalPath logicalPath =
PhysicalTypeIdentifier.getPath(details.getDeclaredByMetadataId());
return createIdentifier(details.getType(), logicalPath);
}
public static JavaType getJavaType(final String metadataIdentificationString) {
return PhysicalTypeIdentifierNamingUtils.getJavaType(PROVIDES_TYPE_STRING,
metadataIdentificationString);
}
public static String getMetadataIdentiferType() {
return PROVIDES_TYPE;
}
public static LogicalPath getPath(final String metadataIdentificationString) {
return PhysicalTypeIdentifierNamingUtils.getPath(PROVIDES_TYPE_STRING,
metadataIdentificationString);
}
public static boolean isValid(final String metadataIdentificationString) {
return PhysicalTypeIdentifierNamingUtils.isValid(PROVIDES_TYPE_STRING,
metadataIdentificationString);
}
/**
* Constructor
*
* @param identifier
* the identifier for this item of metadata (required)
* @param aspectName
* the Java type of the ITD (required)
* @param governorPhysicalTypeMetadata
* the governor, which is expected to contain a
* {@link ClassOrInterfaceTypeDetails} (required)
* @param collectionController
* @param formBeansEnumFields
* @param formBeansDateTimeFields
* @param detailsCollectionController
* @param relatedCollectionController
*
*/
public ThymeleafMetadata(final String identifier, final JavaType aspectName,
final PhysicalTypeMetadata governorPhysicalTypeMetadata,
ControllerMetadata controllerMetadata, ServiceMetadata serviceMetadata,
JpaEntityMetadata entityMetadata, String entityPlural, String entityIdentifierPlural,
final List<Pair<RelationInfo, JpaEntityMetadata>> compositionRelationOneToOne,
final JavaType itemController, final JavaType collectionController,
final List<FieldMetadata> dateTimeFields, final List<FieldMetadata> enumFields,
final Map<String, MethodMetadata> findersToAdd,
final Map<JavaType, List<FieldMetadata>> formBeansDateTimeFields,
final Map<JavaType, List<FieldMetadata>> formBeansEnumFields,
final JavaType detailItemController, JavaType detailsCollectionController,
final JavaType relatedCollectionController, final JavaType relatedItemController,
final List<FieldMetadata> validFields, final Map<String, JavaType> jasperReportsMap,
final JavaType relatedCollectionLinkFactory, final JavaType relatedItemLinkFactory) {
super(identifier, aspectName, governorPhysicalTypeMetadata);
this.jasperReportsMap = jasperReportsMap;
this.entityValidFields = validFields;
this.readOnly = entityMetadata.isReadOnly();
this.controllerMetadata = controllerMetadata;
this.type = this.controllerMetadata.getType();
this.serviceMetadata = serviceMetadata;
this.entity = serviceMetadata.getEntity();
this.entityMetadata = entityMetadata;
this.entityIdentifier =
entityMetadata.getCurrentIndentifierField().getFieldName().getSymbolName();
this.entityIdentifierPlural = entityIdentifierPlural;
this.entityItemName = StringUtils.uncapitalize(entity.getSimpleTypeName());
this.entityLabel = "label_".concat(this.entityItemName.toLowerCase());
this.entityPlural = entityPlural;
this.entityPluralUncapitalized = StringUtils.uncapitalize(entityPlural);
this.compositionRelationOneToOne = compositionRelationOneToOne;
this.itemController = itemController;
this.detailItemController = detailItemController;
this.detailCollectionController = detailsCollectionController;
this.collectionController = collectionController;
this.dateTimeFields = Collections.unmodifiableList(dateTimeFields);
this.enumFields = Collections.unmodifiableList(enumFields);
this.formBeansDateTimeFields = formBeansDateTimeFields;
this.formBeansEnumFields = formBeansEnumFields;
this.relatedCollectionController = relatedCollectionController;
this.relatedItemController = relatedItemController;
this.viewsPath =
controllerMetadata.getPath().startsWith("/") ? controllerMetadata.getPath().substring(1)
: controllerMetadata.getPath();
this.mvcMethodNames = new HashMap<String, String>();
this.relatedCollectionLinkFactory = relatedCollectionLinkFactory;
this.relatedItemLinkFactory = relatedItemLinkFactory;
// Add @Controller
ensureGovernorIsAnnotated(new AnnotationMetadataBuilder(SpringJavaType.CONTROLLER));
// Add @RequestMapping
ensureGovernorIsAnnotated(getRequestMappingAnnotation());
this.messageSourceField = getMessageSourceField();
ensureGovernorHasField(new FieldMetadataBuilder(this.messageSourceField));
List<MethodMetadata> allMethods = new ArrayList<MethodMetadata>();
switch (this.type) {
case COLLECTION: {
// Add MethodLinkBuilderFactory field
this.methodLinkBuilderFactoryField =
getMethodLinkBuilderFactoryField(ITEM_LINK, this.itemController);
ensureGovernorHasField(new FieldMetadataBuilder(this.methodLinkBuilderFactoryField));
// ROO-3868: New entity visualization support needs a
// ConversionService field
this.conversionServiceField = getConversionServiceField();
ensureGovernorHasField(new FieldMetadataBuilder(this.conversionServiceField));
// Build constructor
String linkBuilderLine =
String.format("%s(linkBuilder.of(%s.class));",
getMutatorMethod(this.methodLinkBuilderFactoryField).getMethodName(),
getNameOfJavaType(this.itemController));
this.constructor = addAndGetConstructor(getConstructor(linkBuilderLine));
// Build methods
this.listMethod = addAndGet(getListMethod(), allMethods);
this.listDatatablesMethod = addAndGet(getListDatatablesMethod(), allMethods);
this.listDatatablesByIdsInMethod = addAndGet(getListDatatablesByIdsInMethod(), allMethods);
boolean generateSelect2 = true;
// XXX To Be Analyzed
// for (FieldMetadata relationField :
// entityMetadata.getRelationsAsChild().values()) {
// if (relationField.getAnnotation(JpaJavaType.MANY_TO_ONE) != null
// || relationField.getAnnotation(JpaJavaType.MANY_TO_MANY) != null)
// {
// generateSelect2 = true;
// break;
// }
// }
if (generateSelect2) {
this.select2Method = addAndGet(getSelect2Method(), allMethods);
} else {
this.select2Method = null;
}
if (this.readOnly) {
this.initBinderMethod = null;
this.populateFormMethod = null;
this.populateFormatsMethod = null;
this.createMethod = null;
this.createFormMethod = null;
this.deleteBatchMethod = null;
} else {
this.initBinderMethod = addAndGet(getInitBinderMethod(entity), allMethods);
this.populateFormatsMethod = addAndGet(getPopulateFormatsMethod(), allMethods);
this.populateFormMethod = addAndGet(getPopulateFormMethod(), allMethods);
this.createMethod = addAndGet(getCreateMethod(), allMethods);
this.createFormMethod = addAndGet(getCreateFormMethod(), allMethods);
this.deleteBatchMethod = addAndGet(getDeleteBatchMethod(), allMethods);
}
this.modelAttributeMethod = null;
this.editFormMethod = null;
this.updateMethod = null;
this.deleteMethod = null;
this.showMethod = null;
this.showInlineMethod = null;
this.modelAttributeDetailsMethod = null;
this.listDatatablesDetailsMethod = null;
this.listDatatablesByIdsInDetailsMethod = null;
this.finderListMethods = null;
this.finderDatatableMethods = null;
this.finderFormMethods = null;
this.createDetailsMethod = null;
this.createFormDetailsMethod = null;
this.removeFromDetailsMethod = null;
this.removeFromDetailsBatchMethod = null;
this.editFormDetailMethod = null;
this.updateDetailMethod = null;
this.deleteDetailMethod = null;
this.showDetailMethod = null;
this.showDetailInlineMethod = null;
// Jasper export methods
List<MethodMetadata> exportMethods = new ArrayList<MethodMetadata>();
this.exportMethod = addAndGet(getExportMethod(), exportMethods);
this.exportCsvMethod = addAndGet(getCsvExportMethod(), exportMethods);
this.exportPdfMethod = addAndGet(getPdfExportMethod(), exportMethods);
this.exportXlsMethod = addAndGet(getXlsMethod(), exportMethods);
this.addColumnToReportBuilderMethod =
addAndGet(getAddColumnToReportBuilderMethod(), exportMethods);
this.exportMethods = exportMethods;
break;
}
case ITEM: {
// Add MethodLinkBuilderFactory field
this.methodLinkBuilderFactoryField =
getMethodLinkBuilderFactoryField(ITEM_LINK, this.governorTypeDetails.getType());
ensureGovernorHasField(new FieldMetadataBuilder(this.methodLinkBuilderFactoryField));
this.conversionServiceField = null;
// Build constructor
String linkBuilderLine =
String.format("%s(linkBuilder.of(%s.class));",
getMutatorMethod(methodLinkBuilderFactoryField).getMethodName(),
getNameOfJavaType(this.governorTypeDetails.getType()));
this.constructor = addAndGetConstructor(getConstructor(linkBuilderLine));
// Build methods
this.modelAttributeMethod = addAndGet(getModelAttributeMethod(), allMethods);
this.showMethod = addAndGet(getShowMethod(), allMethods);
this.showInlineMethod = addAndGet(getShowInlineMethod(), allMethods);
if (readOnly) {
this.editFormMethod = null;
this.updateMethod = null;
this.deleteMethod = null;
this.populateFormatsMethod = null;
this.populateFormMethod = null;
this.initBinderMethod = null;
} else {
this.initBinderMethod = addAndGet(getInitBinderMethod(entity), allMethods);
this.populateFormatsMethod = addAndGet(getPopulateFormatsMethod(), allMethods);
this.populateFormMethod = addAndGet(getPopulateFormMethod(), allMethods);
this.editFormMethod = addAndGet(getEditFormMethod(), allMethods);
this.updateMethod = addAndGet(getUpdateMethod(), allMethods);
this.deleteMethod = addAndGet(getDeleteMethod(), allMethods);
}
this.deleteBatchMethod = null;
this.listMethod = null;
this.listDatatablesMethod = null;
this.listDatatablesByIdsInMethod = null;
this.createMethod = null;
this.createFormMethod = null;
this.modelAttributeDetailsMethod = null;
this.listDatatablesDetailsMethod = null;
this.listDatatablesByIdsInDetailsMethod = null;
this.finderListMethods = null;
this.finderDatatableMethods = null;
this.finderFormMethods = null;
this.select2Method = null;
this.createDetailsMethod = null;
this.createFormDetailsMethod = null;
this.removeFromDetailsMethod = null;
this.removeFromDetailsBatchMethod = null;
this.editFormDetailMethod = null;
this.updateDetailMethod = null;
this.deleteDetailMethod = null;
this.showDetailMethod = null;
this.showDetailInlineMethod = null;
// Jasper export methods
this.exportMethod = null;
this.exportCsvMethod = null;
this.exportPdfMethod = null;
this.exportXlsMethod = null;
this.addColumnToReportBuilderMethod = null;
this.exportMethods = null;
break;
}
case SEARCH: {
this.methodLinkBuilderFactoryField = null;
this.conversionServiceField = null;
// Build constructor
String linkBuilderLine = "";
this.constructor = addAndGetConstructor(getConstructor(linkBuilderLine));
// Build methods
Map<String, MethodMetadata> tmpFindersDtt = new TreeMap<String, MethodMetadata>();
Map<String, MethodMetadata> tmpFinderLists = new TreeMap<String, MethodMetadata>();
Map<String, MethodMetadata> tmpFinderForms = new TreeMap<String, MethodMetadata>();
MethodMetadata finderFormMethod, finderMethod, finderDtMethod;
for (Entry<String, MethodMetadata> finder : findersToAdd.entrySet()) {
finderFormMethod =
getFinderFormMethodForFinderInService(finder.getKey(), finder.getValue());
tmpFinderForms.put(finder.getKey(), addAndGet(finderFormMethod, allMethods));
finderMethod = getFinderMethodForFinderInService(finder.getKey(), finder.getValue());
tmpFinderLists.put(finder.getKey(), addAndGet(finderMethod, allMethods));
finderDtMethod =
getFinderDatatablesMethodForFinderInService(finder.getKey(), finder.getValue());
tmpFindersDtt.put(finder.getKey(), addAndGet(finderDtMethod, allMethods));
}
this.finderDatatableMethods = Collections.unmodifiableMap(tmpFindersDtt);
this.finderListMethods = Collections.unmodifiableMap(tmpFinderLists);
this.finderFormMethods = Collections.unmodifiableMap(tmpFinderForms);
// FIXME We need more method to handle it... To Be Defined!!!
this.deleteBatchMethod = null;
this.listMethod = null;
this.listDatatablesMethod = null;
this.listDatatablesByIdsInMethod = null;
this.createMethod = null;
this.createFormMethod = null;
this.initBinderMethod = null;
this.modelAttributeMethod = null;
this.editFormMethod = null;
this.updateMethod = null;
this.deleteMethod = null;
this.showMethod = null;
this.showInlineMethod = null;
this.populateFormMethod = null;
this.populateFormatsMethod = null;
this.modelAttributeDetailsMethod = null;
this.listDatatablesDetailsMethod = null;
this.listDatatablesByIdsInDetailsMethod = null;
this.select2Method = null;
this.createDetailsMethod = null;
this.createFormDetailsMethod = null;
this.removeFromDetailsMethod = null;
this.removeFromDetailsBatchMethod = null;
this.editFormDetailMethod = null;
this.updateDetailMethod = null;
this.deleteDetailMethod = null;
this.showDetailMethod = null;
this.showDetailInlineMethod = null;
// Jasper export methods
this.exportMethod = null;
this.exportCsvMethod = null;
this.exportPdfMethod = null;
this.exportXlsMethod = null;
this.addColumnToReportBuilderMethod = null;
this.exportMethods = null;
break;
}
case DETAIL: {
// Add MethodLinkBuilderFactory field
this.methodLinkBuilderFactoryField =
getMethodLinkBuilderFactoryField(COLLECTION_LINK, this.collectionController);
ensureGovernorHasField(new FieldMetadataBuilder(this.methodLinkBuilderFactoryField));
// ROO-3868: New entity visualization support needs a
// ConversionService field
this.conversionServiceField = getConversionServiceField();
ensureGovernorHasField(new FieldMetadataBuilder(this.conversionServiceField));
// Build constructor
String linkBuilderLine =
String.format("%s(linkBuilder.of(%s.class));",
getMutatorMethod(methodLinkBuilderFactoryField).getMethodName(),
getNameOfJavaType(this.collectionController));
this.constructor = addAndGetConstructor(getConstructor(linkBuilderLine));
// Build methods
this.modelAttributeMethod = addAndGet(getModelAttributeMethod(), allMethods);
Map<RelationInfo, MethodMetadata> modelAtributeDetailsMethod =
new TreeMap<RelationInfo, MethodMetadata>();
for (int i = 0; i < controllerMetadata.getDetailsFieldInfo().size() - 1; i++) {
RelationInfo info = controllerMetadata.getDetailsFieldInfo().get(i);
JavaType entityType = info.childType;
MethodMetadata method =
addAndGet(
getModelAttributeMethod(info.fieldName,
controllerMetadata.getServiceMetadataForEntity(entityType),
controllerMetadata.getDetailsServiceFields().get(entityType)), allMethods);
modelAtributeDetailsMethod.put(info, method);
}
this.modelAttributeDetailsMethod = Collections.unmodifiableMap(modelAtributeDetailsMethod);
this.populateFormatsMethod = addAndGet(getPopulateFormatsMethod(), allMethods);
this.populateFormMethod = addAndGet(getPopulateFormMethod(), allMethods);
this.listDatatablesDetailsMethod = addAndGet(getListDatatablesDetailMethod(), allMethods);
this.listDatatablesByIdsInDetailsMethod =
addAndGet(getListDatatablesByIdsInDetailMethod(), allMethods);
this.createFormDetailsMethod = addAndGet(getCreateFormDetailsMethod(), allMethods);
// ReadOnly entities doesn't manage relations
if (controllerMetadata.getLastDetailsInfo().type == JpaRelationType.AGGREGATION
&& !entityMetadata.isReadOnly()) {
this.removeFromDetailsMethod = addAndGet(getRemoveFromDetailsMethod(), allMethods);
this.removeFromDetailsBatchMethod =
addAndGet(getRemoveFromDetailsBatchMethod(), allMethods);
this.createDetailsMethod = addAndGet(getCreateDetailsMethod(), allMethods);
this.initBinderMethod = null;
} else if (!entityMetadata.isReadOnly()) {
this.initBinderMethod =
addAndGet(getInitBinderMethod(controllerMetadata.getLastDetailEntity()), allMethods);
this.createDetailsMethod = addAndGet(getCreateDetailsCompositionMethod(), allMethods);
this.removeFromDetailsMethod = null;
this.removeFromDetailsBatchMethod = null;
} else {
this.initBinderMethod = null;
this.createDetailsMethod = null;
this.removeFromDetailsMethod = null;
this.removeFromDetailsBatchMethod = null;
}
this.listMethod = null;
this.listDatatablesMethod = null;
this.listDatatablesByIdsInMethod = null;
this.createMethod = null;
this.createFormMethod = null;
this.deleteBatchMethod = null;
this.editFormMethod = null;
this.updateMethod = null;
this.deleteMethod = null;
this.showMethod = null;
this.showInlineMethod = null;
this.finderListMethods = null;
this.finderDatatableMethods = null;
this.finderFormMethods = null;
this.select2Method = null;
this.editFormDetailMethod = null;
this.updateDetailMethod = null;
this.deleteDetailMethod = null;
this.showDetailMethod = null;
this.showDetailInlineMethod = null;
// Jasper export methods
this.exportMethod = null;
this.exportCsvMethod = null;
this.exportPdfMethod = null;
this.exportXlsMethod = null;
this.addColumnToReportBuilderMethod = null;
this.exportMethods = null;
break;
}
case DETAIL_ITEM: {
// Add MethodLinkBuilderFactory field
this.methodLinkBuilderFactoryField =
getMethodLinkBuilderFactoryField(COLLECTION_LINK, this.collectionController);
ensureGovernorHasField(new FieldMetadataBuilder(this.methodLinkBuilderFactoryField));
this.conversionServiceField = null;
// Build constructor
String linkBuilderLine =
String.format("%s(linkBuilder.of(%s.class));",
getMutatorMethod(methodLinkBuilderFactoryField).getMethodName(),
getNameOfJavaType(this.collectionController));
this.constructor = addAndGetConstructor(getConstructor(linkBuilderLine));
// Build methods
this.modelAttributeMethod = addAndGet(getModelAttributeMethod(), allMethods);
Map<RelationInfo, MethodMetadata> modelAtributeDetailsMethod =
new TreeMap<RelationInfo, MethodMetadata>();
for (RelationInfo info : controllerMetadata.getDetailsFieldInfo()) {
JavaType entityType = info.childType;
MethodMetadata method =
addAndGet(
getModelAttributeMethod(info.fieldName,
controllerMetadata.getServiceMetadataForEntity(entityType),
controllerMetadata.getDetailsServiceFields().get(entityType)), allMethods);
modelAtributeDetailsMethod.put(info, method);
}
this.initBinderMethod =
addAndGet(getInitBinderMethod(controllerMetadata.getLastDetailEntity()), allMethods);
this.modelAttributeDetailsMethod = Collections.unmodifiableMap(modelAtributeDetailsMethod);
this.populateFormatsMethod = addAndGet(getPopulateFormatsMethod(), allMethods);
this.populateFormMethod = addAndGet(getPopulateFormMethod(), allMethods);
this.editFormDetailMethod = addAndGet(getEditFormDetailMethod(), allMethods);
this.updateDetailMethod = addAndGet(getUpdateDetailMethod(), allMethods);
this.deleteDetailMethod = addAndGet(getDeleteDetailMethod(), allMethods);
this.showDetailMethod = addAndGet(getShowDetailMethod(), allMethods);
this.showDetailInlineMethod = addAndGet(getShowDetailInlineMethod(), allMethods);
this.listMethod = null;
this.listDatatablesMethod = null;
this.listDatatablesByIdsInMethod = null;
this.createMethod = null;
this.createFormMethod = null;
this.deleteBatchMethod = null;
this.editFormMethod = null;
this.updateMethod = null;
this.deleteMethod = null;
this.showMethod = null;
this.showInlineMethod = null;
this.finderDatatableMethods = null;
this.finderListMethods = null;
this.finderFormMethods = null;
this.select2Method = null;
this.listDatatablesDetailsMethod = null;
this.listDatatablesByIdsInDetailsMethod = null;
this.removeFromDetailsMethod = null;
this.removeFromDetailsBatchMethod = null;
this.createDetailsMethod = null;
this.createFormDetailsMethod = null;
// Jasper export methods
this.exportMethod = null;
this.exportCsvMethod = null;
this.exportPdfMethod = null;
this.exportXlsMethod = null;
this.addColumnToReportBuilderMethod = null;
this.exportMethods = null;
break;
}
default:
throw new IllegalArgumentException("Unsupported Controller type: " + this.type.name());
}
this.allMethods = Collections.unmodifiableList(allMethods);
// Build the ITD
itdTypeDetails = builder.build();
}
private FieldMetadata getConversionServiceField() {
return new FieldMetadataBuilder(getId(), Modifier.PRIVATE,
new ArrayList<AnnotationMetadataBuilder>(), CONVERSION_SERVICE_FIELD_NAME,
SpringJavaType.CONVERSION_SERVICE).build();
}
private FieldMetadata getMessageSourceField() {
return new FieldMetadataBuilder(getId(), Modifier.PRIVATE,
new ArrayList<AnnotationMetadataBuilder>(), MESSAGE_SOURCE, SpringJavaType.MESSAGE_SOURCE)
.build();
}
private MethodMetadata addAndGet(MethodMetadata method, List<MethodMetadata> allMethods) {
if (allMethods != null) {
allMethods.add(method);
}
ensureGovernorHasMethod(new MethodMetadataBuilder(method));
return method;
}
private ConstructorMetadata addAndGetConstructor(ConstructorMetadata constructor) {
ensureGovernorHasConstructor(new ConstructorMetadataBuilder(constructor));
return constructor;
}
private AnnotationMetadataBuilder getRequestMappingAnnotation() {
AnnotationMetadataBuilder annotationBuilder =
new AnnotationMetadataBuilder(SpringJavaType.REQUEST_MAPPING);
// Adding path attribute
annotationBuilder.addStringAttribute("value", controllerMetadata.getRequestMappingValue());
// Add name attribute
annotationBuilder.addStringAttribute("name", this.getMvcControllerName());
// Add produces
annotationBuilder.addEnumAttribute("produces", SpringEnumDetails.MEDIA_TYPE_TEXT_HTML_VALUE);
return annotationBuilder;
}
private ConstructorMetadata getConstructor(String linkBuilderLine) {
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
// Generating constructor
ConstructorMetadataBuilder constructor = new ConstructorMetadataBuilder(getId());
constructor.setModifier(Modifier.PUBLIC);
constructor.addAnnotation(new AnnotationMetadataBuilder(SpringJavaType.AUTOWIRED));
// Getting serviceFieldName
String serviceFieldName = controllerMetadata.getServiceField().getFieldName().getSymbolName();
constructor.addParameter(serviceFieldName, controllerMetadata.getService());
bodyBuilder.appendFormalLine(String.format("%s(%s);",
getMutatorMethod(controllerMetadata.getServiceField()).getMethodName(), serviceFieldName));
if (this.type == ControllerType.DETAIL || this.type == ControllerType.DETAIL_ITEM) {
for (FieldMetadata serviceField : controllerMetadata.getDetailsServiceFields().values()) {
// Getting parentServiceFieldName
String childServiceFieldName = serviceField.getFieldName().getSymbolName();
// Adding parameters
constructor.addParameter(childServiceFieldName, serviceField.getFieldType());
// Generating body
bodyBuilder.appendFormalLine(String.format("%s(%s);", getMutatorMethod(serviceField)
.getMethodName(), childServiceFieldName));
}
}
// ROO-3868: New entity visualization support needs a ConversionService
// field
if (this.type == ControllerType.COLLECTION || this.type == ControllerType.DETAIL) {
String conversionServiceFieldName =
this.conversionServiceField.getFieldName().getSymbolName();
constructor.addParameter(conversionServiceFieldName,
this.conversionServiceField.getFieldType());
bodyBuilder.appendFormalLine("%s(%s);", getMutatorMethod(this.getConversionServiceField())
.getMethodName(), conversionServiceFieldName);
}
String messageSourceName = this.messageSourceField.getFieldName().getSymbolName();
constructor.addParameter(messageSourceName, messageSourceField.getFieldType());
bodyBuilder.appendFormalLine("%s(%s);", getMutatorMethod(this.messageSourceField)
.getMethodName(), messageSourceName);
// Add ControllerMethodLinkBuilderFactory argument
if (StringUtils.isNotBlank(linkBuilderLine)) {
constructor.addParameter(LINK_BUILDER_ARGUMENT_NAME,
SpringletsJavaType.SPRINGLETS_CONTROLLER_METHOD_LINK_BUILDER_FACTORY);
bodyBuilder.appendFormalLine(linkBuilderLine);
this.builder.getImportRegistrationResolver().addImport(
SpringletsJavaType.SPRINGLETS_CONTROLLER_METHOD_LINK_BUILDER_FACTORY);
}
// Adding body
constructor.setBodyBuilder(bodyBuilder);
return constructor.build();
}
/* Jasper Export Methods */
/**
* Generates a method to add columns to DynamicJasper report builder.
*
* @return MethodMetadata
*/
private MethodMetadata getAddColumnToReportBuilderMethod() {
JavaSymbolName methodName = ADD_COLUMN_TO_REPORT_BUILDER_METHOD_NAME;
// Including parameter types
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
parameterTypes.add(STRING_PARAM);
parameterTypes.add(new AnnotatedJavaType(FAST_REPORT_BUILDER));
parameterTypes.add(LOCALE_PARAM);
parameterTypes.add(STRING_PARAM);
// Check method existence
MethodMetadata existingMethod =
getGovernorMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes));
if (existingMethod != null) {
return existingMethod;
}
// Including parameter names
final List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
final JavaSymbolName columnName = new JavaSymbolName("columnName");
parameterNames.add(columnName);
final JavaSymbolName reportBuilder = new JavaSymbolName("builder");
parameterNames.add(reportBuilder);
parameterNames.add(LOCALE_PARAM_NAME);
parameterNames.add(FILE_NAME_PARAM_NAME);
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
// try {
bodyBuilder.appendFormalLine("try {");
for (int i = 0; i < this.entityValidFields.size(); i++) {
String fieldName = this.entityValidFields.get(i).getFieldName().getSymbolName();
if (i == 0) {
// if (columnName.equals("FIELD")) {
bodyBuilder.appendFormalLine("if (columnName.equals(\"%s\")) {", fieldName);
} else {
// else if (columnName.equals("FIELD")) {
bodyBuilder.appendFormalLine("else if (columnName.equals(\"%s\")) {", fieldName);
}
bodyBuilder.indent();
if (this.entityValidFields.get(i).getFieldName()
.equals(this.entityMetadata.getCurrentIndentifierField().getFieldName())) {
// builder.addColumn("FIELD-TITLE", "FIELD-NAME", FIELD-CLASS,
// 50);
if (this.entityValidFields.get(i).getFieldType().isPrimitive()) {
// Print SimpleTypeName of JavaType when it is a primitive
bodyBuilder
.appendFormalLine(
"builder.addColumn(%s().getMessage(\"%s_%s\", null, \"%s\", locale), \"%s\", %s.class.getName(), 50);",
getAccessorMethod(this.messageSourceField).getMethodName(), this.entityLabel,
fieldName.toLowerCase(), getFieldDefaultLabelValue(fieldName), fieldName,
this.entityValidFields.get(i).getFieldType().getSimpleTypeName());
getNameOfJavaType(this.entityValidFields.get(i).getFieldType());
} else {
bodyBuilder
.appendFormalLine(
"builder.addColumn(%s().getMessage(\"%s_%s\", null, \"%s\", locale), \"%s\", %s.class.getName(), 50);",
getAccessorMethod(this.messageSourceField).getMethodName(), this.entityLabel,
fieldName.toLowerCase(), getFieldDefaultLabelValue(fieldName), fieldName,
getNameOfJavaType(this.entityValidFields.get(i).getFieldType()));
}
} else {
// builder.addColumn("FIELD-TITLE", "FIELD-NAME", FIELD-CLASS,
// 100);
if (this.entityValidFields.get(i).getFieldType().isPrimitive()) {
bodyBuilder
.appendFormalLine(
"builder.addColumn(%s().getMessage(\"%s_%s\", null, \"%s\", locale), \"%s\", %s.class.getName(), 100);",
getAccessorMethod(this.messageSourceField).getMethodName(), this.entityLabel,
fieldName.toLowerCase(), getFieldDefaultLabelValue(fieldName), fieldName,
this.entityValidFields.get(i).getFieldType().getSimpleTypeName());
getNameOfJavaType(this.entityValidFields.get(i).getFieldType());
} else {
bodyBuilder
.appendFormalLine(
"builder.addColumn(%s().getMessage(\"%s_%s\", null, \"%s\", locale), \"%s\", %s.class.getName(), 100);",
getAccessorMethod(this.messageSourceField).getMethodName(), this.entityLabel,
fieldName.toLowerCase(), getFieldDefaultLabelValue(fieldName), fieldName,
getNameOfJavaType(this.entityValidFields.get(i).getFieldType()));
}
}
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
}
// }
bodyBuilder.appendFormalLine("}");
// Build catch blocks
buildExportCatchBlock(bodyBuilder, COLUMN_BUILDER_EXCEPTION);
buildExportCatchBlock(bodyBuilder, CLASS_NOT_FOUND_EXCEPTION);
// Build method
MethodMetadataBuilder methodBuilder =
new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName, JavaType.VOID_PRIMITIVE,
parameterTypes, parameterNames, bodyBuilder);
// Add Javadoc to method
CommentStructure commentStructure = new CommentStructure();
String description =
"This method contains all the entity fields that are able to be displayed in a "
.concat(IOUtils.LINE_SEPARATOR)
.concat(
"report. The developer could add a new column to the report builder providing the ")
.concat(IOUtils.LINE_SEPARATOR)
.concat("field name and the builder where the new field will be added as column.");
List<String> paramInfo = new ArrayList<String>();
paramInfo.add("columnName the field name to show as column");
paramInfo.add("builder The builder where the new field will be added as column.");
commentStructure.addComment(new JavadocComment(description, paramInfo, null, null),
CommentLocation.BEGINNING);
methodBuilder.setCommentStructure(commentStructure);
return methodBuilder.build();
}
/**
* Generates a method to export data using DynamicJasper and arguments
* received as different export methods will delegate in this one.
*
* @return MethodMetadata
*/
private MethodMetadata getExportMethod() {
JavaSymbolName methodName = EXPORT_METHOD_NAME;
// Including parameter types
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
parameterTypes.add(GLOBAL_SEARCH_PARAM);
AnnotationMetadataBuilder pageableDefaultAnnotation =
new AnnotationMetadataBuilder(SpringJavaType.PAGEABLE_DEFAULT);
pageableDefaultAnnotation.addIntegerAttribute("size", Integer.MAX_VALUE);
parameterTypes.add(new AnnotatedJavaType(SpringJavaType.PAGEABLE, pageableDefaultAnnotation
.build()));
parameterTypes.add(STRING_ARRAY_PARAM);
parameterTypes
.add(new AnnotatedJavaType(new JavaType("javax.servlet.http.HttpServletResponse")));
parameterTypes.add(new AnnotatedJavaType(this.jasperReportsMap.get("JasperReportsExporter")));
parameterTypes.add(STRING_PARAM);
parameterTypes.add(LOCALE_PARAM);
MethodMetadata existingMethod =
getGovernorMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes));
if (existingMethod != null) {
return existingMethod;
}
final List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(GLOBAL_SEARCH_PARAM_NAME);
parameterNames.add(PAGEABLE_PARAM_NAME);
parameterNames.add(DATATABLES_COLUMNS_PARAM_NAME);
parameterNames.add(RESPONSE_PARAM_NAME);
parameterNames.add(EXPORTER_PARAM_NAME);
parameterNames.add(FILE_NAME_PARAM_NAME);
parameterNames.add(LOCALE_PARAM_NAME);
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
// Get findAll method
MethodMetadata findAllMethod = this.serviceMetadata.getCurrentFindAllWithGlobalSearchMethod();
// Getting the default return type
JavaType defaultReturnType = findAllMethod.getReturnType();
// Obtain the filtered and ordered elements
// Page<Owner> owners = ownerService.findAll(search, pageable);
bodyBuilder.appendFormalLine("// Obtain the filtered and ordered elements");
bodyBuilder.appendFormalLine("%s %s = %s().%s(%s, %s);", getNameOfJavaType(defaultReturnType),
this.entityPluralUncapitalized,
getAccessorMethod(this.controllerMetadata.getServiceField()).getMethodName(), findAllMethod
.getMethodName().getSymbolName(), GLOBAL_SEARCH_PARAM_NAME, PAGEABLE_PARAM_NAME);
bodyBuilder.newLine();
// // Prevent generation of reports with empty data
bodyBuilder.appendFormalLine("// Prevent generation of reports with empty data");
// if (owners == null || owners.getContent().isEmpty()) {
bodyBuilder.appendFormalLine("if (%1$s == null || %s.getContent().isEmpty()) {",
this.entityPluralUncapitalized);
// return;
bodyBuilder.indent();
bodyBuilder.appendFormalLine("return;");
// }
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
bodyBuilder.newLine();
// // Creates a new ReportBuilder using DynamicJasper library
bodyBuilder.appendFormalLine("// Creates a new ReportBuilder using DynamicJasper library");
// FastReportBuilder builder = new FastReportBuilder();
bodyBuilder.appendFormalLine("%1$s builder = new %1$s();",
getNameOfJavaType(FAST_REPORT_BUILDER));
bodyBuilder.newLine();
// // IMPORTANT: By default, this application uses
// "export_default.jrxml"
bodyBuilder
.appendFormalLine("// IMPORTANT: By default, this application uses \"export_default.jrxml\"");
// // to generate all reports. If you want to customize this specific
// report,
bodyBuilder
.appendFormalLine("// to generate all reports. If you want to customize this specific report,");
// create a new ".jrxml" template and customize it. Take in account the
bodyBuilder
.appendFormalLine("// create a new \".jrxml\" template and customize it. (Take in account the ");
// DynamicJasper restrictions:
bodyBuilder.appendFormalLine("// DynamicJasper restrictions: ");
// http://dynamicjasper.com/2010/10/06/how-to-use-custom-jrxml-templates/)
bodyBuilder
.appendFormalLine("// http://dynamicjasper.com/2010/10/06/how-to-use-custom-jrxml-templates/)");
// builder.setTemplateFile("templates/reports/export_default.jrxml");
bodyBuilder
.appendFormalLine("builder.setTemplateFile(\"templates/reports/export_default.jrxml\");");
bodyBuilder.newLine();
// // The generated report will display the same columns as the
// Datatables component.
bodyBuilder
.appendFormalLine("// The generated report will display the same columns as the Datatables component.");
// // However, this is not mandatory. You could edit this code if you
// want to ignore
bodyBuilder
.appendFormalLine("// However, this is not mandatory. You could edit this code if you want to ignore");
// // the provided datatablesColumns
bodyBuilder.appendFormalLine("// the provided datatablesColumns");
// if (datatablesColumns != null) {
bodyBuilder.appendFormalLine("if (%s != null) {", DATATABLES_COLUMNS_PARAM_NAME);
bodyBuilder.indent();
// for (String column : datatablesColumns) {
bodyBuilder.appendFormalLine("for (String column : %s) {", DATATABLES_COLUMNS_PARAM_NAME);
bodyBuilder.indent();
// // Delegates in addColumnToReportBuilder to include each datatables
// column
bodyBuilder.appendFormalLine("// Delegates in %s to include each datatables column",
ADD_COLUMN_TO_REPORT_BUILDER_METHOD_NAME);
// // to the report builder
bodyBuilder.appendFormalLine("// to the report builder");
// addColumnToReportBuilder(column, builder, locale);
bodyBuilder.appendFormalLine("addColumnToReportBuilder(column, builder, %s, %s);",
LOCALE_PARAM_NAME, FILE_NAME_PARAM_NAME);
bodyBuilder.indentRemove();
// }
bodyBuilder.appendFormalLine("}");
bodyBuilder.indentRemove();
// }
bodyBuilder.appendFormalLine("}");
bodyBuilder.newLine();
// // This property resizes the columns to use full width page.
bodyBuilder.appendFormalLine("// This property resizes the columns to use full width page.");
// // Set false value if you want to use the specific width of each
// column.
bodyBuilder
.appendFormalLine("// Set false value if you want to use the specific width of each column.");
// builder.setUseFullPageWidth(true);
bodyBuilder.appendFormalLine("builder.setUseFullPageWidth(true);");
bodyBuilder.newLine();
// // Creates a new Jasper Reports Datasource using the obtained
// elements
bodyBuilder
.appendFormalLine("// Creates a new Jasper Reports Datasource using the obtained elements");
// JRDataSource ds = new
// JRBeanCollectionDataSource(owners.getContent());
bodyBuilder.appendFormalLine("%s ds = new %s(%s.getContent());",
getNameOfJavaType(JR_DATA_SOURCE), getNameOfJavaType(JR_BEAN_COLLECTION_DATA_SOURCE),
this.entityPluralUncapitalized);
bodyBuilder.newLine();
// // Generates the JasperReport
bodyBuilder.appendFormalLine("// Generates the JasperReport");
// JasperPrint jp;
bodyBuilder.appendFormalLine("%s jp;", getNameOfJavaType(JASPER_PRINT));
// try {
bodyBuilder.appendFormalLine("try {");
bodyBuilder.indent();
// jp = DynamicJasperHelper.generateJasperPrint(builder.build(), new
// ClassicLayoutManager(), ds);
bodyBuilder.appendFormalLine("jp = %s.generateJasperPrint(builder.build(), new %s(), ds);",
getNameOfJavaType(DYNAMIC_JASPER_HELPER), getNameOfJavaType(CLASSIC_LAYOUT_MANAGER));
bodyBuilder.indentRemove();
// "}"
bodyBuilder.appendFormalLine("}");
// Build catch block
buildExportCatchBlock(bodyBuilder, JR_EXCEPTION);
bodyBuilder.newLine();
// // Converts the JaspertReport element to a ByteArrayOutputStream and
bodyBuilder
.appendFormalLine("// Converts the JaspertReport element to a ByteArrayOutputStream and");
// // write it into the response stream using the provided
// JasperReportExporter
bodyBuilder
.appendFormalLine("// write it into the response stream using the provided JasperReportExporter");
bodyBuilder.appendFormalLine("try {");
bodyBuilder.indent();
// exporter.export(jp, fileName, response);
bodyBuilder.appendFormalLine("%s.export(jp, %s, %s);", EXPORTER_PARAM_NAME,
FILE_NAME_PARAM_NAME, RESPONSE_PARAM_NAME);
bodyBuilder.indentRemove();
// "}"
bodyBuilder.appendFormalLine("}");
buildExportCatchBlock(bodyBuilder, JR_EXCEPTION);
buildExportCatchBlock(bodyBuilder, IO_EXCEPTION);
bodyBuilder.reset();
// Build method
MethodMetadataBuilder methodBuilder =
new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName, JavaType.VOID_PRIMITIVE,
parameterTypes, parameterNames, bodyBuilder);
// Add Javadoc to method
CommentStructure commentStructure = new CommentStructure();
String description =
"Method that obtains the filtered and ordered records using the Datatables information and "
.concat(IOUtils.LINE_SEPARATOR)
.concat("export them to a new report file. (It ignores the current pagination).")
.concat(IOUtils.LINE_SEPARATOR)
.concat(IOUtils.LINE_SEPARATOR)
.concat("To generate the report file it uses the `DynamicJasper` library")
.concat(IOUtils.LINE_SEPARATOR)
.concat(
"(http://dynamicjasper.com). This library allows developers to generate reports dynamically")
.concat(IOUtils.LINE_SEPARATOR)
.concat("without use an specific template to each entity.")
.concat(IOUtils.LINE_SEPARATOR)
.concat(IOUtils.LINE_SEPARATOR)
.concat(
"To customize the appearance of ALL generated reports, you could customize the ")
.concat(IOUtils.LINE_SEPARATOR)
.concat(
"\"export_default.jrxml\" template located in \"src/main/resources/templates/reports/\". However,")
.concat(IOUtils.LINE_SEPARATOR)
.concat(
"if you want to customize the appearance of this specific report, you could create a new")
.concat(IOUtils.LINE_SEPARATOR)
.concat(
"\".jrxml\" file and provide it to the library replacing the `builder.setTemplateFile();`")
.concat(IOUtils.LINE_SEPARATOR).concat("operation used in this implementation.");
// Create params info
List<String> paramsInfo = new ArrayList<String>();
paramsInfo
.add("search GlobalSearch that contains the filter provided by the Datatables component.");
paramsInfo
.add("pageable Pageable that contains the Sort info provided by the Datatabes component.");
paramsInfo.add("datatablesColumns Columns displayed in the Datatables component.");
paramsInfo.add("response The HttpServletResponse.");
paramsInfo.add("exporter An specific JasperReportsExporter to be used during export process.");
paramsInfo.add("fileName The final filename to use.");
paramsInfo.add("locale The current Locale in the view context.");
// Add JavadocComment to CommentStructure and method
commentStructure.addComment(new JavadocComment(description, paramsInfo, null, null),
CommentLocation.BEGINNING);
methodBuilder.setCommentStructure(commentStructure);
return methodBuilder.build();
}
/**
* Generates a method to export data to CSV using DynamicJasper.
*
* @return MethodMetadata
*/
private MethodMetadata getCsvExportMethod() {
if (jasperReportsMap.get("JasperReportsCsvExporter") != null) {
final String exporterMethodInvocation =
String.format("new %s()",
getNameOfJavaType(jasperReportsMap.get("JasperReportsCsvExporter")));
final String fileName =
String.format("%s_report.csv", StringUtils.uncapitalize(this.entityPlural));
final JavaSymbolName methodName = EXPORT_CSV_METHOD_NAME;
return buildExportTypeMethod(exporterMethodInvocation, fileName, methodName, "exportCsv",
"/export/csv", "CSV");
}
return null;
}
/**
* Generates a method to export data to PDF using DynamicJasper.
*
* @return MethodMetadata
*/
private MethodMetadata getPdfExportMethod() {
if (jasperReportsMap.get("JasperReportsPdfExporter") != null) {
final String exporterMethodInvocation =
String.format("new %s()",
getNameOfJavaType(jasperReportsMap.get("JasperReportsPdfExporter")));
final String fileName =
String.format("%s_report.pdf", StringUtils.uncapitalize(this.entityPlural));
final JavaSymbolName methodName = EXPORT_PDF_METHOD_NAME;
return buildExportTypeMethod(exporterMethodInvocation, fileName, methodName, "exportPdf",
"/export/pdf", "PDF");
}
return null;
}
/**
* Generates a method to export data to XLS using DynamicJasper.
*
* @return MethodMetadata
*/
private MethodMetadata getXlsMethod() {
if (jasperReportsMap.get("JasperReportsXlsExporter") != null) {
final String exporterMethodInvocation =
String.format("new %s()",
getNameOfJavaType(jasperReportsMap.get("JasperReportsXlsExporter")));
final String fileName =
String.format("%s_report.xls", StringUtils.uncapitalize(this.entityPlural));
final JavaSymbolName methodName = EXPORT_XLS_METHOD_NAME;
return buildExportTypeMethod(exporterMethodInvocation, fileName, methodName, "exportXls",
"/export/xls", "XLS");
}
return null;
}
/**
* Builds a `catch` block which throws an exception with a localized message
* for export method.
*
* @param bodyBuilder
* the InvocableMemberBodyBuilder which will be appended to
* export method
*/
private void buildExportCatchBlock(InvocableMemberBodyBuilder bodyBuilder, JavaType exceptionType) {
// } catch (JRException e) {
bodyBuilder.appendFormalLine("catch (%s e) {", getNameOfJavaType(exceptionType));
bodyBuilder.indent();
// String errorMessage =
// this.messageSource.getMessage("error_exportingErrorException",
bodyBuilder.appendFormalLine(
"String errorMessage = %s().getMessage(\"error_exportingErrorException\", ",
getAccessorMethod(this.messageSourceField).getMethodName());
// new Object[] {StringUtils.substringAfterLast(fileName,
// ".").toUpperCase()},
bodyBuilder.indent();
bodyBuilder.appendFormalLine(
"new Object[] {%s.substringAfterLast(fileName, \".\").toUpperCase()}, ",
getNameOfJavaType(STRING_UTILS_APACHE));
// String.format("Error while exporting data to %s file", StringUtils
bodyBuilder.appendFormalLine(
"String.format(\"Error while exporting data to %s file\", StringUtils.",
getNameOfJavaType(STRING_UTILS_APACHE));
bodyBuilder.indent();
// substringAfterLast(fileName, ".").toUpperCase()), locale);
bodyBuilder.appendFormalLine("substringAfterLast(fileName, \".\").toUpperCase()), locale);");
bodyBuilder.indentRemove();
bodyBuilder.indentRemove();
// throw new ExportingErrorException(errorMessage);
bodyBuilder.appendFormalLine("throw new %s(errorMessage);",
getNameOfJavaType(this.jasperReportsMap.get("ExportingErrorException")));
bodyBuilder.indentRemove();
// }
bodyBuilder.appendFormalLine("}");
}
/**
* Builds export (TYPE) method, which is similar in all export target types.
*
* @param exporterClassInstantiation
* the String with the instantiation of the JasperReports support
* class.
* @param fileName
* the String with the output file name.
* @param methodName
* the JavaSymbolName with the method name.
* @return MethodMetadata
*/
private MethodMetadata buildExportTypeMethod(final String exporterClassInstantiation,
final String fileName, final JavaSymbolName methodName, final String getMappingAnnotatinName,
final String getMappingAnnotationValue, final String fileType) {
// Including parameter types
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
parameterTypes.add(GLOBAL_SEARCH_PARAM);
AnnotationMetadataBuilder pageableDefaultAnnotation =
new AnnotationMetadataBuilder(SpringJavaType.PAGEABLE_DEFAULT);
pageableDefaultAnnotation.addIntegerAttribute("size", Integer.MAX_VALUE);
parameterTypes.add(new AnnotatedJavaType(SpringJavaType.PAGEABLE, pageableDefaultAnnotation
.build()));
AnnotationMetadataBuilder requestParamAnnotation =
new AnnotationMetadataBuilder(SpringJavaType.REQUEST_PARAM);
requestParamAnnotation.addStringAttribute("value",
DATATABLES_COLUMNS_PARAM_NAME.getSymbolName());
parameterTypes
.add(new AnnotatedJavaType(JavaType.STRING_ARRAY, requestParamAnnotation.build()));
parameterTypes
.add(new AnnotatedJavaType(new JavaType("javax.servlet.http.HttpServletResponse")));
parameterTypes.add(LOCALE_PARAM);
MethodMetadata existingMethod =
getGovernorMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes));
if (existingMethod != null) {
return existingMethod;
}
// Including parameter names
final List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(GLOBAL_SEARCH_PARAM_NAME);
parameterNames.add(PAGEABLE_PARAM_NAME);
parameterNames.add(DATATABLES_COLUMNS_PARAM_NAME);
parameterNames.add(RESPONSE_PARAM_NAME);
parameterNames.add(LOCALE_PARAM_NAME);
// Adding annotations
final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
AnnotationMetadataBuilder getMappingBuilder = new AnnotationMetadataBuilder(GET_MAPPING);
getMappingBuilder.addStringAttribute("name", getMappingAnnotatinName);
getMappingBuilder.addStringAttribute("value", getMappingAnnotationValue);
annotations.add(getMappingBuilder);
annotations.add(RESPONSE_BODY_ANNOTATION);
// Add throws types
final List<JavaType> throwTypes = new ArrayList<JavaType>();
throwTypes.add(JR_EXCEPTION);
throwTypes.add(IO_EXCEPTION);
throwTypes.add(COLUMN_BUILDER_EXCEPTION);
throwTypes.add(CLASS_NOT_FOUND_EXCEPTION);
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
// export(search, pageable, datatablesColumns, response, new
// JasperReportsCsvExporter(), "ENTITY-ITEM_report.csv");
bodyBuilder.appendFormalLine("export(%s, %s, %s, %s, %s, \"%s\", %s);",
GLOBAL_SEARCH_PARAM_NAME, PAGEABLE_PARAM_NAME, DATATABLES_COLUMNS_PARAM_NAME,
RESPONSE_PARAM_NAME, exporterClassInstantiation, fileName,
LOCALE_PARAM_NAME.getSymbolName());
// return ResponseEntity.ok().build();
bodyBuilder.appendFormalLine("return %s.ok().build();", getNameOfJavaType(RESPONSE_ENTITY));
// Build method
MethodMetadataBuilder methodBuilder =
new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName,
JavaType.wrapperWilcard(RESPONSE_ENTITY), parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
// Add JavaDoc
CommentStructure commentStructure = new CommentStructure();
String description =
"It delegates in the `export` method providing the necessary information".concat(
IOUtils.LINE_SEPARATOR).concat(String.format("to generate a %s report.", fileType));
// Add params info to commment block
List<String> paramsInfo = new ArrayList<String>();
paramsInfo
.add("search The GlobalSearch that contains the filter provided by the Datatables component");
paramsInfo
.add("pageable The Pageable that contains the Sort info provided by the Datatabes component");
paramsInfo.add("datatablesColumns The Columns displayed in the Datatables component");
paramsInfo.add("response The HttpServletResponse");
// Add JavadocComment to CommentStructure and to method
commentStructure.addComment(new JavadocComment(description, paramsInfo, null, null),
CommentLocation.BEGINNING);
methodBuilder.setCommentStructure(commentStructure);
return methodBuilder.build();
}
/**
* Returns a String with default label to show when cannot find the right
* label code.
*
* @return a String with default field label
*/
private String getFieldDefaultLabelValue(String fieldName) {
String[] splittedFieldName = StringUtils.splitByCharacterTypeCamelCase(fieldName);
String label = "";
for (int i = 0; i < splittedFieldName.length; i++) {
if (i != 0) {
label = label.concat(" ");
}
label = label.concat(StringUtils.capitalize(splittedFieldName[i]));
}
return label;
}
/**
* Generates a finder method which delegates on entity service to get result
*
* @param finderName
* @param serviceFinderMethod
* @return
*/
private MethodMetadata getFinderFormMethodForFinderInService(String finderName,
MethodMetadata serviceFinderMethod) {
// Define methodName
String pathName = finderName;
if (pathName.startsWith("findBy")) {
pathName = pathName.replace("findBy", "by");
}
final JavaSymbolName methodName = new JavaSymbolName(pathName.concat("Form"));
// Form Bean is always the first parameter of finder
final JavaType formBean = serviceFinderMethod.getParameterTypes().get(0).getJavaType();
List<AnnotationMetadata> formBeanAnnotations = new ArrayList<AnnotationMetadata>();
AnnotationMetadataBuilder formBeanAnnotation =
new AnnotationMetadataBuilder(SpringJavaType.MODEL_ATTRIBUTE);
formBeanAnnotation.addStringAttribute("value", FORM_BEAN_PARAM_NAME.getSymbolName());
formBeanAnnotations.add(formBeanAnnotation.build());
AnnotatedJavaType annotatedFormBean = new AnnotatedJavaType(formBean, formBeanAnnotations);
// Including annotated formBean parameter and Model parameter
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
parameterTypes.add(annotatedFormBean);
parameterTypes.add(MODEL_PARAM);
MethodMetadata existingMethod =
getGovernorMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes));
if (existingMethod != null) {
return existingMethod;
}
final List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(FORM_BEAN_PARAM_NAME);
parameterNames.add(MODEL_PARAM_NAME);
// Adding annotations
final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
// Adding @GetMapping annotation
AnnotationMetadataBuilder getMappingAnnotation = new AnnotationMetadataBuilder(GET_MAPPING);
getMappingAnnotation.addStringAttribute("name", methodName.getSymbolName());
// TODO Delegates on ControllerOperations to obtain the URL for this
// finder
getMappingAnnotation.addStringAttribute("value", "/" + pathName + "/search-form");
annotations.add(getMappingAnnotation);
this.mvcMethodNames.put(methodName.getSymbolName(), methodName.getSymbolName());
// Generate body
final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
buildPopulateFormatBody(bodyBuilder, formBeansDateTimeFields.get(formBean));
final List<FieldMetadata> enumFileds = formBeansEnumFields.get(formBean);
if (enumFileds != null && !enumFileds.isEmpty()) {
buildPopulateEnumsBody(bodyBuilder, formBeansEnumFields.get(formBean));
}
// return new ModelAndView("customers/findByFirstNameLastNameForm");
bodyBuilder.appendFormalLine("return new %s(\"%s/%s\");",
getNameOfJavaType(SpringJavaType.MODEL_AND_VIEW), viewsPath, finderName.concat("Form"));
MethodMetadataBuilder methodBuilder =
new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName,
SpringJavaType.MODEL_AND_VIEW, parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
return methodBuilder.build();
}
/**
* Generates a finder method which delegates on entity service to get result
*
* @param finderName
* @param serviceFinderMethod
* @return
*/
private MethodMetadata getFinderMethodForFinderInService(String finderName,
MethodMetadata serviceFinderMethod) {
// Define methodName
String pathName = finderName;
if (pathName.startsWith("findBy")) {
pathName = pathName.replace("findBy", "by");
}
final JavaSymbolName methodName = new JavaSymbolName(pathName);
// Form Bean is always the first parameter of finder
final JavaType formBean = serviceFinderMethod.getParameterTypes().get(0).getJavaType();
List<AnnotationMetadata> formBeanAnnotations = new ArrayList<AnnotationMetadata>();
AnnotationMetadataBuilder formBeanAnnotation =
new AnnotationMetadataBuilder(SpringJavaType.MODEL_ATTRIBUTE);
formBeanAnnotation.addStringAttribute("value", FORM_BEAN_PARAM_NAME.getSymbolName());
formBeanAnnotations.add(formBeanAnnotation.build());
AnnotatedJavaType annotatedFormBean = new AnnotatedJavaType(formBean, formBeanAnnotations);
// Including annotated formBean parameter and Model parameter
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
parameterTypes.add(annotatedFormBean);
parameterTypes.add(MODEL_PARAM);
MethodMetadata existingMethod =
getGovernorMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes));
if (existingMethod != null) {
return existingMethod;
}
final List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(FORM_BEAN_PARAM_NAME);
parameterNames.add(MODEL_PARAM_NAME);
// Adding annotations
final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
// Adding @GetMapping annotation
AnnotationMetadataBuilder getMappingAnnotation = new AnnotationMetadataBuilder(GET_MAPPING);
getMappingAnnotation.addStringAttribute("name", methodName.getSymbolName());
// TODO Delegates on ControllerOperations to obtain the URL for this
// finder
getMappingAnnotation.addStringAttribute("value", "/" + pathName);
annotations.add(getMappingAnnotation);
this.mvcMethodNames.put(methodName.getSymbolName(), methodName.getSymbolName());
// Generate body
final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
buildPopulateFormatBody(bodyBuilder, formBeansDateTimeFields.get(formBean));
final List<FieldMetadata> enumFileds = formBeansEnumFields.get(formBean);
if (enumFileds != null && !enumFileds.isEmpty()) {
buildPopulateEnumsBody(bodyBuilder, formBeansEnumFields.get(formBean));
}
// return new ModelAndView("customers/findByFirstNameLastName");
bodyBuilder.appendFormalLine("return new %s(\"%s/%s\");",
getNameOfJavaType(SpringJavaType.MODEL_AND_VIEW), viewsPath, finderName);
MethodMetadataBuilder methodBuilder =
new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName,
SpringJavaType.MODEL_AND_VIEW, parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
return methodBuilder.build();
}
/**
* Generates a finder method which delegates on entity service to get result
*
* @param finderName
* @param serviceFinderMethod
* @return
*/
private MethodMetadata getFinderDatatablesMethodForFinderInService(String finderName,
MethodMetadata serviceFinderMethod) {
// Define methodName
String pathName = finderName;
if (pathName.startsWith("findBy")) {
pathName = pathName.replace("findBy", "by");
}
final JavaSymbolName methodName = new JavaSymbolName(pathName.concat("Dt"));
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
// Form Bean is always the first parameter of finder
final JavaType formBean = serviceFinderMethod.getParameterTypes().get(0).getJavaType();
List<AnnotationMetadata> formBeanAnnotations = new ArrayList<AnnotationMetadata>();
AnnotationMetadataBuilder formBeanAnnotation =
new AnnotationMetadataBuilder(SpringJavaType.MODEL_ATTRIBUTE);
formBeanAnnotation.addStringAttribute("value", FORM_BEAN_PARAM_NAME.getSymbolName());
formBeanAnnotations.add(formBeanAnnotation.build());
AnnotatedJavaType annotatedFormBean = new AnnotatedJavaType(formBean, formBeanAnnotations);
parameterTypes.add(annotatedFormBean);
// Including GlobalSearch parameter and DatatablesPageable parameter
parameterTypes.add(GLOBAL_SEARCH_PARAM);
parameterTypes.add(DATATABLES_PAGEABLE_PARAM);
// Including Draw parameter
List<AnnotationMetadata> drawAnnotations = new ArrayList<AnnotationMetadata>();
AnnotationMetadataBuilder drawAnnotation =
new AnnotationMetadataBuilder(SpringJavaType.REQUEST_PARAM);
drawAnnotation.addEnumAttribute("value", SpringletsJavaType.SPRINGLETS_DATATABLES,
"PARAMETER_DRAW");
drawAnnotations.add(drawAnnotation.build());
AnnotatedJavaType annotatedDraw = new AnnotatedJavaType(JavaType.INT_OBJECT, drawAnnotations);
parameterTypes.add(annotatedDraw);
MethodMetadata existingMethod =
getGovernorMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes));
if (existingMethod != null) {
return existingMethod;
}
final List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
final List<String> parameterStrings = new ArrayList<String>();
parameterNames.add(FORM_BEAN_PARAM_NAME);
parameterStrings.add(FORM_BEAN_PARAM_NAME.getSymbolName());
parameterNames.add(GLOBAL_SEARCH_PARAM_NAME);
parameterStrings.add(GLOBAL_SEARCH_PARAM_NAME.getSymbolName());
parameterNames.add(DATATABLES_PAGEABLE_PARAM_NAME);
parameterStrings.add(DATATABLES_PAGEABLE_PARAM_NAME.getSymbolName());
parameterNames.add(DRAW_PARAM_NAME);
// Adding annotations
final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
// Adding @GetMapping annotation
AnnotationMetadataBuilder getMappingAnnotation = new AnnotationMetadataBuilder(GET_MAPPING);
getMappingAnnotation.addStringAttribute("name", methodName.getSymbolName());
// TODO Delegates on ControllerOperations to obtain the URL for this
// finder
getMappingAnnotation.addStringAttribute("value", "/" + pathName + "/dt");
getMappingAnnotation.addEnumAttribute("produces", SPRINGLETS_DATATABLES, "MEDIA_TYPE");
annotations.add(getMappingAnnotation);
this.mvcMethodNames.put(methodName.getSymbolName(), methodName.getSymbolName());
// Adding @ResoponseBody
annotations.add(RESPONSE_BODY_ANNOTATION);
// Generating returnType
JavaType serviceReturnType = serviceFinderMethod.getReturnType();
JavaType datatablesDataReturnType =
serviceReturnType.getParameters().isEmpty() ? serviceReturnType.getBaseType()
: serviceReturnType.getParameters().get(0);
JavaType returnType =
JavaType.wrapperOf(RESPONSE_ENTITY, JavaType.wrapperOf(
SpringletsJavaType.SPRINGLETS_DATATABLES_DATA, datatablesDataReturnType));
// Generate body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
final String itemNames = StringUtils.uncapitalize(this.entityPlural);
// Page<Customer> customers = customerService.findAll(formBean,
// globalSearch, pageable);
bodyBuilder.newLine();
bodyBuilder.appendFormalLine("%s %s = %s().%s(%s);", getNameOfJavaType(serviceReturnType),
itemNames, getAccessorMethod(controllerMetadata.getServiceField()).getMethodName(),
serviceFinderMethod.getMethodName(), StringUtils.join(parameterStrings, ","));
// long totalProductsCount = products.getTotalElements();
String totalItemNamesCount = String.format("total%sCount", StringUtils.capitalize(itemNames));
bodyBuilder.appendFormalLine(String.format("long %s = %s.getTotalElements();",
totalItemNamesCount, itemNames));
// if (search != null && StringUtils.hasText(search.getText())) {
bodyBuilder
.appendFormalLine(String.format("if (%s != null && %s.isNotBlank(%s.getText())) {",
GLOBAL_SEARCH_PARAM_NAME, getNameOfJavaType(STRING_UTILS_APACHE),
GLOBAL_SEARCH_PARAM_NAME));
// Getting count method
MethodMetadata countMethod = null;
Map<JavaSymbolName, MethodMetadata> repositoryCustomFindersAndCounts =
serviceMetadata.getRepositoryCustomFindersAndCounts();
for (Entry<JavaSymbolName, MethodMetadata> entry : repositoryCustomFindersAndCounts.entrySet()) {
if (entry.getKey().getSymbolName().equals(finderName)) {
countMethod = entry.getValue();
}
}
Validate
.notNull(
countMethod,
String
.format(
"ERROR: Is not possible to obtain the count method related with finder '%s'. Please, "
+ "generate the count method before continue publishing this finder to the web layer.",
finderName));
// totalProductsCount =
// productService.countByNameAndDescription(formBean);
bodyBuilder.indent();
bodyBuilder.appendFormalLine(String.format("%s = %s().%s(%s);", totalItemNamesCount,
getAccessorMethod(controllerMetadata.getServiceField()).getMethodName(),
countMethod.getMethodName(), FORM_BEAN_PARAM_NAME));
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
// DatatablesData<Product> datatablesData = new
// DatatablesData<Product>(products, totalProductsCount, draw);
bodyBuilder.appendFormalLine(String.format(
"%s<%s> datatablesData = new DatatablesData<%s>(%s, %s, %s);",
getNameOfJavaType(SpringletsJavaType.SPRINGLETS_DATATABLES_DATA),
getNameOfJavaType(datatablesDataReturnType), getNameOfJavaType(datatablesDataReturnType),
itemNames, totalItemNamesCount, DRAW_PARAM_NAME));
// return ResponseEntity.ok(datatablesData);
bodyBuilder.appendFormalLine(String.format("return %s.ok(datatablesData);",
getNameOfJavaType(RESPONSE_ENTITY)));
MethodMetadataBuilder methodBuilder =
new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName, returnType, parameterTypes,
parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
return methodBuilder.build();
}
/**
* Creates getInitBinderMethod method
*
* @return
*/
private MethodMetadata getInitBinderMethod(JavaType entity) {
// Define methodName
final JavaSymbolName methodName =
new JavaSymbolName("init" + entity.getSimpleTypeName() + "Binder");
// Define method parameter types and parameter names
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
parameterTypes.add(AnnotatedJavaType.convertFromJavaType(SpringJavaType.WEB_DATA_BINDER));
List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(new JavaSymbolName("dataBinder"));
MethodMetadata existingMethod =
getGovernorMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes));
if (existingMethod != null) {
return existingMethod;
}
InvocableMemberBodyBuilder body = new InvocableMemberBodyBuilder();
// dataBinder.setDisallowedFields("id");
body.appendFormalLine("dataBinder.setDisallowedFields(\"%s\");", entityIdentifier);
for (Pair<RelationInfo, JpaEntityMetadata> item : compositionRelationOneToOne) {
body.appendFormalLine("dataBinder.setDisallowedFields(\"%s.%s\");", item.getKey().fieldName,
item.getValue().getCurrentIndentifierField().getFieldName());
}
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder =
new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName, JavaType.VOID_PRIMITIVE,
parameterTypes, parameterNames, body);
// Adding annotation
final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
// Adding @InitBinder annotation
AnnotationMetadataBuilder getInitBinderAnnotation = new AnnotationMetadataBuilder(INIT_BINDER);
getInitBinderAnnotation.addStringAttribute("value",
StringUtils.uncapitalize(entity.getSimpleTypeName()));
annotations.add(getInitBinderAnnotation);
methodBuilder.setAnnotations(annotations);
return methodBuilder.build();
}
/**
* Build a MethodLinkBuilderFactory field of provided type
*
* @param fieldName
* @return FieldMetadata
*/
private FieldMetadata getMethodLinkBuilderFactoryField(String fieldName, JavaType controller) {
FieldMetadataBuilder field =
new FieldMetadataBuilder(getId(), Modifier.PRIVATE, new JavaSymbolName(fieldName),
JavaType.wrapperOf(SpringletsJavaType.SPRINGLETS_METHOD_LINK_BUILDER_FACTORY,
controller), null);
return field.build();
}
/**
* This method provides the getModelAttributeMethod() method
*
* @return MethodMetadata
*/
private MethodMetadata getModelAttributeMethod() {
return getModelAttributeMethod(StringUtils.uncapitalize(entity.getSimpleTypeName()),
serviceMetadata, controllerMetadata.getServiceField());
}
/**
* This method provides the method to add to manage a model attribute from a
* path variable
*
* @param pathVariable
* @param serviceMetadata
* @param serviceField
* @return MethodMetadata
*/
private MethodMetadata getModelAttributeMethod(String pathVariable,
ServiceMetadata serviceMetadata, FieldMetadata serviceField) {
String pathVariableUncapitalized = StringUtils.uncapitalize(pathVariable);
// Define methodName
final JavaSymbolName methodName =
new JavaSymbolName("get" + StringUtils.capitalize(pathVariable));
final JavaType idType =
serviceMetadata.getCurrentFindOneMethod().getParameterTypes().get(0).getJavaType();
final JavaSymbolName idName =
serviceMetadata.getCurrentFindOneMethod().getParameterNames().get(0);
final JavaType entityType = serviceMetadata.getCurrentFindOneMethod().getReturnType();
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
AnnotationMetadataBuilder pathVariableAnnotation =
new AnnotationMetadataBuilder(SpringJavaType.PATH_VARIABLE);
pathVariableAnnotation.addStringAttribute("value", pathVariableUncapitalized);
parameterTypes.add(new AnnotatedJavaType(idType, pathVariableAnnotation.build()));
parameterTypes.add(LOCALE_PARAM);
parameterTypes.add(new AnnotatedJavaType(SpringJavaType.HTTP_METHOD));
MethodMetadata existingMethod =
getGovernorMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes));
if (existingMethod != null) {
return existingMethod;
}
final List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(idName);
parameterNames.add(LOCALE_PARAM_NAME);
parameterNames.add(HTTP_METHOD_PARAM_NAME);
// Generate body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
if (this.entityMetadata.isReadOnly()) {
// Customer customer = customerService.findOne(id);
bodyBuilder.appendFormalLine("%s %s = %s.%s(%s);", getNameOfJavaType(entityType),
pathVariableUncapitalized, serviceField.getFieldName(), serviceMetadata
.getCurrentFindOneMethod().getMethodName(), idName);
// if (entity == null) {
bodyBuilder.appendFormalLine("if (%s == null) {", pathVariableUncapitalized);
bodyBuilder.indent();
// String message = messageSource.getMessage("error_NotFound",
// entity, null, locale);
bodyBuilder.appendFormalLine(
"String message = %s.getMessage(\"error_NotFound\", new Object[] "
+ "{\"%s\", %s}, \"The record couldn't be found\", %s);", MESSAGE_SOURCE,
this.entity.getSimpleTypeName(), idName, LOCALE_PARAM_NAME.getSymbolName());
// throw new NotFoundException(message);
bodyBuilder.appendFormalLine("throw new %s(message);",
getNameOfJavaType(SPRINGLETS_NOT_FOUND_EXCEPTION));
bodyBuilder.indentRemove();
// }
bodyBuilder.appendFormalLine("}");
} else {
// Entity entity = null;
bodyBuilder.appendFormalLine("%s %s = null;", getNameOfJavaType(entityType),
pathVariableUncapitalized);
// if (HttpMethod.PUT.equals(method)) {
bodyBuilder.appendFormalLine("if (%s.PUT.equals(%s)) {",
getNameOfJavaType(SpringJavaType.HTTP_METHOD), HTTP_METHOD_PARAM_NAME);
// pet = petService.findOneForUpdate(id);
bodyBuilder.indent();
bodyBuilder.appendFormalLine("%s = %s.%s(%s);", pathVariableUncapitalized, serviceField
.getFieldName().getSymbolName(), FIN_ONE_FOR_UPDATE_METHOD_NAME.getSymbolName(), idName);
// } else {
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("} else {");
// entity = entityService.findOne(id);
bodyBuilder.indent();
bodyBuilder.appendFormalLine("%s = %s.%s(%s);", pathVariableUncapitalized, serviceField
.getFieldName().getSymbolName(), serviceMetadata.getCurrentFindOneMethod()
.getMethodName().getSymbolName(), idName);
// }
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
// if (entity == null) {
bodyBuilder.newLine();
bodyBuilder.appendFormalLine("if (%s == null) {", pathVariableUncapitalized);
// String message = messageSource.getMessage("error_NotFound",
// entity, null, locale);
bodyBuilder.indent();
bodyBuilder
.appendFormalLine(
"String message = %s.getMessage(\"error_NotFound\", new Object[] {\"%s\", %s}, \"The record couldn't be found\", %s);",
MESSAGE_SOURCE, this.entity.getSimpleTypeName(), idName,
LOCALE_PARAM_NAME.getSymbolName());
// throw new NotFoundException(message);
bodyBuilder.appendFormalLine("throw new %s(message);",
getNameOfJavaType(SPRINGLETS_NOT_FOUND_EXCEPTION));
bodyBuilder.indentRemove();
// }
bodyBuilder.appendFormalLine("}");
}
// return entity;
bodyBuilder.appendFormalLine("return %s;", pathVariableUncapitalized);
MethodMetadataBuilder methodBuilder =
new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName, entityType, parameterTypes,
parameterNames, bodyBuilder);
methodBuilder.addAnnotation(ANN_METADATA_MODEL_ATTRIBUTE);
return methodBuilder.build();
}
/*
* =========================================================================
* ==========
*/
/**
* This method provides the "list" form method using Thymeleaf view response
* type
*
* @return MethodMetadata
*/
private MethodMetadata getListMethod() {
// Define methodName
final JavaSymbolName methodName = LIST_METHOD_NAME;
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
parameterTypes.add(MODEL_PARAM);
MethodMetadata existingMethod =
getGovernorMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes));
if (existingMethod != null) {
return existingMethod;
}
final List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(MODEL_PARAM_NAME);
// Adding annotations
final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
// Adding @GetMapping annotation
AnnotationMetadataBuilder getMappingAnnotation = new AnnotationMetadataBuilder(GET_MAPPING);
getMappingAnnotation.addStringAttribute("name", methodName.getSymbolName());
annotations.add(getMappingAnnotation);
this.mvcMethodNames.put(methodName.getSymbolName(), methodName.getSymbolName());
// Generate body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
// return new ModelAndView("customers/list");
bodyBuilder.appendFormalLine("return new %s(\"%s/list\");",
getNameOfJavaType(SpringJavaType.MODEL_AND_VIEW), controllerMetadata.getPath());
MethodMetadataBuilder methodBuilder =
new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName,
SpringJavaType.MODEL_AND_VIEW, parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
return methodBuilder.build();
}
/**
* This method provides the "create" form method using Thymeleaf view
* response type
*
* @return MethodMetadata
*/
private MethodMetadata getCreateFormMethod() {
// Define methodName
final JavaSymbolName methodName = CREATE_FORM_METHOD_NAME;
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
parameterTypes.add(MODEL_PARAM);
MethodMetadata existingMethod =
getGovernorMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes));
if (existingMethod != null) {
return existingMethod;
}
final List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(MODEL_PARAM_NAME);
// Adding annotations
final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
// Adding @GetMapping annotation
AnnotationMetadataBuilder getMapping = new AnnotationMetadataBuilder(GET_MAPPING);
getMapping.addStringAttribute("value", "/create-form");
getMapping.addStringAttribute("name", methodName.getSymbolName());
annotations.add(getMapping);
this.mvcMethodNames.put(methodName.getSymbolName(), methodName.getSymbolName());
// Generate body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
// populateForm(model);
bodyBuilder.appendFormalLine("%s(model);", populateFormMethod.getMethodName());
bodyBuilder.newLine();
// model.addAttribute("entity", new Entity());
bodyBuilder.appendFormalLine(String.format("model.addAttribute(\"%s\", new %s());",
StringUtils.uncapitalize(getNameOfJavaType(this.entity)), getNameOfJavaType(this.entity)));
// return "path/create";
bodyBuilder.appendFormalLine("return new %s(\"%s/create\");",
getNameOfJavaType(SpringJavaType.MODEL_AND_VIEW), viewsPath);
MethodMetadataBuilder methodBuilder =
new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName,
SpringJavaType.MODEL_AND_VIEW, parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
return methodBuilder.build();
}
/**
* This method provides the "create" method using Thymeleaf view response
* type
*
* @return MethodMetadata
*/
private MethodMetadata getCreateMethod() {
// Define methodName
final JavaSymbolName methodName = CREATE_METHOD_NAME;
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
parameterTypes.add(new AnnotatedJavaType(this.entity, ANN_METADATA_VALID,
ANN_METADATA_MODEL_ATTRIBUTE));
parameterTypes.add(AnnotatedJavaType.convertFromJavaType(SpringJavaType.BINDING_RESULT));
parameterTypes.add(AnnotatedJavaType.convertFromJavaType(SpringJavaType.MODEL));
MethodMetadata existingMethod =
getGovernorMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes));
if (existingMethod != null) {
return existingMethod;
}
final List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(new JavaSymbolName(entityItemName));
parameterNames.add(new JavaSymbolName("result"));
parameterNames.add(MODEL_PARAM_NAME);
// Adding annotations
final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
// Adding @RequestMapping annotation
AnnotationMetadataBuilder postMappingAnnotation = new AnnotationMetadataBuilder(POST_MAPPING);
postMappingAnnotation.addStringAttribute("name", methodName.getSymbolName());
annotations.add(postMappingAnnotation);
this.mvcMethodNames.put(methodName.getSymbolName(), methodName.getSymbolName());
// Generate body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
// if (result.hasErrors()) {
bodyBuilder.appendFormalLine("if (result.hasErrors()) {");
bodyBuilder.indent();
// populateFormats(model);
bodyBuilder.appendFormalLine("%s(model);", populateFormMethod.getMethodName());
bodyBuilder.newLine();
// return new ModelAndView("customers/create");
bodyBuilder.appendFormalLine("return new %s(\"%s/create\");",
getNameOfJavaType(SpringJavaType.MODEL_AND_VIEW), controllerMetadata.getPath());
bodyBuilder.indentRemove();
// }
bodyBuilder.appendFormalLine("}");
final String newValueVar = "new" + entity.getSimpleTypeName();
// Customer newCustomer = customerService.save(customer);
bodyBuilder.appendFormalLine("%s %s = %s().%s(%s);", getNameOfJavaType(entity), newValueVar,
getAccessorMethod(this.controllerMetadata.getServiceField()).getMethodName(),
serviceMetadata.getCurrentSaveMethod().getMethodName(), entityItemName);
// UriComponents showURI = itemLink.to("show").with("category",
// newCategory.getId()).toUri();
bodyBuilder.appendFormalLine("%s showURI = %s().to(%s.SHOW).with(\"%s\", %s.getId()).toUri();",
getNameOfJavaType(SpringJavaType.URI_COMPONENTS),
getAccessorMethod(this.methodLinkBuilderFactoryField).getMethodName(),
getNameOfJavaType(relatedItemLinkFactory), this.entityItemName, newValueVar);
// return new ModelAndView("redirect:" + showURI.toUriString());
bodyBuilder.appendFormalLine("return new %s(\"redirect:\" + showURI.toUriString());",
getNameOfJavaType(SpringJavaType.MODEL_AND_VIEW));
MethodMetadataBuilder methodBuilder =
new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName,
SpringJavaType.MODEL_AND_VIEW, parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
return methodBuilder.build();
}
/**
* This method provides the "update" method using Thymeleaf view response
* type
*
* @return MethodMetadata
*/
private MethodMetadata getUpdateMethod() {
// Define methodName
final JavaSymbolName methodName = UPDATE_METHOD_NAME;
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
parameterTypes.add(new AnnotatedJavaType(this.entity, ANN_METADATA_VALID,
ANN_METADATA_MODEL_ATTRIBUTE));
// Version parameter
AnnotationMetadataBuilder requestParamAnnotation = new AnnotationMetadataBuilder(REQUEST_PARAM);
requestParamAnnotation.addStringAttribute("value", VERSION_PARAM_NAME.getSymbolName());
parameterTypes.add(new AnnotatedJavaType(this.entityMetadata.getCurrentVersionField()
.getFieldType(), requestParamAnnotation.build()));
// Concurrency control parameter
AnnotationMetadataBuilder concurrencyControlRequestParam =
new AnnotationMetadataBuilder(REQUEST_PARAM);
concurrencyControlRequestParam.addStringAttribute("value", "concurrency");
concurrencyControlRequestParam.addBooleanAttribute("required", false);
concurrencyControlRequestParam.addStringAttribute("defaultValue", "");
parameterTypes.add(new AnnotatedJavaType(JavaType.STRING, concurrencyControlRequestParam
.build()));
parameterTypes.add(new AnnotatedJavaType(SpringJavaType.BINDING_RESULT));
parameterTypes.add(MODEL_PARAM);
MethodMetadata existingMethod =
getGovernorMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes));
if (existingMethod != null) {
return existingMethod;
}
final List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(new JavaSymbolName(entityItemName));
parameterNames.add(this.entityMetadata.getCurrentVersionField().getFieldName());
parameterNames.add(new JavaSymbolName("concurrencyControl"));
parameterNames.add(new JavaSymbolName("result"));
parameterNames.add(MODEL_PARAM_NAME);
// Adding annotations
final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
// Adding @PutMapping annotation
AnnotationMetadataBuilder putMappingAnnotation =
new AnnotationMetadataBuilder(SpringJavaType.PUT_MAPPING);
putMappingAnnotation.addStringAttribute("name", methodName.getSymbolName());
annotations.add(putMappingAnnotation);
this.mvcMethodNames.put(methodName.getSymbolName(), methodName.getSymbolName());
// Generate body
final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
// // Check if provided form contain errors
bodyBuilder.appendFormalLine("// Check if provided form contain errors");
// if (result.hasErrors()) {
bodyBuilder.appendFormalLine("if (result.hasErrors()) {");
bodyBuilder.indent();
// populateFormats(model);
bodyBuilder.appendFormalLine("%s(model);", populateFormMethod.getMethodName());
bodyBuilder.newLine();
// return "path/create";
bodyBuilder.appendFormalLine("return new %s(\"%s/edit\");",
getNameOfJavaType(SpringJavaType.MODEL_AND_VIEW), viewsPath);
bodyBuilder.indentRemove();
// }
bodyBuilder.appendFormalLine("}");
// // Concurrency control
bodyBuilder.appendFormalLine("// Concurrency control");
// Pet existingPet = getPetService().findOne(pet.getId());
String existingVarName = "existing".concat(entity.getSimpleTypeName());
bodyBuilder.appendFormalLine("%s %s = %s().%s(%s.%s());", getNameOfJavaType(entity),
existingVarName, getAccessorMethod(controllerMetadata.getServiceField()).getMethodName(),
serviceMetadata.getCurrentFindOneMethod().getMethodName(), entityItemName,
getAccessorMethod(this.entityMetadata.getCurrentIndentifierField()).getMethodName());
// if(pet.getVersion() != existingPet.getVersion() && StringUtils.isEmpty(concurrencyControl)){
bodyBuilder.appendFormalLine("if(%s.%s() != %s.%s() && %s.isEmpty(concurrencyControl)){",
entityItemName, getAccessorMethod(this.entityMetadata.getCurrentVersionField())
.getMethodName(), existingVarName,
getAccessorMethod(this.entityMetadata.getCurrentVersionField()).getMethodName(),
getNameOfJavaType(new JavaType("org.apache.commons.lang3.StringUtils")));
bodyBuilder.indent();
// populateForm(model);
bodyBuilder.appendFormalLine("populateForm(model);");
// model.addAttribute("entity", entityParam)
bodyBuilder.appendFormalLine("model.addAttribute(\"%s\", %s);", entityItemName, entityItemName);
// model.addAttribute("concurrency", true);
bodyBuilder.appendFormalLine("model.addAttribute(\"concurrency\", true);");
// return new ModelAndView("pets/edit");
bodyBuilder.appendFormalLine("return new %s(\"%s/edit\");",
getNameOfJavaType(SpringJavaType.MODEL_AND_VIEW), viewsPath);
bodyBuilder.indentRemove();
// } else if(pet.getVersion() != existingPet.getVersion() && "discard".equals(concurrencyControl)){
bodyBuilder.appendFormalLine(
"} else if(%s.%s() != %s.%s() && \"discard\".equals(concurrencyControl)){", entityItemName,
getAccessorMethod(this.entityMetadata.getCurrentVersionField()).getMethodName(),
existingVarName, getAccessorMethod(this.entityMetadata.getCurrentVersionField())
.getMethodName());
bodyBuilder.indent();
// populateForm(model);
bodyBuilder.appendFormalLine("populateForm(model);");
// model.addAttribute("pet", existingPet);
bodyBuilder
.appendFormalLine("model.addAttribute(\"%s\", %s);", entityItemName, existingVarName);
// model.addAttribute("concurrency", false);
bodyBuilder.appendFormalLine("model.addAttribute(\"concurrency\", false);");
// return new ModelAndView("pets/edit");
bodyBuilder.appendFormalLine("return new %s(\"%s/edit\");",
getNameOfJavaType(SpringJavaType.MODEL_AND_VIEW), viewsPath);
bodyBuilder.indentRemove();
// } else if(pet.getVersion() != existingPet.getVersion() && "apply".equals(concurrencyControl)){
bodyBuilder.appendFormalLine(
"} else if(%s.%s() != %s.%s() && \"apply\".equals(concurrencyControl)){", entityItemName,
getAccessorMethod(this.entityMetadata.getCurrentVersionField()).getMethodName(),
existingVarName, getAccessorMethod(this.entityMetadata.getCurrentVersionField())
.getMethodName());
bodyBuilder.indent();
// // Update the version field to be able to override the existing values
bodyBuilder
.appendFormalLine("// Update the version field to be able to override the existing values");
// pet.setVersion(existingPet.getVersion());
bodyBuilder.appendFormalLine("%s.%s(%s.%s());", entityItemName,
getMutatorMethod(this.entityMetadata.getCurrentVersionField()).getMethodName(),
existingVarName, getAccessorMethod(this.entityMetadata.getCurrentVersionField())
.getMethodName());
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
String savedVarName = "saved" + entity.getSimpleTypeName();
// Customer savedCustomer = customerService.save(customer);;
bodyBuilder.appendFormalLine("%s %s = %s().%s(%s);", getNameOfJavaType(entity), savedVarName,
getAccessorMethod(controllerMetadata.getServiceField()).getMethodName(), serviceMetadata
.getCurrentSaveMethod().getMethodName(), entityItemName);
// UriComponents showURI =
// itemLink.to(CategoryItemThymeleafLinkFactory.SHOW).with("category",
// savedCategory.getId()).toUri();
bodyBuilder.appendFormalLine("%s showURI = %s().to(%s.SHOW).with(\"%s\", %s.getId()).toUri();",
getNameOfJavaType(SpringJavaType.URI_COMPONENTS),
getAccessorMethod(this.methodLinkBuilderFactoryField).getMethodName(),
getNameOfJavaType(relatedItemLinkFactory), this.entityItemName, savedVarName);
// return new ModelAndView("redirect:" + showURI.toUriString());
bodyBuilder.appendFormalLine("return new %s(\"redirect:\" + showURI.toUriString());",
getNameOfJavaType(SpringJavaType.MODEL_AND_VIEW));
MethodMetadataBuilder methodBuilder =
new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName,
SpringJavaType.MODEL_AND_VIEW, parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
return methodBuilder.build();
}
/**
* This method provides the "update" method using Thymeleaf view response
* type
*
* @return MethodMetadata
*/
private MethodMetadata getUpdateDetailMethod() {
// Define methodName
final JavaSymbolName methodName = UPDATE_METHOD_NAME;
final RelationInfoExtended info = controllerMetadata.getLastDetailsInfo();
final JavaType parentEntity = info.entityType;
final JavaType entity = info.childType;
final String entityItemName = StringUtils.uncapitalize(entity.getSimpleTypeName());
final ServiceMetadata serviceMetadata = controllerMetadata.getServiceMetadataForEntity(entity);
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
parameterTypes.add(new AnnotatedJavaType(parentEntity, ANN_METADATA_MODEL_ATTRIBUTE));
parameterTypes.add(new AnnotatedJavaType(entity, ANN_METADATA_VALID,
ANN_METADATA_MODEL_ATTRIBUTE));
// Version parameter
AnnotationMetadataBuilder requestParamAnnotation = new AnnotationMetadataBuilder(REQUEST_PARAM);
requestParamAnnotation.addStringAttribute("value", VERSION_PARAM_NAME.getSymbolName());
parameterTypes.add(new AnnotatedJavaType(this.entityMetadata.getCurrentVersionField()
.getFieldType(), requestParamAnnotation.build()));
// Concurrency control parameter
AnnotationMetadataBuilder concurrencyControlRequestParam =
new AnnotationMetadataBuilder(REQUEST_PARAM);
concurrencyControlRequestParam.addStringAttribute("value", "concurrency");
concurrencyControlRequestParam.addBooleanAttribute("required", false);
concurrencyControlRequestParam.addStringAttribute("defaultValue", "");
parameterTypes.add(new AnnotatedJavaType(JavaType.STRING, concurrencyControlRequestParam
.build()));
parameterTypes.add(new AnnotatedJavaType(SpringJavaType.BINDING_RESULT));
parameterTypes.add(MODEL_PARAM);
MethodMetadata existingMethod =
getGovernorMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes));
if (existingMethod != null) {
return existingMethod;
}
final List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(new JavaSymbolName(
StringUtils.uncapitalize(parentEntity.getSimpleTypeName())));
parameterNames.add(new JavaSymbolName(entityItemName));
parameterNames.add(this.entityMetadata.getCurrentVersionField().getFieldName());
parameterNames.add(new JavaSymbolName("concurrencyControl"));
parameterNames.add(new JavaSymbolName("result"));
parameterNames.add(MODEL_PARAM_NAME);
// Adding annotations
final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
// Adding @PutMapping annotation
AnnotationMetadataBuilder putMappingAnnotation =
new AnnotationMetadataBuilder(SpringJavaType.PUT_MAPPING);
putMappingAnnotation.addStringAttribute("name", methodName.getSymbolName());
annotations.add(putMappingAnnotation);
this.mvcMethodNames.put(methodName.getSymbolName(), methodName.getSymbolName());
// Generate body
final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
// if (result.hasErrors()) {
bodyBuilder.appendFormalLine("if (result.hasErrors()) {");
bodyBuilder.indent();
// populateFormats(model);
bodyBuilder.appendFormalLine("%s(model);", populateFormMethod.getMethodName());
bodyBuilder.newLine();
// return new ModelAndView("customerorders/details/edit");
bodyBuilder.appendFormalLine("return new %s(\"%s/%s/edit\");",
getNameOfJavaType(SpringJavaType.MODEL_AND_VIEW), viewsPath,
controllerMetadata.getDetailsPathAsString("/"));;
// }
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
// // Concurrency control
bodyBuilder.appendFormalLine("// Concurrency control");
// Pet existingPet = getPetService().findOne(pet.getId());
String existingVarName = "existing".concat(entity.getSimpleTypeName());
bodyBuilder.appendFormalLine("%s %s = %s().%s(%s.%s());", getNameOfJavaType(entity),
existingVarName, getAccessorMethod(controllerMetadata.getLastDetailServiceField())
.getMethodName(), serviceMetadata.getCurrentFindOneMethod().getMethodName(),
entityItemName, getAccessorMethod(this.entityMetadata.getCurrentIndentifierField())
.getMethodName());
// if(pet.getVersion() != existingPet.getVersion() && StringUtils.isEmpty(concurrencyControl)){
bodyBuilder.appendFormalLine("if(%s.%s() != %s.%s() && %s.isEmpty(concurrencyControl)){",
entityItemName, getAccessorMethod(this.entityMetadata.getCurrentVersionField())
.getMethodName(), existingVarName,
getAccessorMethod(this.entityMetadata.getCurrentVersionField()).getMethodName(),
getNameOfJavaType(new JavaType("org.apache.commons.lang3.StringUtils")));
bodyBuilder.indent();
// populateForm(model);
bodyBuilder.appendFormalLine("populateForm(model);");
// model.addAttribute("concurrency", true);
bodyBuilder.appendFormalLine("model.addAttribute(\"concurrency\", true);");
// return new ModelAndView("pets/edit");
bodyBuilder.appendFormalLine("return new %s(\"%s/edit\");",
getNameOfJavaType(SpringJavaType.MODEL_AND_VIEW), viewsPath);
bodyBuilder.indentRemove();
// } else if(pet.getVersion() != existingPet.getVersion() && "discard".equals(concurrencyControl)){
bodyBuilder.appendFormalLine(
"} else if(%s.%s() != %s.%s() && \"discard\".equals(concurrencyControl)){", entityItemName,
getAccessorMethod(this.entityMetadata.getCurrentVersionField()).getMethodName(),
existingVarName, getAccessorMethod(this.entityMetadata.getCurrentVersionField())
.getMethodName());
bodyBuilder.indent();
// populateForm(model);
bodyBuilder.appendFormalLine("populateForm(model);");
// model.addAttribute("pet", existingPet);
bodyBuilder
.appendFormalLine("model.addAttribute(\"%s\", %s);", entityItemName, existingVarName);
// model.addAttribute("concurrency", false);
bodyBuilder.appendFormalLine("model.addAttribute(\"concurrency\", false);");
// return new ModelAndView("pets/edit");
bodyBuilder.appendFormalLine("return new %s(\"%s/edit\");",
getNameOfJavaType(SpringJavaType.MODEL_AND_VIEW), viewsPath);
bodyBuilder.indentRemove();
// } else if(pet.getVersion() != existingPet.getVersion() && "apply".equals(concurrencyControl)){
bodyBuilder.appendFormalLine(
"} else if(%s.%s() != %s.%s() && \"apply\".equals(concurrencyControl)){", entityItemName,
getAccessorMethod(this.entityMetadata.getCurrentVersionField()).getMethodName(),
existingVarName, getAccessorMethod(this.entityMetadata.getCurrentVersionField())
.getMethodName());
bodyBuilder.indent();
// // Update the version field to be able to override the existing values
bodyBuilder
.appendFormalLine("// Update the version field to be able to override the existing values");
// pet.setVersion(existingPet.getVersion());
bodyBuilder.appendFormalLine("%s.%s(%s.%s());", entityItemName,
getMutatorMethod(this.entityMetadata.getCurrentVersionField()).getMethodName(),
existingVarName, getAccessorMethod(this.entityMetadata.getCurrentVersionField())
.getMethodName());
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
// Customer savedCustomer = customerService.save(customer);
bodyBuilder.appendFormalLine("%s().%s(%s);",
getAccessorMethod(controllerMetadata.getLastDetailServiceField()).getMethodName(),
serviceMetadata.getCurrentSaveMethod().getMethodName(), entityItemName);
// return new ModelAndView("redirect:" +
// collectionLink.to("list").toUriString());
bodyBuilder.appendFormalLine("return new %s(\"redirect:\" + %s().to(%s.LIST).toUriString());",
getNameOfJavaType(SpringJavaType.MODEL_AND_VIEW),
getAccessorMethod(this.methodLinkBuilderFactoryField).getMethodName(),
getNameOfJavaType(relatedCollectionLinkFactory));
MethodMetadataBuilder methodBuilder =
new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName,
SpringJavaType.MODEL_AND_VIEW, parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
return methodBuilder.build();
}
/**
* This method provides the "delete" method using Thymeleaf view response
* type
*
* @return MethodMetadata
*/
private MethodMetadata getDeleteMethod() {
// Define methodName
final JavaSymbolName methodName = DELETE_METHOD_NAME;
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
parameterTypes.add(new AnnotatedJavaType(this.entity, ANN_METADATA_MODEL_ATTRIBUTE));
MethodMetadata existingMethod =
getGovernorMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes));
if (existingMethod != null) {
return existingMethod;
}
final List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(new JavaSymbolName(entityItemName));
// Adding annotations
final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
// Adding @RequestMapping annotation
AnnotationMetadataBuilder deleteMapping = new AnnotationMetadataBuilder(DELETE_MAPPING);
deleteMapping.addStringAttribute("name", methodName.getSymbolName());
annotations.add(RESPONSE_BODY_ANNOTATION);
annotations.add(deleteMapping);
this.mvcMethodNames.put(methodName.getSymbolName(), methodName.getSymbolName());
// Generate body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
// customerService.delete(customer);
bodyBuilder.appendFormalLine("%s().%s(%s);",
getAccessorMethod(controllerMetadata.getServiceField()).getMethodName(), serviceMetadata
.getCurrentDeleteMethod().getMethodName(), entityItemName);
// return ResponseEntity.ok().build();
bodyBuilder.appendFormalLine("return %s.ok().build();", getNameOfJavaType(RESPONSE_ENTITY));
MethodMetadataBuilder methodBuilder =
new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName,
JavaType.wrapperWilcard(RESPONSE_ENTITY), parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
return methodBuilder.build();
}
/**
* This method provides the "deleteBatch" method using Thymeleaf view
* response type. This method will be only created if it not exists in
* collection JSON controller.
*
* @return MethodMetadata
*/
private MethodMetadata getDeleteBatchMethod() {
// Define methodName
final JavaSymbolName methodName = DELETE_BATCH_METHOD_NAME;
// Adding parameter types
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
AnnotationMetadataBuilder pathVariable =
new AnnotationMetadataBuilder(SpringJavaType.PATH_VARIABLE);
pathVariable.addStringAttribute("value", entityIdentifierPlural);
parameterTypes.add(new AnnotatedJavaType(JavaType.collectionOf(entityMetadata
.getCurrentIndentifierField().getFieldType()), pathVariable.build()));
MethodMetadata existingMethod =
getGovernorMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes));
if (existingMethod != null) {
return existingMethod;
}
// Adding parameter names
final List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(new JavaSymbolName(entityIdentifierPlural));
// Adding annotations
final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
// Adding @DeleteMapping annotation
AnnotationMetadataBuilder deleteMappingAnnotation =
new AnnotationMetadataBuilder(DELETE_MAPPING);
deleteMappingAnnotation.addStringAttribute("value", "/batch/{" + entityIdentifierPlural + "}");
deleteMappingAnnotation.addStringAttribute("name", methodName.getSymbolName());
annotations.add(deleteMappingAnnotation);
// Adding @ResponseBody annotation
AnnotationMetadataBuilder responseBodyAnnotation =
new AnnotationMetadataBuilder(SpringJavaType.RESPONSE_BODY);
annotations.add(responseBodyAnnotation);
// Generate body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
// serviceField.SERVICE_DELETE_METHOD(ids);
bodyBuilder.newLine();
bodyBuilder.appendFormalLine("%s().%s(%s);",
getAccessorMethod(this.controllerMetadata.getServiceField()).getMethodName(),
serviceMetadata.getCurrentDeleteBatchMethod().getMethodName(), entityIdentifierPlural);
// return ResponseEntity.ok().build();
bodyBuilder.newLine();
bodyBuilder.appendFormalLine("return %s.ok().build();", getNameOfJavaType(RESPONSE_ENTITY));
MethodMetadataBuilder methodBuilder =
new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName,
JavaType.wrapperWilcard(RESPONSE_ENTITY), parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
return methodBuilder.build();
}
/**
* This method provides a finder method using THYMELEAF response type
*
* @param finderMethod
*
* @return MethodMetadata
*/
private MethodMetadata getFinderMethod(MethodMetadata finderMethod) {
// TODO
return null;
/*
* final List<AnnotatedJavaType> originalParameterTypes =
* finderMethod.getParameterTypes();
*
* // Get finder parameter names final List<JavaSymbolName>
* originalParameterNames = finderMethod.getParameterNames();
* List<String> stringParameterNames = new ArrayList<String>(); for
* (JavaSymbolName parameterName : originalParameterNames) {
* stringParameterNames.add(parameterName.getSymbolName()); }
*
* // Define methodName final JavaSymbolName methodName =
* finderMethod.getMethodName();
*
* // Define path String path = ""; if
* (StringUtils.startsWith(methodName.getSymbolName(), "count")) { path
* = StringUtils.removeStart(methodName.getSymbolName(), "count"); }
* else if (StringUtils.startsWith(methodName.getSymbolName(), "find"))
* { path = StringUtils.removeStart(methodName.getSymbolName(), "find");
* } else if (StringUtils.startsWith(methodName.getSymbolName(),
* "query")) { path =
* StringUtils.removeStart(methodName.getSymbolName(), "query"); } else
* if (StringUtils.startsWith(methodName.getSymbolName(), "read")) {
* path = StringUtils.removeStart(methodName.getSymbolName(), "read"); }
* else { path = methodName.getSymbolName(); } path =
* StringUtils.uncapitalize(path);
*
* // Check if exists other method with the same @RequesMapping to
* generate MethodMetadata existingMVCMethod =
* getControllerMVCService().getMVCMethodByRequestMapping(
* controller.getType(), SpringEnumDetails.REQUEST_METHOD_GET, "/" +
* path, stringParameterNames, null, "application/vnd.datatables+json",
* ""); if (existingMVCMethod != null &&
* !existingMVCMethod.getDeclaredByMetadataId().equals(this.
* metadataIdentificationString)) { return existingMVCMethod; }
*
* // Get parameters List<AnnotatedJavaType> parameterTypes = new
* ArrayList<AnnotatedJavaType>(); List<JavaSymbolName> parameterNames =
* new ArrayList<JavaSymbolName>(); StringBuffer finderParamsString =
* new StringBuffer(); for (int i = 0; i <
* originalParameterTypes.size(); i++) {
*
* // Add @ModelAttribute for search param if (i == 0) {
* AnnotationMetadataBuilder requestParamAnnotation = new
* AnnotationMetadataBuilder(SpringJavaType.MODEL_ATTRIBUTE);
* requestParamAnnotation.addStringAttribute("value",
* originalParameterNames.get(i).getSymbolName());
* parameterTypes.add(new
* AnnotatedJavaType(originalParameterTypes.get(i).getJavaType(),
* requestParamAnnotation.build()));
* parameterNames.add(originalParameterNames.get(i));
* finderParamsString.append(originalParameterNames.get(i).getSymbolName
* ()); } else if (originalParameterTypes.get(i).getJavaType()
* .equals(SpringletsJavaType.SPRINGLETS_GLOBAL_SEARCH)) {
* parameterTypes.add(originalParameterTypes.get(i));
* addTypeToImport(originalParameterTypes.get(i).getJavaType());
* parameterNames.add(originalParameterNames.get(i));
*
* // Build finder parameters String
* finderParamsString.append(", ".concat(originalParameterNames.get(i).
* getSymbolName())); } }
*
* // Add DatatablesPageable param parameterTypes
* .add(AnnotatedJavaType.convertFromJavaType(addTypeToImport(this.
* datatablesPageable))); parameterNames.add(new
* JavaSymbolName("pageable")); finderParamsString.append(", pageable");
*
* // Add additional 'draw' param AnnotationMetadataBuilder
* requestParamAnnotation = new
* AnnotationMetadataBuilder(addTypeToImport(SpringJavaType.
* REQUEST_PARAM)); requestParamAnnotation.addStringAttribute("value",
* "draw"); parameterTypes.add(new
* AnnotatedJavaType(JavaType.INT_OBJECT,
* requestParamAnnotation.build())); parameterNames.add(new
* JavaSymbolName("draw"));
*
* // Adding annotations final List<AnnotationMetadataBuilder>
* annotations = new ArrayList<AnnotationMetadataBuilder>();
*
* // Adding @RequestMapping annotation annotations.add(
* getControllerMVCService().getRequestMappingAnnotation(
* SpringEnumDetails.REQUEST_METHOD_GET, "/" + path,
* stringParameterNames, null, "application/vnd.datatables+json", ""));
*
* // Adding @ResponseBody annotation AnnotationMetadataBuilder
* responseBodyAnnotation = new
* AnnotationMetadataBuilder(SpringJavaType.RESPONSE_BODY);
* annotations.add(responseBodyAnnotation);
*
* // Generate body InvocableMemberBodyBuilder bodyBuilder = new
* InvocableMemberBodyBuilder();
*
* // Generating returnType JavaType returnType =
* finderMethod.getReturnType(); List<JavaType> returnParameterTypes =
* returnType.getParameters(); StringBuffer returnTypeParamsString = new
* StringBuffer(); for (int i = 0; i < returnParameterTypes.size(); i++)
* { addTypeToImport(returnParameterTypes.get(i)); if (i > 0) {
* returnTypeParamsString.append(","); }
* returnTypeParamsString.append(returnParameterTypes.get(i).
* getSimpleTypeName());
*
* // Add module dependency
* getTypeLocationService().addModuleDependency(this.controller.getType(
* ).getModule(), returnParameterTypes.get(i)); }
*
* // ReturnType<ReturnTypeParams> entity = //
* ENTITY_SERVICE_FIELD.FINDER_NAME(SEARCH_PARAMS); String
* returnParameterName =
* StringUtils.uncapitalize(returnParameterTypes.get(0).
* getSimpleTypeName()); bodyBuilder.newLine(); if
* (StringUtils.isEmpty(returnTypeParamsString)) {
* bodyBuilder.appendFormalLine(String.format("%s %s = %s.%s(%s);",
* addTypeToImport(returnType).getSimpleTypeName(), returnParameterName,
* getServiceField().getFieldName(), methodName, finderParamsString)); }
* else {
* bodyBuilder.appendFormalLine(String.format("%s<%s> %s = %s.%s(%s);",
* addTypeToImport(returnType).getSimpleTypeName(),
* returnTypeParamsString, returnParameterName,
* getServiceField().getFieldName(), methodName, finderParamsString)); }
*
* // long allAvailableEntity/Projection = //
* ENTITY_SERVICE_FIELD.COUNT_METHOD(formBean); bodyBuilder.newLine();
* bodyBuilder.appendFormalLine(String.
* format("long allAvailable%s = %s.%s(%s);",
* StringUtils.capitalize(Noun.pluralOf(returnParameterName,
* Locale.ENGLISH)), getServiceField().getFieldName(),
* "count".concat(StringUtils.capitalize(path)),
* parameterNames.get(0))); bodyBuilder.newLine();
*
* // return new DatatablesData<Entity/Projection>(entity/projection, //
* allAvailableEntity/Projection, draw);
* bodyBuilder.appendFormalLine(String.
* format("return new %s<%s>(%s, allAvailable%s, draw);",
* addTypeToImport(this.datatablesDataType).getSimpleTypeName(),
* returnTypeParamsString, returnParameterName,
* StringUtils.capitalize(Noun.pluralOf(returnParameterName,
* Locale.ENGLISH))));
*
* MethodMetadataBuilder methodBuilder = new
* MethodMetadataBuilder(this.metadataIdentificationString,
* Modifier.PUBLIC, methodName, addTypeToImport(new
* JavaType(this.datatablesDataType.getFullyQualifiedTypeName(), 0,
* DataType.TYPE, null, returnParameterTypes)), parameterTypes,
* parameterNames, bodyBuilder);
* methodBuilder.setAnnotations(annotations);
*
* return methodBuilder.build();
*/
}
/**
* This method provides a finder redirect method using THYMELEAF response
* type
*
* @param finderMethod
* @return
*/
private MethodMetadata getFinderRedirectMethod(MethodMetadata finderMethod) {
// TODO
return null;
/*
*
* // Get finder parameter names final List<JavaSymbolName>
* originalParameterNames = finderMethod.getParameterNames();
* List<String> stringParameterNames = new ArrayList<String>(); for
* (JavaSymbolName parameterName : originalParameterNames) {
* stringParameterNames.add(parameterName.getSymbolName()); }
*
* // Define methodName final JavaSymbolName methodName = new
* JavaSymbolName(finderMethod.getMethodName().getSymbolName().concat(
* "Redirect"));
*
* // Define path String path = ""; if
* (StringUtils.startsWith(methodName.getSymbolName(), "count")) { path
* = StringUtils.removeStart(methodName.getSymbolName(), "count"); }
* else if (StringUtils.startsWith(methodName.getSymbolName(), "find"))
* { path = StringUtils.removeStart(methodName.getSymbolName(), "find");
* } else if (StringUtils.startsWith(methodName.getSymbolName(),
* "query")) { path =
* StringUtils.removeStart(methodName.getSymbolName(), "query"); } else
* if (StringUtils.startsWith(methodName.getSymbolName(), "read")) {
* path = StringUtils.removeStart(methodName.getSymbolName(), "read"); }
* else { path = methodName.getSymbolName(); } path =
* StringUtils.uncapitalize(StringUtils.removeEnd(path, "Redirect"));
*
* // Check if exists other method with the same @RequesMapping to
* generate MethodMetadata existingMVCMethod =
* getControllerMVCService().getMVCMethodByRequestMapping(
* controller.getType(), SpringEnumDetails.REQUEST_METHOD_POST, "/" +
* path, stringParameterNames, null,
* SpringEnumDetails.MEDIA_TYPE_TEXT_HTML_VALUE.toString(), ""); if
* (existingMVCMethod != null &&
* !existingMVCMethod.getDeclaredByMetadataId().equals(this.
* metadataIdentificationString)) { return existingMVCMethod; }
*
* // Get parameters List<AnnotatedJavaType> parameterTypes = new
* ArrayList<AnnotatedJavaType>(); List<JavaSymbolName> parameterNames =
* new ArrayList<JavaSymbolName>();
*
* // Check if finder parameter is a DTO JavaType formBean =
* finderMethod.getParameterTypes().get(0).getJavaType(); if
* (getTypeLocationService().getTypeDetails(formBean) != null &&
* getTypeLocationService()
* .getTypeDetails(formBean).getAnnotation(RooJavaType.ROO_DTO) == null)
* {
*
* // Finder parameter are entity fields formBean = this.entity; }
*
* // Add form bean parameter AnnotationMetadataBuilder
* modelAttributeAnnotation = new
* AnnotationMetadataBuilder(SpringJavaType.MODEL_ATTRIBUTE);
* modelAttributeAnnotation.addStringAttribute("value", "formBean");
* parameterTypes.add(new AnnotatedJavaType(formBean,
* modelAttributeAnnotation.build())); parameterNames.add(new
* JavaSymbolName("formBean"));
*
* // Add redirect parameter parameterTypes.add(
* AnnotatedJavaType.convertFromJavaType(addTypeToImport(SpringJavaType.
* REDIRECT_ATTRIBUTES))); parameterNames.add(new
* JavaSymbolName("redirect"));
*
* // Adding annotations final List<AnnotationMetadataBuilder>
* annotations = new ArrayList<AnnotationMetadataBuilder>();
*
* // Adding @RequestMapping annotation
* annotations.add(getControllerMVCService().
* getRequestMappingAnnotation( SpringEnumDetails.REQUEST_METHOD_POST,
* "/" + path, stringParameterNames, null,
* SpringEnumDetails.MEDIA_TYPE_TEXT_HTML_VALUE, ""));
*
* // Generate body InvocableMemberBodyBuilder bodyBuilder = new
* InvocableMemberBodyBuilder(); bodyBuilder.newLine();
*
* // redirect.addFlashAttribute(entity/dtoSearch);
* bodyBuilder.appendFormalLine(
* String.format("redirect.addFlashAttribute(\"formBean\", %s);",
* parameterNames.get(0))); bodyBuilder.newLine();
*
* // return "redirect:PATH_PREFIX/ENTITY_PLURAL/FINDER_NAME";
* bodyBuilder.appendFormalLine(String.
* format("return \"redirect:%s/%s/search/%s\";", this.pathPrefix,
* this.entityPlural, path));
*
* MethodMetadataBuilder methodBuilder = new
* MethodMetadataBuilder(this.metadataIdentificationString,
* Modifier.PUBLIC, methodName, JavaType.STRING, parameterTypes,
* parameterNames, bodyBuilder);
* methodBuilder.setAnnotations(annotations);
*
* return methodBuilder.build();
*/
}
/**
* This method provides a finder form method using THYMELEAF response type
*
* @param finderMethod
* @return
*/
private MethodMetadata getFinderFormMethod(MethodMetadata finderMethod) {
// TODO
return null;
/*
*
* // Get finder parameter names List<String> stringParameterNames = new
* ArrayList<String>(); stringParameterNames.add("model");
*
* // Define methodName final JavaSymbolName methodName = new
* JavaSymbolName(finderMethod.getMethodName().getSymbolName().concat(
* "Form"));
*
* // Define path String path = ""; if
* (StringUtils.startsWith(finderMethod.getMethodName().getSymbolName(),
* "count")) { path =
* StringUtils.removeStart(finderMethod.getMethodName().getSymbolName(),
* "count"); } else if
* (StringUtils.startsWith(finderMethod.getMethodName().getSymbolName(),
* "find")) { path =
* StringUtils.removeStart(finderMethod.getMethodName().getSymbolName(),
* "find"); } else if
* (StringUtils.startsWith(finderMethod.getMethodName().getSymbolName(),
* "query")) { path =
* StringUtils.removeStart(finderMethod.getMethodName().getSymbolName(),
* "query"); } else if
* (StringUtils.startsWith(finderMethod.getMethodName().getSymbolName(),
* "read")) { path =
* StringUtils.removeStart(finderMethod.getMethodName().getSymbolName(),
* "read"); } else { path = methodName.getSymbolName(); } path =
* StringUtils.uncapitalize(path).concat("/search-form");
*
* // Check if exists other method with the same @RequesMapping to
* generate MethodMetadata existingMVCMethod =
* getControllerMVCService().getMVCMethodByRequestMapping(
* controller.getType(), SpringEnumDetails.REQUEST_METHOD_GET, "/" +
* path, stringParameterNames, null,
* SpringEnumDetails.MEDIA_TYPE_TEXT_HTML_VALUE.toString(), ""); if
* (existingMVCMethod != null &&
* !existingMVCMethod.getDeclaredByMetadataId().equals(this.
* metadataIdentificationString)) { return existingMVCMethod; }
*
* // Get parameters List<AnnotatedJavaType> parameterTypes = new
* ArrayList<AnnotatedJavaType>(); List<JavaSymbolName> parameterNames =
* new ArrayList<JavaSymbolName>();
*
* // Add model parameter parameterTypes
* .add(AnnotatedJavaType.convertFromJavaType(addTypeToImport(
* SpringJavaType.MODEL))); parameterNames.add(new
* JavaSymbolName("model"));
*
* // Adding annotations final List<AnnotationMetadataBuilder>
* annotations = new ArrayList<AnnotationMetadataBuilder>();
*
* // Adding @RequestMapping annotation
* annotations.add(getControllerMVCService().
* getRequestMappingAnnotation( SpringEnumDetails.REQUEST_METHOD_GET,
* "/" + path, stringParameterNames, null,
* SpringEnumDetails.MEDIA_TYPE_TEXT_HTML_VALUE, ""));
*
* // Check if finder parameter is a DTO JavaType formBean =
* finderMethod.getParameterTypes().get(0).getJavaType(); if
* (getTypeLocationService().getTypeDetails(formBean) != null &&
* getTypeLocationService()
* .getTypeDetails(formBean).getAnnotation(RooJavaType.ROO_DTO) == null)
* {
*
* // Finder parameter are entity fields formBean = this.entity; }
*
* // Generate body InvocableMemberBodyBuilder bodyBuilder = new
* InvocableMemberBodyBuilder(); bodyBuilder.newLine();
*
* // Entity/DTO search = new Entity/DTO();
* bodyBuilder.appendFormalLine(String.format("%1$s %2$s = new %1$s();",
* addTypeToImport(formBean).getSimpleTypeName(), "formBean"));
* bodyBuilder.newLine();
*
* // model.addAttribute("search", search);
* bodyBuilder.appendFormalLine(String.
* format("model.addAttribute(\"%1$s\", %1$s);", "formBean"));
* bodyBuilder.newLine();
*
* // populateForm(model);
* bodyBuilder.appendFormalLine("populateForm(model);");
* bodyBuilder.newLine();
*
* // return "PATH_PREFIX/ENTITY_PLURAL/FINDER_NAMEForm"; String
* pathPrefix = ""; if (StringUtils.isBlank(this.pathPrefix)) {
* pathPrefix = this.pathPrefix; } else { pathPrefix =
* this.pathPrefix.concat("/"); }
* bodyBuilder.appendFormalLine(String.format("return \"%s%s/%s\";",
* StringUtils.removeStart(pathPrefix, "/"), this.entityPlural,
* methodName.getSymbolName()));
*
* MethodMetadataBuilder methodBuilder = new
* MethodMetadataBuilder(this.metadataIdentificationString,
* Modifier.PUBLIC, methodName, JavaType.STRING, parameterTypes,
* parameterNames, bodyBuilder);
* methodBuilder.setAnnotations(annotations);
*
* return methodBuilder.build();
*/
}
/**
* This method provides populateFormats method that allows to configure date
* time format for every entity
*
* @return
*/
private MethodMetadata getPopulateFormatsMethod() {
// Define methodName
final JavaSymbolName methodName = new JavaSymbolName("populateFormats");
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
parameterTypes.add(AnnotatedJavaType.convertFromJavaType(SpringJavaType.MODEL));
MethodMetadata existingMethod =
getGovernorMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes));
if (existingMethod != null) {
return existingMethod;
}
final List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(MODEL_PARAM_NAME);
// Adding annotations
final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
// Generate body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
buildPopulateFormatBody(bodyBuilder, dateTimeFields);
MethodMetadataBuilder methodBuilder =
new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName, JavaType.VOID_PRIMITIVE,
parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
return methodBuilder.build();
}
/**
* Build method body which populate in model all required formats for a form
* based on dateTimeField of a type.
*
* Also populate current locale in model.
*
* @param bodyBuilder
* @param dateTimeFields
* dateTime fields (optional could be empty or null)
*/
private void buildPopulateFormatBody(InvocableMemberBodyBuilder bodyBuilder,
List<FieldMetadata> dateTimeFields) {
// Always save locale
bodyBuilder.appendFormalLine(
"model.addAttribute(\"application_locale\", %s.getLocale().getLanguage());",
getNameOfJavaType(SpringJavaType.LOCALE_CONTEXT_HOLDER));
if (dateTimeFields == null || dateTimeFields.isEmpty()) {
// All done;
return;
}
// Getting all enum types from provided entity
for (FieldMetadata field : dateTimeFields) {
// Getting annotation format
AnnotationMetadata dateTimeFormatAnnotation =
field.getAnnotation(SpringJavaType.DATE_TIME_FORMAT);
if (dateTimeFormatAnnotation != null
&& (dateTimeFormatAnnotation.getAttribute("style") != null || dateTimeFormatAnnotation
.getAttribute("pattern") != null)) {
AnnotationAttributeValue<String> formatAttr =
dateTimeFormatAnnotation.getAttribute("style");
if (formatAttr != null) {
String format = formatAttr.getValue();
// model.addAttribute("field_date_format",
// DateTimeFormat.patternForStyle("M-",
// LocaleContextHolder.getLocale()));
bodyBuilder
.appendFormalLine(
"model.addAttribute(\"%s_date_format\", %s.patternForStyle(\"%s\", %s.getLocale()));",
field.getFieldName(), getNameOfJavaType(JODA_DATETIME_FORMAT_JAVA_TYPE), format,
getNameOfJavaType(SpringJavaType.LOCALE_CONTEXT_HOLDER));
} else {
formatAttr = dateTimeFormatAnnotation.getAttribute("pattern");
String format = formatAttr.getValue();
// model.addAttribute("field_date_format", "pattern");
bodyBuilder.appendFormalLine(String.format(
"model.addAttribute(\"%s_date_format\", \"%s\");", field.getFieldName(), format));
}
}
}
}
/**
* This method provides the "list" Datatables JSON method using JSON
* response type and returns Datatables element
*
* @return MethodMetadata
*/
private MethodMetadata getListDatatablesMethod() {
// Define methodName
final JavaSymbolName methodName = LIST_DATATABLES_METHOD_NAME;
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
parameterTypes.add(DATATABLES_COLUMNS_PARAM);
parameterTypes.add(GLOBAL_SEARCH_PARAM);
parameterTypes.add(DATATABLES_PAGEABLE_PARAM);
AnnotationMetadataBuilder requestParamAnnotation = new AnnotationMetadataBuilder(REQUEST_PARAM);
requestParamAnnotation.addStringAttribute("value", "draw");
parameterTypes.add(new AnnotatedJavaType(JavaType.INT_OBJECT, requestParamAnnotation.build()));
MethodMetadata existingMethod =
getGovernorMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes));
if (existingMethod != null) {
return existingMethod;
}
final List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(DATATABLES_COLUMNS_PARAM_NAME);
parameterNames.add(new JavaSymbolName("search"));
parameterNames.add(new JavaSymbolName("pageable"));
parameterNames.add(new JavaSymbolName("draw"));
// Adding annotations
final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
// Adding @GetMapping annotation
final AnnotationMetadataBuilder getMappingAnnotation =
new AnnotationMetadataBuilder(GET_MAPPING);
getMappingAnnotation.addEnumAttribute("produces", SPRINGLETS_DATATABLES, "MEDIA_TYPE");
getMappingAnnotation.addStringAttribute("name", methodName.getSymbolName());
getMappingAnnotation.addStringAttribute("value", "/dt");
annotations.add(getMappingAnnotation);
this.mvcMethodNames.put(methodName.getSymbolName(), methodName.getSymbolName());
// Adding @ResponseBody annotation
annotations.add(RESPONSE_BODY_ANNOTATION);
// Generate body
final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
final String itemNames = StringUtils.uncapitalize(this.entityPlural);
// Getting the findAllMethod
MethodMetadata findAllMethod = this.serviceMetadata.getCurrentFindAllWithGlobalSearchMethod();
// Getting the findAll return type
JavaType defaultReturnType = findAllMethod.getReturnType().getParameters().get(0);
// Page<Customer> customers = customerService.findAll(search, pageable);
bodyBuilder.appendFormalLine("%s<%s> %s = %s().%s(search, pageable);",
getNameOfJavaType(SpringJavaType.PAGE), getNameOfJavaType(defaultReturnType), itemNames,
getAccessorMethod(this.controllerMetadata.getServiceField()).getMethodName(),
findAllMethod.getMethodName());
final String totalVarName = "total" + StringUtils.capitalize(this.entityPlural) + "Count";
// long totalCustomersCount = customers.getTotalElements();
bodyBuilder.appendFormalLine("long %s = %s.getTotalElements();", totalVarName, itemNames);
// if (search != null && StringUtils.hasText(search.getText())) {
// totalCustomersCount = customerService.count();
// }
bodyBuilder.appendFormalLine("if (search != null && %s.isNotBlank(search.getText())) {",
getNameOfJavaType(STRING_UTILS_APACHE));
bodyBuilder.indent();
bodyBuilder.appendFormalLine("%s = %s().%s();", totalVarName,
getAccessorMethod(this.controllerMetadata.getServiceField()).getMethodName(),
serviceMetadata.getCurrentCountMethod().getMethodName());
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
// ConvertedDatatablesData<Owner> datatablesData = new
// ConvertedDatatablesData<Owner>(owners,
// totalOwnersCount, draw, conversionService, columns);
bodyBuilder.appendFormalLine(
"%1$s<%2$s> datatablesData = new %1$s<%2$s>(%3$s, %4$s, draw, %5$s(), %6$s);",
getNameOfJavaType(SpringletsJavaType.SPRINGLETS_CONVERTED_DATATABLES_DATA),
getNameOfJavaType(defaultReturnType), itemNames, totalVarName,
getAccessorMethod(this.conversionServiceField).getMethodName(),
DATATABLES_COLUMNS_PARAM_NAME);
// return ResponseEntity.ok(datatablesData);
bodyBuilder.appendFormalLine("return %s.ok(datatablesData);",
getNameOfJavaType(RESPONSE_ENTITY));
// Generating returnType
JavaType returnType =
JavaType.wrapperOf(RESPONSE_ENTITY, JavaType.wrapperOf(
SpringletsJavaType.SPRINGLETS_CONVERTED_DATATABLES_DATA, defaultReturnType));
MethodMetadataBuilder methodBuilder =
new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName, returnType, parameterTypes,
parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
return methodBuilder.build();
}
/**
* This method provides the "list" Datatables JSON method using JSON
* response type and returns Datatables element
*
* @return MethodMetadata
*/
private MethodMetadata getListDatatablesByIdsInMethod() {
// Define methodName
final JavaSymbolName methodName = LIST_DATATABLES_BY_IDS_IN_METHOD_NAME;
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
AnnotationMetadataBuilder requestParamIdsAnnotation =
new AnnotationMetadataBuilder(REQUEST_PARAM);
requestParamIdsAnnotation.addStringAttribute("value", "ids");
parameterTypes.add(new AnnotatedJavaType(JavaType.wrapperOf(JavaType.LIST, entityMetadata
.getCurrentIndentifierField().getFieldType()), requestParamIdsAnnotation.build()));
parameterTypes.add(DATATABLES_COLUMNS_PARAM);
parameterTypes.add(GLOBAL_SEARCH_PARAM);
parameterTypes.add(DATATABLES_PAGEABLE_PARAM);
AnnotationMetadataBuilder requestParamAnnotation = new AnnotationMetadataBuilder(REQUEST_PARAM);
requestParamAnnotation.addStringAttribute("value", "draw");
parameterTypes.add(new AnnotatedJavaType(JavaType.INT_OBJECT, requestParamAnnotation.build()));
MethodMetadata existingMethod =
getGovernorMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes));
if (existingMethod != null) {
return existingMethod;
}
final List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(new JavaSymbolName("ids"));
parameterNames.add(DATATABLES_COLUMNS_PARAM_NAME);
parameterNames.add(new JavaSymbolName("search"));
parameterNames.add(new JavaSymbolName("pageable"));
parameterNames.add(new JavaSymbolName("draw"));
// Adding annotations
final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
// Adding @GetMapping annotation
final AnnotationMetadataBuilder getMappingAnnotation =
new AnnotationMetadataBuilder(GET_MAPPING);
getMappingAnnotation.addEnumAttribute("produces", SPRINGLETS_DATATABLES, "MEDIA_TYPE");
getMappingAnnotation.addStringAttribute("name", methodName.getSymbolName());
getMappingAnnotation.addStringAttribute("value", "/dtByIdsIn");
annotations.add(getMappingAnnotation);
this.mvcMethodNames.put(methodName.getSymbolName(), methodName.getSymbolName());
// Adding @ResponseBody annotation
annotations.add(RESPONSE_BODY_ANNOTATION);
// Generate body
final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
final String itemNames = StringUtils.uncapitalize(this.entityPlural);
// Getting the findAllMethod
MethodMetadata findAllMethod =
this.serviceMetadata.getCurrentFindAllByIdsInWithGlobalSearchMethod();
// Getting the findAll return type
JavaType defaultReturnType = findAllMethod.getReturnType().getParameters().get(0);
// Page<Customer> customers = customerService.findAllByIdsIn(ids, search, pageable);
bodyBuilder.appendFormalLine("%s<%s> %s = %s().%s(ids, search, pageable);",
getNameOfJavaType(SpringJavaType.PAGE), getNameOfJavaType(defaultReturnType), itemNames,
getAccessorMethod(this.controllerMetadata.getServiceField()).getMethodName(),
findAllMethod.getMethodName());
final String totalVarName = "total" + StringUtils.capitalize(this.entityPlural) + "Count";
// long totalCustomersCount = customers.getTotalElements();
bodyBuilder.appendFormalLine("long %s = %s.getTotalElements();", totalVarName, itemNames);
// if (search != null && StringUtils.hasText(search.getText())) {
// totalCustomersCount = customerService.count();
// }
bodyBuilder.appendFormalLine("if (search != null && %s.isNotBlank(search.getText())) {",
getNameOfJavaType(STRING_UTILS_APACHE));
bodyBuilder.indent();
bodyBuilder.appendFormalLine("%s = %s().%s();", totalVarName,
getAccessorMethod(this.controllerMetadata.getServiceField()).getMethodName(),
serviceMetadata.getCurrentCountMethod().getMethodName());
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
// ConvertedDatatablesData<Owner> datatablesData = new
// ConvertedDatatablesData<Owner>(owners,
// totalOwnersCount, draw, conversionService, columns);
bodyBuilder.appendFormalLine(
"%1$s<%2$s> datatablesData = new %1$s<%2$s>(%3$s, %4$s, draw, %5$s(), %6$s);",
getNameOfJavaType(SpringletsJavaType.SPRINGLETS_CONVERTED_DATATABLES_DATA),
getNameOfJavaType(defaultReturnType), itemNames, totalVarName,
getAccessorMethod(this.conversionServiceField).getMethodName(),
DATATABLES_COLUMNS_PARAM_NAME);
// return ResponseEntity.ok(datatablesData);
bodyBuilder.appendFormalLine("return %s.ok(datatablesData);",
getNameOfJavaType(RESPONSE_ENTITY));
// Generating returnType
JavaType returnType =
JavaType.wrapperOf(RESPONSE_ENTITY, JavaType.wrapperOf(
SpringletsJavaType.SPRINGLETS_CONVERTED_DATATABLES_DATA, defaultReturnType));
MethodMetadataBuilder methodBuilder =
new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName, returnType, parameterTypes,
parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
return methodBuilder.build();
}
/**
* This method provides the "select2" Select2 JSON method using JSON
* response type and returns Select2Data element
*
* @return MethodMetadata
*/
private MethodMetadata getSelect2Method() {
// Define methodName
final JavaSymbolName methodName = SELECT2_METHOD_NAME;
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
parameterTypes.add(GLOBAL_SEARCH_PARAM);
parameterTypes.add(PAGEABLE_PARAM);
parameterTypes.add(LOCALE_PARAM);
MethodMetadata existingMethod =
getGovernorMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes));
if (existingMethod != null) {
return existingMethod;
}
final List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(new JavaSymbolName("search"));
parameterNames.add(new JavaSymbolName("pageable"));
parameterNames.add(new JavaSymbolName("locale"));
// Adding annotations
final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
// Adding @GetMapping annotation
final AnnotationMetadataBuilder getMappingAnnotation =
new AnnotationMetadataBuilder(GET_MAPPING);
getMappingAnnotation.addEnumAttribute("produces", SpringJavaType.MEDIA_TYPE,
"APPLICATION_JSON_VALUE");
getMappingAnnotation.addStringAttribute("name", methodName.getSymbolName());
getMappingAnnotation.addStringAttribute("value", "/s2");
annotations.add(getMappingAnnotation);
this.mvcMethodNames.put(methodName.getSymbolName(), methodName.getSymbolName());
// Adding @ResponseBody annotation
annotations.add(RESPONSE_BODY_ANNOTATION);
// Generate body
final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
final String itemsName = StringUtils.uncapitalize(this.entityPlural);
// Getting the findAllMethod
MethodMetadata findAllMethod = this.serviceMetadata.getCurrentFindAllWithGlobalSearchMethod();
// Getting the findAll return type
JavaType defaultReturnType = findAllMethod.getReturnType().getParameters().get(0);
// Page<Customer> customers = customerService.findAll(search, pageable);
bodyBuilder.appendFormalLine("%s<%s> %s = %s().%s(search, pageable);",
getNameOfJavaType(SpringJavaType.PAGE), getNameOfJavaType(defaultReturnType), itemsName,
getAccessorMethod(this.controllerMetadata.getServiceField()).getMethodName(),
findAllMethod.getMethodName());
// String idExpression = "#{id}";
bodyBuilder.appendFormalLine("String idExpression = \"#{%s}\";", this.entityIdentifier);
// Select2DataSupport<Customer> select2Data = new
// Select2DataWithConversion<Customer>(customers, idExpression,
// conversionService);
bodyBuilder.appendFormalLine("%s<%s> select2Data = new %s<%s>(%s, idExpression, %s());",
getNameOfJavaType(SpringletsJavaType.SPRINGLETS_SELECT2_DATA_SUPPORT),
getNameOfJavaType(defaultReturnType),
getNameOfJavaType(SpringletsJavaType.SPRINGLETS_SELECT2_DATA_WITH_CONVERSION),
getNameOfJavaType(defaultReturnType), itemsName,
getAccessorMethod(this.conversionServiceField).getMethodName());
// return ResponseEntity.ok(select2Data);
bodyBuilder.appendFormalLine("return %s.ok(select2Data);", getNameOfJavaType(RESPONSE_ENTITY));
// Generating returnType
JavaType returnType =
JavaType.wrapperOf(RESPONSE_ENTITY, JavaType.wrapperOf(
SpringletsJavaType.SPRINGLETS_SELECT2_DATA_SUPPORT, defaultReturnType));
MethodMetadataBuilder methodBuilder =
new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName, returnType, parameterTypes,
parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
return methodBuilder.build();
}
/**
* This method provides the "edit" form method using Thymeleaf view response
* type
*
* @return MethodMetadata
*/
private MethodMetadata getEditFormMethod() {
// Define methodName
final JavaSymbolName methodName = EDIT_FORM_METHOD_NAME;
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
parameterTypes.add(new AnnotatedJavaType(this.entity, ANN_METADATA_MODEL_ATTRIBUTE));
parameterTypes.add(MODEL_PARAM);
MethodMetadata existingMethod =
getGovernorMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes));
if (existingMethod != null) {
return existingMethod;
}
final List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(new JavaSymbolName(entityItemName));
parameterNames.add(MODEL_PARAM_NAME);
// Adding annotations
final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
// Adding @GetMapping annotation
final AnnotationMetadataBuilder getMapping = new AnnotationMetadataBuilder(GET_MAPPING);
getMapping.addStringAttribute("value", "/edit-form");
getMapping.addStringAttribute("name", methodName.getSymbolName());
annotations.add(getMapping);
this.mvcMethodNames.put(methodName.getSymbolName(), methodName.getSymbolName());
// Generate body
final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
// populateFormats(model);
bodyBuilder.appendFormalLine("%s(model);", populateFormMethod.getMethodName());
bodyBuilder.newLine();
// model.addAttribute("entity", entityParam)
bodyBuilder.appendFormalLine("model.addAttribute(\"%s\", %s);", entityItemName, entityItemName);
// return new ModelAndView("customers/edit");
bodyBuilder.appendFormalLine("return new %s(\"%s/edit\");",
getNameOfJavaType(SpringJavaType.MODEL_AND_VIEW), viewsPath);
MethodMetadataBuilder methodBuilder =
new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName,
SpringJavaType.MODEL_AND_VIEW, parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
return methodBuilder.build();
}
/**
* This method provides the "edit" details form method using Thymeleaf view
* response type
*
* @return MethodMetadata
*/
private MethodMetadata getEditFormDetailMethod() {
// Define methodName
final JavaSymbolName methodName = EDIT_FORM_METHOD_NAME;
final RelationInfoExtended info = controllerMetadata.getLastDetailsInfo();
final JavaType parentEntity = info.entityType;
final JavaType entity = info.childType;
final String entityItemName = StringUtils.uncapitalize(entity.getSimpleTypeName());
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
parameterTypes.add(new AnnotatedJavaType(parentEntity, ANN_METADATA_MODEL_ATTRIBUTE));
parameterTypes.add(new AnnotatedJavaType(entity, ANN_METADATA_MODEL_ATTRIBUTE));
parameterTypes.add(MODEL_PARAM);
MethodMetadata existingMethod =
getGovernorMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes));
if (existingMethod != null) {
return existingMethod;
}
final List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(new JavaSymbolName(
StringUtils.uncapitalize(parentEntity.getSimpleTypeName())));
parameterNames.add(new JavaSymbolName(entityItemName));
parameterNames.add(MODEL_PARAM_NAME);
// Adding annotations
final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
// Adding @GetMapping annotation
final AnnotationMetadataBuilder getMapping = new AnnotationMetadataBuilder(GET_MAPPING);
getMapping.addStringAttribute("value", "/edit-form");
getMapping.addStringAttribute("name", methodName.getSymbolName());
annotations.add(getMapping);
this.mvcMethodNames.put(methodName.getSymbolName(), methodName.getSymbolName());
// Generate body
final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
// populateFormats(model);
bodyBuilder.appendFormalLine("%s(model);", populateFormMethod.getMethodName());
bodyBuilder.newLine();
// model.addAttribute("entity", entityParam)
bodyBuilder.appendFormalLine("model.addAttribute(\"%s\", %s);", entityItemName, entityItemName);
// return new ModelAndView("customerorders/details/edit");
bodyBuilder.appendFormalLine("return new %s(\"%s/%s/edit\");",
getNameOfJavaType(SpringJavaType.MODEL_AND_VIEW), viewsPath,
controllerMetadata.getDetailsPathAsString("/"));
MethodMetadataBuilder methodBuilder =
new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName,
SpringJavaType.MODEL_AND_VIEW, parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
return methodBuilder.build();
}
/**
* This method provides the "show" method using Thymeleaf view response type
*
* @return MethodMetadata
*/
private MethodMetadata getShowMethod() {
// Define methodName
final JavaSymbolName methodName = SHOW_METHOD_NAME;
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
parameterTypes.add(new AnnotatedJavaType(this.entity, ANN_METADATA_MODEL_ATTRIBUTE));
parameterTypes.add(MODEL_PARAM);
MethodMetadata existingMethod =
getGovernorMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes));
if (existingMethod != null) {
return existingMethod;
}
final List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(new JavaSymbolName(entityItemName));
parameterNames.add(MODEL_PARAM_NAME);
// Adding annotations
final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
// Adding @RequestMapping annotation
AnnotationMetadataBuilder getMappingAnnotation = new AnnotationMetadataBuilder(GET_MAPPING);
getMappingAnnotation.addStringAttribute("name", methodName.getSymbolName());
annotations.add(getMappingAnnotation);
// Generate body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
// model.addAttribute("entity", entityParam)
bodyBuilder.appendFormalLine("model.addAttribute(\"%s\", %s);", entityItemName, entityItemName);
// return new ModelAndView("customers/show");
bodyBuilder.appendFormalLine("return new %s(\"%s/show\");",
getNameOfJavaType(SpringJavaType.MODEL_AND_VIEW), viewsPath);
MethodMetadataBuilder methodBuilder =
new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName,
SpringJavaType.MODEL_AND_VIEW, parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
return methodBuilder.build();
}
/**
* This method provides the "showInline" method using Thymeleaf view response type
*
* @return MethodMetadata
*/
private MethodMetadata getShowInlineMethod() {
// Define methodName
final JavaSymbolName methodName = SHOW_INLINE_METHOD_NAME;
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
parameterTypes.add(new AnnotatedJavaType(this.entity, ANN_METADATA_MODEL_ATTRIBUTE));
parameterTypes.add(MODEL_PARAM);
MethodMetadata existingMethod =
getGovernorMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes));
if (existingMethod != null) {
return existingMethod;
}
final List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(new JavaSymbolName(entityItemName));
parameterNames.add(MODEL_PARAM_NAME);
// Adding annotations
final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
// Adding @RequestMapping annotation
AnnotationMetadataBuilder getMappingAnnotation = new AnnotationMetadataBuilder(GET_MAPPING);
getMappingAnnotation.addStringAttribute("value", "/inline");
getMappingAnnotation.addStringAttribute("name", methodName.getSymbolName());
annotations.add(getMappingAnnotation);
// Generate body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
// model.addAttribute("entity", entityParam)
bodyBuilder.appendFormalLine("model.addAttribute(\"%s\", %s);", entityItemName, entityItemName);
// return new ModelAndView("customers/showInline :: inline-content");
bodyBuilder.appendFormalLine("return new %s(\"%s/showInline :: inline-content\");",
getNameOfJavaType(SpringJavaType.MODEL_AND_VIEW), viewsPath);
MethodMetadataBuilder methodBuilder =
new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName,
SpringJavaType.MODEL_AND_VIEW, parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
return methodBuilder.build();
}
/**
* This method provides the "show" detail method using Thymeleaf view
* response type
*
* @return MethodMetadata
*/
private MethodMetadata getShowDetailMethod() {
// Define methodName
final JavaSymbolName methodName = SHOW_METHOD_NAME;
final RelationInfoExtended info = controllerMetadata.getLastDetailsInfo();
final JavaType parentEntity = info.entityType;
final JavaType entity = info.childType;
final String entityItemName = StringUtils.uncapitalize(entity.getSimpleTypeName());
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
parameterTypes.add(new AnnotatedJavaType(parentEntity, ANN_METADATA_MODEL_ATTRIBUTE));
parameterTypes.add(new AnnotatedJavaType(entity, ANN_METADATA_MODEL_ATTRIBUTE));
parameterTypes.add(MODEL_PARAM);
MethodMetadata existingMethod =
getGovernorMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes));
if (existingMethod != null) {
return existingMethod;
}
final List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(new JavaSymbolName(
StringUtils.uncapitalize(parentEntity.getSimpleTypeName())));
parameterNames.add(new JavaSymbolName(entityItemName));
parameterNames.add(MODEL_PARAM_NAME);
// Adding annotations
final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
// Adding @RequestMapping annotation
AnnotationMetadataBuilder getMappingAnnotation = new AnnotationMetadataBuilder(GET_MAPPING);
getMappingAnnotation.addStringAttribute("name", methodName.getSymbolName());
annotations.add(getMappingAnnotation);
// Generate body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
// model.addAttribute("entity", entityParam)
bodyBuilder.appendFormalLine("model.addAttribute(\"%s\", %s);", entityItemName, entityItemName);
// return new ModelAndView("customerorders/details/show");
bodyBuilder.appendFormalLine("return new %s(\"%s/%s/show\");",
getNameOfJavaType(SpringJavaType.MODEL_AND_VIEW), viewsPath,
controllerMetadata.getDetailsPathAsString("/"));
MethodMetadataBuilder methodBuilder =
new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName,
SpringJavaType.MODEL_AND_VIEW, parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
return methodBuilder.build();
}
/**
* This method provides the "showInline" detail method using Thymeleaf view
* response type
*
* @return MethodMetadata
*/
private MethodMetadata getShowDetailInlineMethod() {
// Define methodName
final JavaSymbolName methodName = SHOW_INLINE_METHOD_NAME;
final RelationInfoExtended info = controllerMetadata.getLastDetailsInfo();
final JavaType parentEntity = info.entityType;
final JavaType entity = info.childType;
final String entityItemName = StringUtils.uncapitalize(entity.getSimpleTypeName());
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
parameterTypes.add(new AnnotatedJavaType(parentEntity, ANN_METADATA_MODEL_ATTRIBUTE));
parameterTypes.add(new AnnotatedJavaType(entity, ANN_METADATA_MODEL_ATTRIBUTE));
parameterTypes.add(MODEL_PARAM);
MethodMetadata existingMethod =
getGovernorMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes));
if (existingMethod != null) {
return existingMethod;
}
final List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(new JavaSymbolName(
StringUtils.uncapitalize(parentEntity.getSimpleTypeName())));
parameterNames.add(new JavaSymbolName(entityItemName));
parameterNames.add(MODEL_PARAM_NAME);
// Adding annotations
final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
// Adding @RequestMapping annotation
AnnotationMetadataBuilder getMappingAnnotation = new AnnotationMetadataBuilder(GET_MAPPING);
getMappingAnnotation.addStringAttribute("value", "/inline");
getMappingAnnotation.addStringAttribute("name", methodName.getSymbolName());
annotations.add(getMappingAnnotation);
// Generate body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
// model.addAttribute("entity", entityParam)
bodyBuilder.appendFormalLine("model.addAttribute(\"%s\", %s);", entityItemName, entityItemName);
// return new ModelAndView("customerorders/details/showInline :: inline-content");
bodyBuilder.appendFormalLine("return new %s(\"%s/%s/showInline :: inline-content\");",
getNameOfJavaType(SpringJavaType.MODEL_AND_VIEW), viewsPath,
controllerMetadata.getDetailsPathAsString("/"));
MethodMetadataBuilder methodBuilder =
new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName,
SpringJavaType.MODEL_AND_VIEW, parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
return methodBuilder.build();
}
/**
* This method provides the "populateForm" method
*
* @return MethodMetadata
*/
private MethodMetadata getPopulateFormMethod() {
// Define methodName
final JavaSymbolName methodName = new JavaSymbolName("populateForm");
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
parameterTypes.add(AnnotatedJavaType.convertFromJavaType(SpringJavaType.MODEL));
MethodMetadata existingMethod =
getGovernorMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes));
if (existingMethod != null) {
return existingMethod;
}
final List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(MODEL_PARAM_NAME);
// Adding annotations
final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
// Generate body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
// populateFormats(model);
bodyBuilder.appendFormalLine("%s(model);", populateFormatsMethod.getMethodName());
buildPopulateEnumsBody(bodyBuilder, enumFields);
MethodMetadataBuilder methodBuilder =
new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName, JavaType.VOID_PRIMITIVE,
parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
return methodBuilder.build();
}
/**
* Build method body which populate enum field of a entity into model
*
* @param bodyBuilder
* @param enumFields
*/
private void buildPopulateEnumsBody(InvocableMemberBodyBuilder bodyBuilder,
List<FieldMetadata> enumFields) {
// Getting all enum types from provided entity
for (FieldMetadata field : enumFields) {
// model.addAttribute("enumField",
// Arrays.asList(Enum.values()));
bodyBuilder.appendFormalLine("model.addAttribute(\"%s\", %s.asList(%s.values()));",
field.getFieldName(), getNameOfJavaType(JavaType.ARRAYS),
getNameOfJavaType(field.getFieldType()));
}
}
/**
* This method provides detail datatables list method using Thymeleaf
* response type
*
* @return MethodMetadata
*/
private MethodMetadata getListDatatablesDetailMethod() {
RelationInfo detailsInfo = controllerMetadata.getLastDetailsInfo();
final ServiceMetadata detailsServiceMetadata =
controllerMetadata.getServiceMetadataForEntity(detailsInfo.childType);
final MethodMetadata findAllMethod =
detailsServiceMetadata.getRefencedFieldFindAllDefinedMethod(detailsInfo.mappedBy);
final MethodMetadata countByDetailMethod =
detailsServiceMetadata.getCountByReferenceFieldDefinedMethod(detailsInfo.mappedBy);
final FieldMetadata detailsServiceField =
controllerMetadata.getDetailsServiceFields(detailsInfo.childType);
// Define methodName
final JavaSymbolName methodName = LIST_DATATABLES_DETAILS_METHOD_NAME;
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
parameterTypes.add(new AnnotatedJavaType(
findAllMethod.getParameterTypes().get(0).getJavaType(), ANN_METADATA_MODEL_ATTRIBUTE));
parameterTypes.add(DATATABLES_COLUMNS_PARAM);
parameterTypes.add(GLOBAL_SEARCH_PARAM);
parameterTypes.add(DATATABLES_PAGEABLE_PARAM);
AnnotationMetadataBuilder requestParamAnnotation = new AnnotationMetadataBuilder(REQUEST_PARAM);
requestParamAnnotation.addStringAttribute("value", "draw");
parameterTypes.add(new AnnotatedJavaType(JavaType.INT_OBJECT, requestParamAnnotation.build()));
MethodMetadata existingMethod =
getGovernorMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes));
if (existingMethod != null) {
return existingMethod;
}
final List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
final JavaSymbolName parentParamName = findAllMethod.getParameterNames().get(0);
parameterNames.add(parentParamName);
parameterNames.add(DATATABLES_COLUMNS_PARAM_NAME);
parameterNames.add(new JavaSymbolName("search"));
parameterNames.add(new JavaSymbolName("pageable"));
parameterNames.add(new JavaSymbolName("draw"));
// Adding annotations
final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
// Adding @GetMapping annotation
AnnotationMetadataBuilder getMappingAnnotation = new AnnotationMetadataBuilder(GET_MAPPING);
getMappingAnnotation.addStringAttribute("name", methodName.getSymbolName());
getMappingAnnotation.addEnumAttribute("produces", SPRINGLETS_DATATABLES, "MEDIA_TYPE");
getMappingAnnotation.addStringAttribute("value", "/dt");
annotations.add(getMappingAnnotation);
this.mvcMethodNames.put(methodName.getSymbolName(), methodName.getSymbolName());
// Adding @ResponseBody annotation
annotations.add(RESPONSE_BODY_ANNOTATION);
// Generating returnType
final JavaType serviceReturnType = findAllMethod.getReturnType();
final JavaType dataReturnType =
JavaType.wrapperOf(SpringletsJavaType.SPRINGLETS_CONVERTED_DATATABLES_DATA,
serviceReturnType.getParameters().get(0));
final JavaType returnType = JavaType.wrapperOf(RESPONSE_ENTITY, dataReturnType);
// TODO
// Add module dependency
// getTypeLocationService().addModuleDependency(this.controller.getType().getModule(),
// returnParameterTypes.get(i));
// Generate body
final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
final String itemsName = StringUtils.uncapitalize(detailsInfo.fieldName);
// Page<CustomerOrder> orders =
// customerOrderService.findByCustomer(customer, globalSearch,
// pageable);
bodyBuilder.newLine();
bodyBuilder.appendFormalLine("%s %s = %s().%s(%s, search, pageable);",
getNameOfJavaType(serviceReturnType), itemsName, getAccessorMethod(detailsServiceField)
.getMethodName(), findAllMethod.getMethodName(), parentParamName);
final String totalVarName = "total" + StringUtils.capitalize(itemsName) + "Count";
// long totalOrdersCount =
// customerOrderService.countByCustomer(customer);
bodyBuilder.appendFormalLine("%s %s = %s().%s(%s);",
getNameOfJavaType(countByDetailMethod.getReturnType()), totalVarName,
getAccessorMethod(detailsServiceField).getMethodName(),
countByDetailMethod.getMethodName(), parentParamName);
// ConvertedDatatablesData<CustomerOrder> data = new
// ConvertedDatatablesData<CustomerOrder>(orders,
// totalOrdersCount, draw, conversionService, columns);
bodyBuilder.appendFormalLine("%1$s data = new %1$s(%2$s, %3$s, draw, %4$s(), %5$s);",
getNameOfJavaType(dataReturnType), itemsName, totalVarName,
getAccessorMethod(this.conversionServiceField).getMethodName(),
DATATABLES_COLUMNS_PARAM_NAME);
// return ResponseEntity.ok(data);
bodyBuilder.appendFormalLine("return %s.ok(data);",
getNameOfJavaType(SpringJavaType.RESPONSE_ENTITY));
MethodMetadataBuilder methodBuilder =
new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName, returnType, parameterTypes,
parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
return methodBuilder.build();
}
/**
* This method provides detail datatablesByIdsIn list method using Thymeleaf
* response type
*
* @return MethodMetadata
*/
private MethodMetadata getListDatatablesByIdsInDetailMethod() {
RelationInfo detailsInfo = controllerMetadata.getLastDetailsInfo();
final ServiceMetadata detailsServiceMetadata =
controllerMetadata.getServiceMetadataForEntity(detailsInfo.childType);
final MethodMetadata findAllByIdsInMethod =
detailsServiceMetadata.getCurrentFindAllByIdsInWithGlobalSearchMethod();
final FieldMetadata detailsServiceField =
controllerMetadata.getDetailsServiceFields(detailsInfo.childType);
// Define methodName
final JavaSymbolName methodName = LIST_DATATABLES_BY_IDS_IN_DETAILS_METHOD_NAME;
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
AnnotationMetadataBuilder requestParamIdsAnnotation =
new AnnotationMetadataBuilder(REQUEST_PARAM);
requestParamIdsAnnotation.addStringAttribute("value", "ids");
parameterTypes
.add(new AnnotatedJavaType(JavaType.wrapperOf(JavaType.LIST, findAllByIdsInMethod
.getParameterTypes().get(0).getJavaType().getBaseType()), requestParamIdsAnnotation
.build()));
parameterTypes.add(DATATABLES_COLUMNS_PARAM);
parameterTypes.add(GLOBAL_SEARCH_PARAM);
parameterTypes.add(DATATABLES_PAGEABLE_PARAM);
AnnotationMetadataBuilder requestParamAnnotation = new AnnotationMetadataBuilder(REQUEST_PARAM);
requestParamAnnotation.addStringAttribute("value", "draw");
parameterTypes.add(new AnnotatedJavaType(JavaType.INT_OBJECT, requestParamAnnotation.build()));
MethodMetadata existingMethod =
getGovernorMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes));
if (existingMethod != null) {
return existingMethod;
}
final List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(new JavaSymbolName("ids"));
parameterNames.add(DATATABLES_COLUMNS_PARAM_NAME);
parameterNames.add(new JavaSymbolName("search"));
parameterNames.add(new JavaSymbolName("pageable"));
parameterNames.add(new JavaSymbolName("draw"));
// Adding annotations
final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
// Adding @GetMapping annotation
AnnotationMetadataBuilder getMappingAnnotation = new AnnotationMetadataBuilder(GET_MAPPING);
getMappingAnnotation.addStringAttribute("name", methodName.getSymbolName());
getMappingAnnotation.addEnumAttribute("produces", SPRINGLETS_DATATABLES, "MEDIA_TYPE");
getMappingAnnotation.addStringAttribute("value", "/dtByIdsIn");
annotations.add(getMappingAnnotation);
this.mvcMethodNames.put(methodName.getSymbolName(), methodName.getSymbolName());
// Adding @ResponseBody annotation
annotations.add(RESPONSE_BODY_ANNOTATION);
// Generating returnType
final JavaType serviceReturnType = findAllByIdsInMethod.getReturnType();
final JavaType dataReturnType =
JavaType.wrapperOf(SpringletsJavaType.SPRINGLETS_CONVERTED_DATATABLES_DATA,
serviceReturnType.getParameters().get(0));
final JavaType returnType = JavaType.wrapperOf(RESPONSE_ENTITY, dataReturnType);
// TODO
// Add module dependency
// getTypeLocationService().addModuleDependency(this.controller.getType().getModule(),
// returnParameterTypes.get(i));
// Generate body
final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
final String itemsName = StringUtils.uncapitalize(detailsInfo.fieldName);
// Page<CustomerOrder> orders =
// customerOrderService.findByCustomer(customer, globalSearch,
// pageable);
bodyBuilder.newLine();
bodyBuilder.appendFormalLine("%s %s = %s().%s(ids, search, pageable);",
getNameOfJavaType(serviceReturnType), itemsName, getAccessorMethod(detailsServiceField)
.getMethodName(), findAllByIdsInMethod.getMethodName());
final String totalVarName = "total" + StringUtils.capitalize(itemsName) + "Count";
// long totalOrdersCount =
// customerOrderService.countByCustomer(customer);
bodyBuilder.appendFormalLine("long %s = %s.getTotalElements();", totalVarName, itemsName);
// ConvertedDatatablesData<CustomerOrder> data = new
// ConvertedDatatablesData<CustomerOrder>(orders,
// totalOrdersCount, draw, conversionService, columns);
bodyBuilder.appendFormalLine("%1$s data = new %1$s(%2$s, %3$s, draw, %4$s(), %5$s);",
getNameOfJavaType(dataReturnType), itemsName, totalVarName,
getAccessorMethod(this.conversionServiceField).getMethodName(),
DATATABLES_COLUMNS_PARAM_NAME);
// return ResponseEntity.ok(data);
bodyBuilder.appendFormalLine("return %s.ok(data);",
getNameOfJavaType(SpringJavaType.RESPONSE_ENTITY));
MethodMetadataBuilder methodBuilder =
new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName, returnType, parameterTypes,
parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
return methodBuilder.build();
}
/**
* This method provides the "create" method for details association
* relationship using Thymeleaf view response type
*
* @return MethodMetadata
*/
private MethodMetadata getCreateDetailsCompositionMethod() {
RelationInfo detailsInfo = controllerMetadata.getLastDetailsInfo();
final ServiceMetadata detailsServiceMetadata =
controllerMetadata.getServiceMetadataForEntity(detailsInfo.entityType);
final MethodMetadata addToRelationMethod =
detailsServiceMetadata.getAddToRelationMethods().get(detailsInfo);
final FieldMetadata detailsServiceField =
controllerMetadata.getDetailsServiceFields(detailsInfo.entityType);
final RelationInfoExtended info = controllerMetadata.getLastDetailsInfo();
final JavaType parentEntity = info.entityType;
final JavaType entity = info.childType;
final String entityItemName = StringUtils.uncapitalize(entity.getSimpleTypeName());
final String parentItemName = StringUtils.uncapitalize(parentEntity.getSimpleTypeName());
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
parameterTypes.add(new AnnotatedJavaType(parentEntity, ANN_METADATA_MODEL_ATTRIBUTE));
parameterTypes.add(new AnnotatedJavaType(entity, ANN_METADATA_VALID,
ANN_METADATA_MODEL_ATTRIBUTE));
parameterTypes.add(new AnnotatedJavaType(SpringJavaType.BINDING_RESULT));
parameterTypes.add(MODEL_PARAM);
// Define methodName
final JavaSymbolName methodName = CREATE_METHOD_NAME;
MethodMetadata existingMethod =
getGovernorMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes));
if (existingMethod != null) {
return existingMethod;
}
// Adding annotations
final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
// Adding @PostMapping annotation
AnnotationMetadataBuilder postMappingAnnotation =
new AnnotationMetadataBuilder(SpringJavaType.POST_MAPPING);
postMappingAnnotation.addStringAttribute("name", methodName.getSymbolName());
annotations.add(postMappingAnnotation);
this.mvcMethodNames.put(methodName.getSymbolName(), methodName.getSymbolName());
final List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(new JavaSymbolName(parentItemName));
parameterNames.add(new JavaSymbolName(entityItemName));
parameterNames.add(new JavaSymbolName("result"));
parameterNames.add(MODEL_PARAM_NAME);
// Generate body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
// if (result.hasErrors()) {
bodyBuilder.appendFormalLine("if (result.hasErrors()) {");
bodyBuilder.indent();
// populateFormats(model);
bodyBuilder.appendFormalLine("%s(model);", populateFormMethod.getMethodName());
bodyBuilder.newLine();
// return new ModelAndView("customerorders/details/edit");
bodyBuilder.appendFormalLine("return new %s(\"%s/%s/create\");",
getNameOfJavaType(SpringJavaType.MODEL_AND_VIEW), viewsPath,
controllerMetadata.getDetailsPathAsString("/"));
bodyBuilder.indentRemove();
// }
bodyBuilder.appendFormalLine("}");
// customerOrderService.addToDetails(customerOrder,
// Collections.singleton(orderDetail));
bodyBuilder.appendFormalLine("%s().%s(%s,%s.singleton(%s));",
getAccessorMethod(detailsServiceField).getMethodName(),
addToRelationMethod.getMethodName(), parentItemName,
getNameOfJavaType(JavaType.COLLECTIONS), entityItemName);
// return new ModelAndView("redirect:" +
// collectionLink.to("list").toUriString());
bodyBuilder.appendFormalLine("return new %s(\"redirect:\" + %s().to(%s.LIST).toUriString());",
getNameOfJavaType(SpringJavaType.MODEL_AND_VIEW),
getAccessorMethod(this.methodLinkBuilderFactoryField).getMethodName(),
getNameOfJavaType(relatedCollectionLinkFactory));
MethodMetadataBuilder methodBuilder =
new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName,
SpringJavaType.MODEL_AND_VIEW, parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
return methodBuilder.build();
}
/**
* This method provides the "create" method for details association
* relationship using Thymeleaf view response type
*
* @return MethodMetadata
*/
private MethodMetadata getCreateDetailsMethod() {
RelationInfo detailsInfo = controllerMetadata.getLastDetailsInfo();
final ServiceMetadata detailsServiceMetadata =
controllerMetadata.getServiceMetadataForEntity(detailsInfo.entityType);
final MethodMetadata setMethod =
detailsServiceMetadata.getSetRelationMethods().get(detailsInfo);
final FieldMetadata detailsServiceField =
controllerMetadata.getDetailsServiceFields(detailsInfo.entityType);
// Define methodName
final JavaSymbolName methodName = CREATE_METHOD_NAME;
JavaSymbolName itemsName = setMethod.getParameterNames().get(1);
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
parameterTypes.add(new AnnotatedJavaType(setMethod.getParameterTypes().get(0).getJavaType(),
ANN_METADATA_MODEL_ATTRIBUTE));
AnnotationMetadataBuilder requestParamAnnotation = new AnnotationMetadataBuilder(REQUEST_PARAM);
requestParamAnnotation.addStringAttribute("value", itemsName.getSymbolName().concat("Ids"));
requestParamAnnotation.addBooleanAttribute("required", false);
JavaType identifierType =
setMethod.getParameterTypes().get(1).getJavaType().getParameters().get(0);
parameterTypes.add(new AnnotatedJavaType(JavaType.wrapperOf(JavaType.LIST, identifierType),
requestParamAnnotation.build()));
// Version parameter
AnnotationMetadataBuilder versionRequestParamAnnotation =
new AnnotationMetadataBuilder(REQUEST_PARAM);
versionRequestParamAnnotation.addStringAttribute("value", "parentVersion");
parameterTypes.add(new AnnotatedJavaType(this.entityMetadata.getCurrentVersionField()
.getFieldType(), versionRequestParamAnnotation.build()));
// Concurrency control parameter
AnnotationMetadataBuilder concurrencyControlRequestParam =
new AnnotationMetadataBuilder(REQUEST_PARAM);
concurrencyControlRequestParam.addStringAttribute("value", "concurrency");
concurrencyControlRequestParam.addBooleanAttribute("required", false);
concurrencyControlRequestParam.addStringAttribute("defaultValue", "");
parameterTypes.add(new AnnotatedJavaType(JavaType.STRING, concurrencyControlRequestParam
.build()));
parameterTypes.add(AnnotatedJavaType.convertFromJavaType(SpringJavaType.MODEL));
MethodMetadata existingMethod =
getGovernorMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes));
if (existingMethod != null) {
return existingMethod;
}
// Adding annotations
final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
// Adding @PostMapping annotation
AnnotationMetadataBuilder postMappingAnnotation =
new AnnotationMetadataBuilder(SpringJavaType.POST_MAPPING);
postMappingAnnotation.addStringAttribute("name", methodName.getSymbolName());
annotations.add(postMappingAnnotation);
this.mvcMethodNames.put(methodName.getSymbolName(), methodName.getSymbolName());
final List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.addAll(setMethod.getParameterNames());
parameterNames.add(VERSION_PARAM_NAME);
parameterNames.add(new JavaSymbolName("concurrencyControl"));
parameterNames.add(MODEL_PARAM_NAME);
// Generate body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
/*
* // Remove empty values for (Iterator<Long> iterator =
* products.iterator(); iterator.hasNext();) { if (iterator.next() ==
* null) { iterator.remove(); } }
*/
bodyBuilder.appendFormalLine("// Remove empty values");
// if(books != null){
bodyBuilder.appendFormalLine("if (%s != null) {", itemsName);
bodyBuilder.indent();
bodyBuilder.appendFormalLine("for (%s<%s> iterator = %s.iterator(); iterator.hasNext();) {",
getNameOfJavaType(JavaType.ITERATOR), getNameOfJavaType(identifierType), itemsName);
bodyBuilder.indent();
bodyBuilder.appendFormalLine("if (iterator.next() == null) {");
bodyBuilder.indent();
bodyBuilder.appendFormalLine("iterator.remove();");
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
// // Concurrency control
bodyBuilder.appendFormalLine("// Concurrency control");
JavaSymbolName parentName = setMethod.getParameterNames().get(0);
// if(version != pet.getVersion() && StringUtils.isEmpty(concurrencyControl)){
bodyBuilder.appendFormalLine("if(%s != %s.%s() && %s.isEmpty(concurrencyControl)){",
VERSION_PARAM_NAME, parentName,
getAccessorMethod(this.entityMetadata.getCurrentVersionField()).getMethodName(),
getNameOfJavaType(new JavaType("org.apache.commons.lang3.StringUtils")));
bodyBuilder.indent();
// populateForm(model);
bodyBuilder.appendFormalLine("populateForm(model);");
// // Obtain the selected books and include them in the author that will be
bodyBuilder
.appendFormalLine("// Obtain the selected books and include them in the author that will be ");
// // included in the view
bodyBuilder.appendFormalLine("// included in the view");
// if(books != null){
bodyBuilder.appendFormalLine("if (%s != null) {", itemsName);
bodyBuilder.indent();
// author.setBooks(new HashSet<Book>(getBookService().findAll(books)));
bodyBuilder.appendFormalLine("%s.%s(new %s<%s>(%s().findAll(%s)));", parentName, setMethod
.getMethodName(), getNameOfJavaType(JavaType.HASH_SET),
getNameOfJavaType(detailsInfo.childType),
getAccessorMethod(controllerMetadata.getDetailsServiceFields(detailsInfo.childType))
.getMethodName(), itemsName);
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}else{");
bodyBuilder.indent();
// author.setBooks(new HashSet<Book>());
bodyBuilder.appendFormalLine("%s.%s(new %s<%s>());", parentName, setMethod.getMethodName(),
getNameOfJavaType(JavaType.HASH_SET), getNameOfJavaType(detailsInfo.childType));
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
// // Reset the version to prevent update
bodyBuilder.appendFormalLine("// Reset the version to prevent update");
// author.setVersion(version);
bodyBuilder.appendFormalLine(" %s.setVersion(%s);", parentName, VERSION_PARAM_NAME);
// // Include the updated author in the model
bodyBuilder.appendFormalLine("// Include the updated element in the model");
// model.addAttribute("author", author);
bodyBuilder.appendFormalLine("model.addAttribute(\"%s\", %s);", parentName, parentName);
// model.addAttribute("concurrency", true);
bodyBuilder.appendFormalLine("model.addAttribute(\"concurrency\", true);");
// return new ModelAndView("owners/pets/create");
bodyBuilder.appendFormalLine("return new %s(\"%s/%s/create\");",
getNameOfJavaType(SpringJavaType.MODEL_AND_VIEW), viewsPath, itemsName);
bodyBuilder.indentRemove();
// }else if(version != pet.getVersion() && "discard".equals(concurrencyControl)){
bodyBuilder
.appendFormalLine("}else if(%s != %s.%s() && \"discard\".equals(concurrencyControl)){",
VERSION_PARAM_NAME, parentName,
getAccessorMethod(this.entityMetadata.getCurrentVersionField()).getMethodName());
bodyBuilder.indent();
// populateForm(model);
bodyBuilder.appendFormalLine("populateForm(model);");
// // Provide the original author from the Database
bodyBuilder.appendFormalLine("// Provide the original element from the Database");
// model.addAttribute("author", author);
bodyBuilder.appendFormalLine("model.addAttribute(\"%s\", %s);", parentName, parentName);
// model.addAttribute("concurrency", false);
bodyBuilder.appendFormalLine("model.addAttribute(\"concurrency\", false);");
// return new ModelAndView("owners/pets/create");
bodyBuilder.appendFormalLine("return new %s(\"%s/%s/create\");",
getNameOfJavaType(SpringJavaType.MODEL_AND_VIEW), viewsPath, itemsName);
bodyBuilder.indentRemove();
bodyBuilder.appendFormalLine("}");
// categoryService.setProducts(category, products);
bodyBuilder.appendFormalLine("%s().%s(%s,%s);", getAccessorMethod(detailsServiceField)
.getMethodName(), setMethod.getMethodName(), setMethod.getParameterNames().get(0),
itemsName);
// return new ModelAndView("redirect:" +
// collectionLink.to("list").toUriString());
bodyBuilder.appendFormalLine("return new %s(\"redirect:\" + %s().to(%s.LIST).toUriString());",
getNameOfJavaType(SpringJavaType.MODEL_AND_VIEW),
getAccessorMethod(this.methodLinkBuilderFactoryField).getMethodName(),
getNameOfJavaType(relatedCollectionLinkFactory));
MethodMetadataBuilder methodBuilder =
new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName,
SpringJavaType.MODEL_AND_VIEW, parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
return methodBuilder.build();
}
/**
* This method provides the "create" form method for details using Thymeleaf
* view response type
*
* @return MethodMetadata
*/
private MethodMetadata getCreateFormDetailsMethod() {
// Define methodName
final JavaSymbolName methodName = CREATE_FORM_METHOD_NAME;
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
final RelationInfoExtended info = controllerMetadata.getLastDetailsInfo();
final JavaType parentEntity = info.entityType;
final JavaType entity = info.childType;
parameterTypes.add(new AnnotatedJavaType(parentEntity, ANN_METADATA_MODEL_ATTRIBUTE));
parameterTypes.add(MODEL_PARAM);
MethodMetadata existingMethod =
getGovernorMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes));
if (existingMethod != null) {
return existingMethod;
}
final List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
String parentEntityParamName = StringUtils.uncapitalize(parentEntity.getSimpleTypeName());
parameterNames.add(new JavaSymbolName(parentEntityParamName));
parameterNames.add(MODEL_PARAM_NAME);
// Adding annotations
final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
// Adding @GetMapping annotation
AnnotationMetadataBuilder getMapping = new AnnotationMetadataBuilder(GET_MAPPING);
getMapping.addStringAttribute("value", "/create-form");
getMapping.addStringAttribute("name", methodName.getSymbolName());
annotations.add(getMapping);
this.mvcMethodNames.put(methodName.getSymbolName(), methodName.getSymbolName());
// Generate body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
// populateForm(model);
bodyBuilder.appendFormalLine("%s(model);", populateFormMethod.getMethodName());
// model.addAttribute("entity", new Entity());
bodyBuilder.appendFormalLine(String.format("model.addAttribute(\"%s\", new %s());",
StringUtils.uncapitalize(getNameOfJavaType(entity)), getNameOfJavaType(entity)));
// return new ModelAndView("path/create");
bodyBuilder.appendFormalLine("return new %s(\"%s/%s/create\");",
getNameOfJavaType(SpringJavaType.MODEL_AND_VIEW), viewsPath,
controllerMetadata.getDetailsPathAsString("/"));
MethodMetadataBuilder methodBuilder =
new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName,
SpringJavaType.MODEL_AND_VIEW, parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
return methodBuilder.build();
}
private MethodMetadata getDeleteDetailMethod() {
RelationInfoExtended detailsInfo = controllerMetadata.getLastDetailsInfo();
final ServiceMetadata detailsServiceMetadata =
controllerMetadata.getServiceMetadataForEntity(detailsInfo.entityType);
final MethodMetadata removeFromMethod =
detailsServiceMetadata.getRemoveFromRelationMethods().get(detailsInfo);
final FieldMetadata detailsServiceField =
controllerMetadata.getDetailsServiceFields(detailsInfo.entityType);
JavaSymbolName methodName = DELETE_METHOD_NAME;
JavaSymbolName itemsName = detailsInfo.fieldMetadata.getFieldName();
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
parameterTypes.add(new AnnotatedJavaType(removeFromMethod.getParameterTypes().get(0)
.getJavaType(), ANN_METADATA_MODEL_ATTRIBUTE));
parameterTypes.add(new AnnotatedJavaType(detailsInfo.childType, ANN_METADATA_MODEL_ATTRIBUTE));
MethodMetadata existingMethod =
getGovernorMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes));
if (existingMethod != null) {
return existingMethod;
}
// Adding annotations
final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
// Adding @DeleteMapping annotation
AnnotationMetadataBuilder postMappingAnnotation =
new AnnotationMetadataBuilder(SpringJavaType.DELETE_MAPPING);
postMappingAnnotation.addStringAttribute("name", methodName.getSymbolName());
annotations.add(postMappingAnnotation);
this.mvcMethodNames.put(methodName.getSymbolName(), methodName.getSymbolName());
annotations.add(new AnnotationMetadataBuilder(SpringJavaType.RESPONSE_BODY));
final List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(removeFromMethod.getParameterNames().get(0));
parameterNames.add(itemsName);
// Generate body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
// customerService.addToOrders(customer, order.getId());
bodyBuilder.appendFormalLine("%s().%s(%s,%s.singleton(%s.%s()));",
getAccessorMethod(detailsServiceField).getMethodName(), removeFromMethod.getMethodName(),
removeFromMethod.getParameterNames().get(0), getNameOfJavaType(JavaType.COLLECTIONS),
itemsName, detailsInfo.childEntityMetadata.getCurrentIdentifierAccessor().getMethodName());
// return ResponseEntity.ok().build();
bodyBuilder.appendFormalLine("return %s.ok().build();", getNameOfJavaType(RESPONSE_ENTITY));
MethodMetadataBuilder methodBuilder =
new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName,
JavaType.wrapperWilcard(RESPONSE_ENTITY), parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
return methodBuilder.build();
}
private MethodMetadata getRemoveFromDetailsMethod() {
RelationInfoExtended detailsInfo = controllerMetadata.getLastDetailsInfo();
final ServiceMetadata detailsServiceMetadata =
controllerMetadata.getServiceMetadataForEntity(detailsInfo.entityType);
final MethodMetadata removeFromMethod =
detailsServiceMetadata.getRemoveFromRelationMethods().get(detailsInfo);
final FieldMetadata detailsServiceField =
controllerMetadata.getDetailsServiceFields(detailsInfo.entityType);
// Define methodName
final JavaSymbolName methodName = removeFromMethod.getMethodName();
JavaSymbolName itemsName = removeFromMethod.getParameterNames().get(1);
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
parameterTypes.add(new AnnotatedJavaType(removeFromMethod.getParameterTypes().get(0)
.getJavaType(), AnnotationMetadataBuilder.getInstance(SpringJavaType.MODEL_ATTRIBUTE)));
AnnotationMetadataBuilder pathVariableAnnotation =
new AnnotationMetadataBuilder(SpringJavaType.PATH_VARIABLE);
pathVariableAnnotation.addStringAttribute("value", itemsName.getSymbolName());
parameterTypes.add(new AnnotatedJavaType(removeFromMethod.getParameterTypes().get(1)
.getJavaType().getParameters().get(0), pathVariableAnnotation.build()));
MethodMetadata existingMethod =
getGovernorMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes));
if (existingMethod != null) {
return existingMethod;
}
// Adding annotations
final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
// Adding @DeleteMapping annotation
AnnotationMetadataBuilder postMappingAnnotation =
new AnnotationMetadataBuilder(SpringJavaType.DELETE_MAPPING);
postMappingAnnotation.addStringAttribute("name", methodName.getSymbolName());
postMappingAnnotation.addStringAttribute("value", "/{" + itemsName.getSymbolName() + "}");
annotations.add(postMappingAnnotation);
this.mvcMethodNames.put(methodName.getSymbolName(), methodName.getSymbolName());
annotations.add(new AnnotationMetadataBuilder(SpringJavaType.RESPONSE_BODY));
final List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.addAll(removeFromMethod.getParameterNames());
// Generate body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
// customerService.removeFromOrders(customer,
// Collections.singleton(order));
bodyBuilder.appendFormalLine("%s().%s(%s,%s.singleton(%s));",
getAccessorMethod(detailsServiceField).getMethodName(), removeFromMethod.getMethodName(),
removeFromMethod.getParameterNames().get(0), getNameOfJavaType(JavaType.COLLECTIONS),
itemsName);
// return ResponseEntity.ok().build();
bodyBuilder.appendFormalLine("return %s.ok().build();", getNameOfJavaType(RESPONSE_ENTITY));
MethodMetadataBuilder methodBuilder =
new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName,
JavaType.wrapperWilcard(RESPONSE_ENTITY), parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
return methodBuilder.build();
}
private MethodMetadata getRemoveFromDetailsBatchMethod() {
RelationInfoExtended detailsInfo = controllerMetadata.getLastDetailsInfo();
final ServiceMetadata detailsServiceMetadata =
controllerMetadata.getServiceMetadataForEntity(detailsInfo.entityType);
final MethodMetadata removeFromMethod =
detailsServiceMetadata.getRemoveFromRelationMethods().get(detailsInfo);
final FieldMetadata detailsServiceField =
controllerMetadata.getDetailsServiceFields(detailsInfo.entityType);
// Define methodName
final String methodName = removeFromMethod.getMethodName().getSymbolName().concat("Batch");
JavaSymbolName itemsName = removeFromMethod.getParameterNames().get(1);
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
parameterTypes.add(new AnnotatedJavaType(removeFromMethod.getParameterTypes().get(0)
.getJavaType(), AnnotationMetadataBuilder.getInstance(SpringJavaType.MODEL_ATTRIBUTE)));
AnnotationMetadataBuilder pathVariableAnnotation =
new AnnotationMetadataBuilder(SpringJavaType.PATH_VARIABLE);
pathVariableAnnotation.addStringAttribute("value", itemsName.getSymbolName());
parameterTypes.add(new AnnotatedJavaType(JavaType.collectionOf(removeFromMethod
.getParameterTypes().get(1).getJavaType().getParameters().get(0)), pathVariableAnnotation
.build()));
MethodMetadata existingMethod =
getGovernorMethod(new JavaSymbolName(methodName),
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes));
if (existingMethod != null) {
return existingMethod;
}
// Adding annotations
final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
// Adding @DeleteMapping annotation
AnnotationMetadataBuilder postMappingAnnotation =
new AnnotationMetadataBuilder(SpringJavaType.DELETE_MAPPING);
postMappingAnnotation.addStringAttribute("name", methodName);
postMappingAnnotation.addStringAttribute("value", "/batch/{" + itemsName.getSymbolName() + "}");
annotations.add(postMappingAnnotation);
this.mvcMethodNames.put(methodName, methodName);
annotations.add(new AnnotationMetadataBuilder(SpringJavaType.RESPONSE_BODY));
final List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.addAll(removeFromMethod.getParameterNames());
// Generate body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
// customerService.removeFromOrders(customer, ordersToRemove);
bodyBuilder.appendFormalLine("%s().%s(%s, %s);", getAccessorMethod(detailsServiceField)
.getMethodName(), removeFromMethod.getMethodName(), removeFromMethod.getParameterNames()
.get(0), itemsName);
// return ResponseEntity.ok().build();
bodyBuilder.appendFormalLine("return %s.ok().build();", getNameOfJavaType(RESPONSE_ENTITY));
MethodMetadataBuilder methodBuilder =
new MethodMetadataBuilder(getId(), Modifier.PUBLIC, new JavaSymbolName(methodName),
JavaType.wrapperWilcard(RESPONSE_ENTITY), parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
return methodBuilder.build();
}
/*
* =========================================================================
* =====
*/
/**
* Method that returns list Datatables JSON method
*
* @return
*/
public MethodMetadata getCurrentListDatatablesMethod() {
return this.listDatatablesMethod;
}
/**
* Method that returns create form Thymeleaf method
*
* @return
*/
public MethodMetadata getCurrentCreateFormMethod() {
return this.createFormMethod;
}
/**
* Method that returns create Thymeleaf method
*
* @return
*/
public MethodMetadata getCurrentCreateMethod() {
return this.createMethod;
}
/**
* Method that returns edit form Thymeleaf method
*
* @return
*/
public MethodMetadata getCurrentEditForm() {
return this.editFormMethod;
}
/**
* Method that returns update Thymeleaf method
*
* @return
*/
public MethodMetadata getCurrentUpdateMethod() {
return this.updateMethod;
}
/**
* Method that returns delete Thymeleaf method
*
* @return
*/
public MethodMetadata getCurrentDeleteMethod() {
return this.deleteMethod;
}
/**
* Method that returns show Thymeleaf method
*
* @return
*/
public MethodMetadata getCurrentShowMethod() {
return this.showMethod;
}
/**
* Method that returns populateForm method
*
* @return
*/
public MethodMetadata getCurrentPopulateFormMethod() {
return this.populateFormMethod;
}
/**
* Method that returns if related entity is readOnly or not.
*
* @return
*/
@Override
public boolean isReadOnly() {
return this.readOnly;
}
/**
* gets Mvc URL name for a controller method
*
* @param controller
* @param methodName
* @return
*/
public static String getMvcUrlNameFor(JavaType controller, JavaSymbolName methodName) {
return getMvcControllerName(controller) + "#" + getMvcMethodName(methodName);
}
/**
* gets Mvc URL name for a controller method
*
* @param controller
* @param methodName
* @return
*/
public static String getMvcUrlNameFor(JavaType controller, MethodMetadata method) {
return getMvcUrlNameFor(controller, method.getMethodName());
}
/**
* @return @RequestMapping.name annotation value
*/
public String getMvcControllerName() {
return getMvcControllerName(getDestination());
}
/**
* @return value to use in @RequestMapping.name
*/
public static String getMvcControllerName(JavaType thymeleaftController) {
return thymeleaftController.getSimpleTypeName();
}
public static String getMvcMethodName(JavaSymbolName methodName) {
return methodName.getSymbolName();
}
public MethodMetadata getCurrentListMethod() {
return listMethod;
}
public MethodMetadata getListDatatablesDetailsMethod() {
return listDatatablesDetailsMethod;
}
public MethodMetadata getListDatatablesByIdsInDetailsMethod() {
return listDatatablesByIdsInDetailsMethod;
}
@Override
public JavaType getEntity() {
return entity;
}
public ControllerMetadata getControllerMetadata() {
return controllerMetadata;
}
public JavaType getDetailItemController() {
return detailItemController;
}
public JavaType getDetailCollectionController() {
return detailCollectionController;
}
public JavaType getItemController() {
return itemController;
}
public JavaType getCollectionController() {
return collectionController;
}
public MethodMetadata getCurrentCreateFormDetailsMethod() {
return createFormDetailsMethod;
}
public MethodMetadata getCurrentRemoveFromDetailsMethod() {
return removeFromDetailsMethod;
}
public MethodMetadata getCurrentCreateDetailsMethod() {
return createDetailsMethod;
}
public MethodMetadata getCurrentDeleteDetailsMethod() {
return deleteDetailMethod;
}
public MethodMetadata getCurrentEditFormDetailsMethod() {
return editFormDetailMethod;
}
@Override
public String toString() {
final ToStringBuilder builder = new ToStringBuilder(this);
builder.append("identifier", getId());
builder.append("valid", valid);
builder.append("aspectName", aspectName);
builder.append("destinationType", destination);
builder.append("governor", governorPhysicalTypeMetadata.getId());
builder.append("itdTypeDetails", itdTypeDetails);
return builder.toString();
}
public JavaType getRelatedCollectionController() {
return relatedCollectionController;
}
public JavaType getRelatedItemController() {
return relatedItemController;
}
public Map<String, MethodMetadata> getFinderFormMethods() {
return finderFormMethods;
}
public Map<String, MethodMetadata> getFinderDatatableMethods() {
return finderDatatableMethods;
}
public Map<String, MethodMetadata> getFinderListMethods() {
return finderListMethods;
}
public List<MethodMetadata> getExportMethods() {
return exportMethods;
}
}