package org.springframework.roo.addon.web.mvc.controller.addon.config; import org.apache.commons.lang3.builder.ToStringBuilder; import org.springframework.roo.addon.web.mvc.controller.annotations.config.RooDomainModelModule; 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.annotations.AnnotationMetadataBuilder; import org.springframework.roo.classpath.itd.AbstractItdTypeDetailsProvidingMetadataItem; import org.springframework.roo.classpath.itd.InvocableMemberBodyBuilder; import org.springframework.roo.metadata.MetadataIdentificationUtils; import org.springframework.roo.model.JavaType; import org.springframework.roo.project.LogicalPath; import java.lang.reflect.Modifier; import java.util.Collections; import java.util.Map; import java.util.Map.Entry; import java.util.TreeMap; /** * Metadata for {@link RooDomainModelModule}. * * @author Jose Manuel Vivó * @since 2.0 */ public class DomainModelModuleMetadata extends AbstractItdTypeDetailsProvidingMetadataItem { private static final JavaType JACKSON_SIMPLE_MODULE = new JavaType( "com.fasterxml.jackson.databind.module.SimpleModule"); private static final JavaType BOOT_JACKSON_JSON_COMPONENT = new JavaType( "org.springframework.boot.jackson.JsonComponent"); private static final String PROVIDES_TYPE_STRING = DomainModelModuleMetadata.class.getName(); private static final String PROVIDES_TYPE = MetadataIdentificationUtils .create(PROVIDES_TYPE_STRING); 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); } private final Map<JavaType, JavaType> mixins; /** * 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) * */ public DomainModelModuleMetadata(final String identifier, final JavaType aspectName, final PhysicalTypeMetadata governorPhysicalTypeMetadata, final Map<JavaType, JavaType> mixins) { super(identifier, aspectName, governorPhysicalTypeMetadata); Map<JavaType, JavaType> orderedMixins = new TreeMap<JavaType, JavaType>(mixins); this.mixins = Collections.unmodifiableMap(orderedMixins); // Add @Configuration ensureGovernorIsAnnotated(new AnnotationMetadataBuilder(BOOT_JACKSON_JSON_COMPONENT)); // Add extends WebMvcConfigurerAdapter ensureGovernorExtends(JACKSON_SIMPLE_MODULE); // Add constructor ensureGovernorHasConstructor(new ConstructorMetadataBuilder(getConstructor())); // Build the ITD itdTypeDetails = builder.build(); } private ConstructorMetadata getConstructor() { InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder(); // Generating constructor ConstructorMetadataBuilder constructor = new ConstructorMetadataBuilder(getId()); constructor.setModifier(Modifier.PUBLIC); bodyBuilder.appendFormalLine("// Mixin registration"); bodyBuilder.newLine(); // Generating body for (Entry<JavaType, JavaType> item : mixins.entrySet()) { bodyBuilder.appendFormalLine("setMixInAnnotation(%s.class, %s.class);", getNameOfJavaType(item.getKey()), getNameOfJavaType(item.getValue())); } // Adding body constructor.setBodyBuilder(bodyBuilder); return constructor.build(); } /** * @return registered mixins */ public Map<JavaType, JavaType> getMixins() { return this.mixins; } @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(); } }