/addon-layers-service/src/main/java/org/springframework/roo/addon/layers/service/ServiceClassMetadata.java

http://github.com/SpringSource/spring-roo · Java · 168 lines · 125 code · 16 blank · 27 comment · 10 complexity · 3c6b814649b67ee95748eb6d2db62536 MD5 · raw file

  1. package org.springframework.roo.addon.layers.service;
  2. import static org.springframework.roo.model.SpringJavaType.SERVICE;
  3. import static org.springframework.roo.model.SpringJavaType.TRANSACTIONAL;
  4. import java.lang.reflect.Modifier;
  5. import java.util.Map;
  6. import java.util.Map.Entry;
  7. import org.apache.commons.lang3.Validate;
  8. import org.apache.commons.lang3.builder.ToStringBuilder;
  9. import org.springframework.roo.classpath.PhysicalTypeIdentifierNamingUtils;
  10. import org.springframework.roo.classpath.PhysicalTypeMetadata;
  11. import org.springframework.roo.classpath.details.ClassOrInterfaceTypeDetails;
  12. import org.springframework.roo.classpath.details.MethodMetadataBuilder;
  13. import org.springframework.roo.classpath.details.annotations.AnnotatedJavaType;
  14. import org.springframework.roo.classpath.details.annotations.AnnotationMetadata;
  15. import org.springframework.roo.classpath.details.annotations.AnnotationMetadataBuilder;
  16. import org.springframework.roo.classpath.itd.AbstractItdTypeDetailsProvidingMetadataItem;
  17. import org.springframework.roo.classpath.itd.InvocableMemberBodyBuilder;
  18. import org.springframework.roo.classpath.layers.MemberTypeAdditions;
  19. import org.springframework.roo.classpath.scanner.MemberDetails;
  20. import org.springframework.roo.metadata.MetadataIdentificationUtils;
  21. import org.springframework.roo.model.JavaSymbolName;
  22. import org.springframework.roo.model.JavaType;
  23. import org.springframework.roo.project.LogicalPath;
  24. /**
  25. * @author Stefan Schmidt
  26. * @since 1.2.0
  27. */
  28. public class ServiceClassMetadata extends
  29. AbstractItdTypeDetailsProvidingMetadataItem {
  30. private static final String PROVIDES_TYPE_STRING = ServiceClassMetadata.class
  31. .getName();
  32. private static final String PROVIDES_TYPE = MetadataIdentificationUtils
  33. .create(PROVIDES_TYPE_STRING);
  34. public static String createIdentifier(final JavaType javaType,
  35. final LogicalPath path) {
  36. return PhysicalTypeIdentifierNamingUtils.createIdentifier(
  37. PROVIDES_TYPE_STRING, javaType, path);
  38. }
  39. public static JavaType getJavaType(final String metadataIdentificationString) {
  40. return PhysicalTypeIdentifierNamingUtils.getJavaType(
  41. PROVIDES_TYPE_STRING, metadataIdentificationString);
  42. }
  43. public static String getMetadataIdentiferType() {
  44. return PROVIDES_TYPE;
  45. }
  46. public static LogicalPath getPath(final String metadataIdentificationString) {
  47. return PhysicalTypeIdentifierNamingUtils.getPath(PROVIDES_TYPE_STRING,
  48. metadataIdentificationString);
  49. }
  50. public static boolean isValid(final String metadataIdentificationString) {
  51. return PhysicalTypeIdentifierNamingUtils.isValid(PROVIDES_TYPE_STRING,
  52. metadataIdentificationString);
  53. }
  54. /**
  55. * Constructor
  56. *
  57. * @param identifier the identifier for this item of metadata (required)
  58. * @param aspectName the Java type of the ITD (required)
  59. * @param governorPhysicalTypeMetadata the governor, which is expected to
  60. * contain a {@link ClassOrInterfaceTypeDetails} (required)
  61. * @param governorDetails (required)
  62. * @param annotationValues (required)
  63. * @param domainTypeToIdTypeMap (required)
  64. * @param allCrudAdditions any additions to be made to the service class in
  65. * order to invoke lower-layer methods (required)
  66. * @param domainTypePlurals the plurals of each domain type managed by the
  67. * service
  68. */
  69. public ServiceClassMetadata(
  70. final String identifier,
  71. final JavaType aspectName,
  72. final PhysicalTypeMetadata governorPhysicalTypeMetadata,
  73. final MemberDetails governorDetails,
  74. final ServiceAnnotationValues annotationValues,
  75. final Map<JavaType, JavaType> domainTypeToIdTypeMap,
  76. final Map<JavaType, Map<ServiceLayerMethod, MemberTypeAdditions>> allCrudAdditions,
  77. final Map<JavaType, String> domainTypePlurals) {
  78. super(identifier, aspectName, governorPhysicalTypeMetadata);
  79. Validate.notNull(allCrudAdditions, "CRUD additions required");
  80. Validate.notNull(annotationValues, "Annotation values required");
  81. Validate.notNull(governorDetails, "Governor details required");
  82. Validate.notNull(domainTypePlurals, "Domain type plurals required");
  83. for (final Entry<JavaType, JavaType> entry : domainTypeToIdTypeMap
  84. .entrySet()) {
  85. final JavaType domainType = entry.getKey();
  86. final JavaType idType = entry.getValue();
  87. final Map<ServiceLayerMethod, MemberTypeAdditions> crudAdditions = allCrudAdditions
  88. .get(domainType);
  89. for (final ServiceLayerMethod method : ServiceLayerMethod.values()) {
  90. final JavaSymbolName methodName = method.getSymbolName(
  91. annotationValues, domainType,
  92. domainTypePlurals.get(domainType));
  93. if (methodName != null
  94. && !governorDetails.isMethodDeclaredByAnother(
  95. methodName,
  96. method.getParameterTypes(domainType, idType),
  97. getId())) {
  98. // The method is desired and the service class' Java file
  99. // doesn't contain it, so generate it
  100. final MemberTypeAdditions lowerLayerCallAdditions = crudAdditions
  101. .get(method);
  102. if (lowerLayerCallAdditions != null) {
  103. // A lower layer implements it
  104. lowerLayerCallAdditions.copyAdditionsTo(builder,
  105. governorTypeDetails);
  106. }
  107. final String body = method.getBody(lowerLayerCallAdditions);
  108. final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
  109. bodyBuilder.appendFormalLine(body);
  110. builder.addMethod(new MethodMetadataBuilder(getId(),
  111. Modifier.PUBLIC, methodName, method
  112. .getReturnType(domainType),
  113. AnnotatedJavaType.convertFromJavaTypes(method
  114. .getParameterTypes(domainType, idType)),
  115. method.getParameterNames(domainType, idType),
  116. bodyBuilder));
  117. }
  118. }
  119. }
  120. // Introduce the @Service annotation via the ITD if it's not already on
  121. // the service's Java class
  122. final AnnotationMetadata serviceAnnotation = new AnnotationMetadataBuilder(
  123. SERVICE).build();
  124. if (!governorDetails.isRequestingAnnotatedWith(serviceAnnotation,
  125. getId())) {
  126. builder.addAnnotation(serviceAnnotation);
  127. }
  128. // Introduce the @Transactional annotation via the ITD if it's not
  129. // already on the service's Java class
  130. if (annotationValues.isTransactional()) {
  131. final AnnotationMetadata transactionalAnnotation = new AnnotationMetadataBuilder(
  132. TRANSACTIONAL).build();
  133. if (!governorDetails.isRequestingAnnotatedWith(serviceAnnotation,
  134. getId())) {
  135. builder.addAnnotation(transactionalAnnotation);
  136. }
  137. }
  138. // Create a representation of the desired output ITD
  139. itdTypeDetails = builder.build();
  140. }
  141. @Override
  142. public String toString() {
  143. final ToStringBuilder builder = new ToStringBuilder(this);
  144. builder.append("identifier", getId());
  145. builder.append("valid", valid);
  146. builder.append("aspectName", aspectName);
  147. builder.append("destinationType", destination);
  148. builder.append("governor", governorPhysicalTypeMetadata.getId());
  149. builder.append("itdTypeDetails", itdTypeDetails);
  150. return builder.toString();
  151. }
  152. }