private MethodMetadata getDelegateMethod( final JavaSymbolName methodName, final String methodDelegateName) { // Method definition to find or build final JavaType[] parameterTypes = {}; // Locate user-defined method final MethodMetadata userMethod = getGovernorMethod(methodName, parameterTypes); if (userMethod != null) { return userMethod; } // Create the method final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>(); final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder(); // Address non-injected entity manager field final MethodMetadata entityManagerMethod = getEntityManagerMethod(); Assert.notNull(entityManagerMethod, "Entity manager method should not have returned null"); // Use the getEntityManager() method to acquire an entity manager (the method will throw an // exception if it cannot be acquired) final String entityManagerFieldName = getEntityManagerField().getFieldName().getSymbolName(); bodyBuilder.appendFormalLine( "if (this." + entityManagerFieldName + " == null) this." + entityManagerFieldName + " = " + entityManagerMethod.getMethodName().getSymbolName() + "();"); JavaType returnType = JavaType.VOID_PRIMITIVE; if ("flush".equals(methodDelegateName)) { addTransactionalAnnotation(annotations); bodyBuilder.appendFormalLine("this." + entityManagerFieldName + ".flush();"); } else if ("clear".equals(methodDelegateName)) { addTransactionalAnnotation(annotations); bodyBuilder.appendFormalLine("this." + entityManagerFieldName + ".clear();"); } else if ("merge".equals(methodDelegateName)) { addTransactionalAnnotation(annotations); returnType = new JavaType(destination.getSimpleTypeName()); bodyBuilder.appendFormalLine( destination.getSimpleTypeName() + " merged = this." + entityManagerFieldName + ".merge(this);"); bodyBuilder.appendFormalLine("this." + entityManagerFieldName + ".flush();"); bodyBuilder.appendFormalLine("return merged;"); } else if ("remove".equals(methodDelegateName)) { addTransactionalAnnotation(annotations); bodyBuilder.appendFormalLine("if (this." + entityManagerFieldName + ".contains(this)) {"); bodyBuilder.indent(); bodyBuilder.appendFormalLine("this." + entityManagerFieldName + ".remove(this);"); bodyBuilder.indentRemove(); bodyBuilder.appendFormalLine("} else {"); bodyBuilder.indent(); bodyBuilder.appendFormalLine( destination.getSimpleTypeName() + " attached = " + destination.getSimpleTypeName() + "." + getFindMethod().getMethodName().getSymbolName() + "(this." + identifierField.getFieldName().getSymbolName() + ");"); bodyBuilder.appendFormalLine("this." + entityManagerFieldName + ".remove(attached);"); bodyBuilder.indentRemove(); bodyBuilder.appendFormalLine("}"); } else { // Persist addTransactionalAnnotation(annotations, true); bodyBuilder.appendFormalLine( "this." + entityManagerFieldName + "." + methodDelegateName + "(this);"); } final MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder( getId(), Modifier.PUBLIC, methodName, returnType, AnnotatedJavaType.convertFromJavaTypes(parameterTypes), new ArrayList<JavaSymbolName>(), bodyBuilder); methodBuilder.setAnnotations(annotations); return methodBuilder.build(); }
/** * @return the static utility entityManager() method used by other methods to obtain entity * manager and available as a utility for user code (never returns nulls) */ public MethodMetadata getEntityManagerMethod() { if (parent != null) { // The parent is required to guarantee this is available return parent.getEntityManagerMethod(); } // Method definition to find or build final JavaSymbolName methodName = new JavaSymbolName(ENTITY_MANAGER_METHOD_NAME); final JavaType[] parameterTypes = {}; final JavaType returnType = ENTITY_MANAGER; // Locate user-defined method final MethodMetadata userMethod = getGovernorMethod(methodName, parameterTypes); if (userMethod != null) { Assert.isTrue( userMethod.getReturnType().equals(returnType), "Method '" + methodName + "' on '" + destination + "' must return '" + returnType.getNameIncludingTypeParameters() + "'"); return userMethod; } // Create method final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder(); if (Modifier.isAbstract(governorTypeDetails.getModifier())) { // Create an anonymous inner class that extends the abstract class (no-arg constructor is // available as this is a JPA entity) bodyBuilder.appendFormalLine( ENTITY_MANAGER.getNameIncludingTypeParameters( false, builder.getImportRegistrationResolver()) + " em = new " + destination.getSimpleTypeName() + "() {"); // Handle any abstract methods in this class bodyBuilder.indent(); for (final MethodMetadata method : governorTypeDetails.getMethods()) { if (Modifier.isAbstract(method.getModifier())) { final StringBuilder params = new StringBuilder(); int i = -1; final List<AnnotatedJavaType> types = method.getParameterTypes(); for (final JavaSymbolName name : method.getParameterNames()) { i++; if (i > 0) { params.append(", "); } final AnnotatedJavaType type = types.get(i); params.append(type.toString()).append(" ").append(name); } final int newModifier = method.getModifier() - Modifier.ABSTRACT; bodyBuilder.appendFormalLine( Modifier.toString(newModifier) + " " + method.getReturnType().getNameIncludingTypeParameters() + " " + method.getMethodName().getSymbolName() + "(" + params.toString() + ") {"); bodyBuilder.indent(); bodyBuilder.appendFormalLine("throw new UnsupportedOperationException();"); bodyBuilder.indentRemove(); bodyBuilder.appendFormalLine("}"); } } bodyBuilder.indentRemove(); bodyBuilder.appendFormalLine( "}." + getEntityManagerField().getFieldName().getSymbolName() + ";"); } else { // Instantiate using the no-argument constructor (we know this is available as the entity must // comply with the JPA no-arg constructor requirement) bodyBuilder.appendFormalLine( ENTITY_MANAGER.getNameIncludingTypeParameters( false, builder.getImportRegistrationResolver()) + " em = new " + destination.getSimpleTypeName() + "()." + getEntityManagerField().getFieldName().getSymbolName() + ";"); } bodyBuilder.appendFormalLine( "if (em == null) throw new IllegalStateException(\"Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)\");"); bodyBuilder.appendFormalLine("return em;"); final int modifier = Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL; final MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder( getId(), modifier, methodName, returnType, AnnotatedJavaType.convertFromJavaTypes(parameterTypes), new ArrayList<JavaSymbolName>(), bodyBuilder); return methodBuilder.build(); }
private MethodMetadataBuilder getFinderMethod(final FinderMetadataDetails finderMetadataDetails) { Validate.notNull(finderMetadataDetails, "Method metadata required for finder"); final JavaSymbolName finderMethodName = new JavaSymbolName( finderMetadataDetails.getFinderMethodMetadata().getMethodName().getSymbolName()); final List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>(); final List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>(); final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder(); final StringBuilder methodParams = new StringBuilder(); boolean dateFieldPresent = !dateTypes.isEmpty(); for (final FieldMetadata field : finderMetadataDetails.getFinderMethodParamFields()) { final JavaSymbolName fieldName = field.getFieldName(); final List<AnnotationMetadata> annotations = new ArrayList<AnnotationMetadata>(); final List<AnnotationAttributeValue<?>> attributes = new ArrayList<AnnotationAttributeValue<?>>(); attributes.add( new StringAttributeValue( new JavaSymbolName("value"), uncapitalize(fieldName.getSymbolName()))); if (field.getFieldType().equals(JavaType.BOOLEAN_PRIMITIVE) || field.getFieldType().equals(JavaType.BOOLEAN_OBJECT)) { attributes.add(new BooleanAttributeValue(new JavaSymbolName("required"), false)); } final AnnotationMetadataBuilder requestParamAnnotation = new AnnotationMetadataBuilder(REQUEST_PARAM, attributes); annotations.add(requestParamAnnotation.build()); if (field.getFieldType().equals(DATE) || field.getFieldType().equals(CALENDAR)) { dateFieldPresent = true; final AnnotationMetadata annotation = MemberFindingUtils.getAnnotationOfType(field.getAnnotations(), DATE_TIME_FORMAT); if (annotation != null) { getShortName(DATE_TIME_FORMAT); annotations.add(annotation); } } parameterNames.add(fieldName); parameterTypes.add(new AnnotatedJavaType(field.getFieldType(), annotations)); if (field.getFieldType().equals(JavaType.BOOLEAN_OBJECT)) { methodParams.append(fieldName + " == null ? Boolean.FALSE : " + fieldName + ", "); } else { methodParams.append(fieldName + ", "); } } if (methodParams.length() > 0) { methodParams.delete(methodParams.length() - 2, methodParams.length()); } final List<AnnotationAttributeValue<?>> firstResultAttributes = new ArrayList<AnnotationAttributeValue<?>>(); firstResultAttributes.add(new StringAttributeValue(new JavaSymbolName("value"), "page")); firstResultAttributes.add(new BooleanAttributeValue(new JavaSymbolName("required"), false)); final AnnotationMetadataBuilder firstResultAnnotation = new AnnotationMetadataBuilder(REQUEST_PARAM, firstResultAttributes); final List<AnnotationAttributeValue<?>> maxResultsAttributes = new ArrayList<AnnotationAttributeValue<?>>(); maxResultsAttributes.add(new StringAttributeValue(new JavaSymbolName("value"), "size")); maxResultsAttributes.add(new BooleanAttributeValue(new JavaSymbolName("required"), false)); final AnnotationMetadataBuilder maxResultAnnotation = new AnnotationMetadataBuilder(REQUEST_PARAM, maxResultsAttributes); final List<AnnotationAttributeValue<?>> sortFieldNameAttributes = new ArrayList<AnnotationAttributeValue<?>>(); sortFieldNameAttributes.add( new StringAttributeValue(new JavaSymbolName("value"), "sortFieldName")); sortFieldNameAttributes.add(new BooleanAttributeValue(new JavaSymbolName("required"), false)); final AnnotationMetadataBuilder sortFieldNameAnnotation = new AnnotationMetadataBuilder(REQUEST_PARAM, sortFieldNameAttributes); final List<AnnotationAttributeValue<?>> sortOrderAttributes = new ArrayList<AnnotationAttributeValue<?>>(); sortOrderAttributes.add(new StringAttributeValue(new JavaSymbolName("value"), "sortOrder")); sortOrderAttributes.add(new BooleanAttributeValue(new JavaSymbolName("required"), false)); final AnnotationMetadataBuilder sortOrderAnnotation = new AnnotationMetadataBuilder(REQUEST_PARAM, sortOrderAttributes); parameterTypes.add( new AnnotatedJavaType( new JavaType(Integer.class.getName()), firstResultAnnotation.build())); parameterTypes.add( new AnnotatedJavaType(new JavaType(Integer.class.getName()), maxResultAnnotation.build())); parameterTypes.add( new AnnotatedJavaType( new JavaType(String.class.getName()), sortFieldNameAnnotation.build())); parameterTypes.add( new AnnotatedJavaType(new JavaType(String.class.getName()), sortOrderAnnotation.build())); parameterTypes.add(new AnnotatedJavaType(MODEL)); if (getGovernorMethod( finderMethodName, AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes)) != null) { return null; } final List<JavaSymbolName> newParamNames = new ArrayList<JavaSymbolName>(); newParamNames.addAll(parameterNames); newParamNames.add(new JavaSymbolName("page")); newParamNames.add(new JavaSymbolName("size")); newParamNames.add(new JavaSymbolName("sortFieldName")); newParamNames.add(new JavaSymbolName("sortOrder")); newParamNames.add(new JavaSymbolName("uiModel")); final List<AnnotationAttributeValue<?>> requestMappingAttributes = new ArrayList<AnnotationAttributeValue<?>>(); requestMappingAttributes.add( new StringAttributeValue( new JavaSymbolName("params"), "find=" + finderMetadataDetails .getFinderMethodMetadata() .getMethodName() .getSymbolName() .replaceFirst("find" + javaTypeMetadataHolder.getPlural(), ""))); requestMappingAttributes.add( new EnumAttributeValue( new JavaSymbolName("method"), new EnumDetails(REQUEST_METHOD, new JavaSymbolName("GET")))); final AnnotationMetadataBuilder requestMapping = new AnnotationMetadataBuilder(REQUEST_MAPPING, requestMappingAttributes); final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>(); annotations.add(requestMapping); bodyBuilder.appendFormalLine("if (page != null || size != null) {"); bodyBuilder.indent(); bodyBuilder.appendFormalLine("int sizeNo = size == null ? 10 : size.intValue();"); bodyBuilder.appendFormalLine( "final int firstResult = page == null ? 0 : (page.intValue() - 1) * sizeNo;"); String methodParamsString = methodParams.toString(); if (StringUtils.isNotBlank(methodParamsString)) { methodParamsString.concat(", "); } bodyBuilder.appendFormalLine( "uiModel.addAttribute(\"" + javaTypeMetadataHolder.getPlural().toLowerCase() + "\", " + getShortName(formBackingType) + "." + finderMetadataDetails.getFinderMethodMetadata().getMethodName().getSymbolName() + "(" + methodParamsString + "sortFieldName, sortOrder).setFirstResult(firstResult).setMaxResults(sizeNo).getResultList());"); char[] methodNameArray = finderMetadataDetails .getFinderMethodMetadata() .getMethodName() .getSymbolName() .toCharArray(); methodNameArray[0] = Character.toUpperCase(methodNameArray[0]); String countMethodName = "count" + new String(methodNameArray); bodyBuilder.appendFormalLine( "float nrOfPages = (float) " + getShortName(formBackingType) + "." + countMethodName + "(" + methodParamsString + ") / sizeNo;"); bodyBuilder.appendFormalLine( "uiModel.addAttribute(\"maxPages\", (int) ((nrOfPages > (int) nrOfPages || nrOfPages == 0.0) ? nrOfPages + 1 : nrOfPages));"); bodyBuilder.indentRemove(); bodyBuilder.appendFormalLine("} else {"); bodyBuilder.indent(); bodyBuilder.appendFormalLine( "uiModel.addAttribute(\"" + javaTypeMetadataHolder.getPlural().toLowerCase() + "\", " + getShortName(formBackingType) + "." + finderMetadataDetails.getFinderMethodMetadata().getMethodName().getSymbolName() + "(" + methodParamsString + "sortFieldName, sortOrder).getResultList());"); bodyBuilder.indentRemove(); bodyBuilder.appendFormalLine("}"); if (dateFieldPresent) { bodyBuilder.appendFormalLine("addDateTimeFormatPatterns(uiModel);"); } bodyBuilder.appendFormalLine("return \"" + controllerPath + "/list\";"); final MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder( getId(), Modifier.PUBLIC, finderMethodName, JavaType.STRING, parameterTypes, newParamNames, bodyBuilder); methodBuilder.setAnnotations(annotations); return methodBuilder; }