package org.springframework.roo.addon.web.mvc.controller.addon.config;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
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.MethodMetadata;
import org.springframework.roo.classpath.details.MethodMetadataBuilder;
import org.springframework.roo.classpath.details.annotations.AnnotatedJavaType;
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.JavaSymbolName;
import org.springframework.roo.model.JavaType;
import org.springframework.roo.model.JdkJavaType;
import org.springframework.roo.model.SpringJavaType;
import org.springframework.roo.project.LogicalPath;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
/**
* Metadata for {@link RooWebMVCConfiguration}.
*
* @author Juan Carlos García
* @author Jose Manuel Vivó
* @since 2.0
*/
public class WebMvcConfigurationMetadata extends AbstractItdTypeDetailsProvidingMetadataItem {
private static final String PROVIDES_TYPE_STRING = WebMvcConfigurationMetadata.class.getName();
private static final String PROVIDES_TYPE = MetadataIdentificationUtils
.create(PROVIDES_TYPE_STRING);
private static final JavaType TRACEE_INTERCEPTOR_JAVATYPE = new JavaType(
"io.tracee.binding.springmvc.TraceeInterceptor");
public static String createIdentifier(final JavaType javaType, final LogicalPath path) {
return PhysicalTypeIdentifierNamingUtils.createIdentifier(PROVIDES_TYPE_STRING, javaType, path);
}
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)
*
*/
public WebMvcConfigurationMetadata(final String identifier, final JavaType aspectName,
final PhysicalTypeMetadata governorPhysicalTypeMetadata, final String defaultLanguage) {
super(identifier, aspectName, governorPhysicalTypeMetadata);
// Add @Configuration
ensureGovernorIsAnnotated(new AnnotationMetadataBuilder(SpringJavaType.CONFIGURATION));
// Add extends WebMvcConfigurerAdapter
ensureGovernorExtends(SpringJavaType.WEB_MVC_CONFIGURER_ADAPTER);
// Add validator method
ensureGovernorHasMethod(new MethodMetadataBuilder(getValidatorMethod()));
// Add localResolver
ensureGovernorHasMethod(new MethodMetadataBuilder(getLocaleResolver(defaultLanguage)));
// Add localeChangeInterceptor
ensureGovernorHasMethod(new MethodMetadataBuilder(getLocaleChangeInterceptor()));
// Add addInterceptors
ensureGovernorHasMethod(new MethodMetadataBuilder(getAddInterceptors()));
// Build the ITD
itdTypeDetails = builder.build();
}
/**
* Method that generates "validator" method.
*
* @return MethodMetadata
*/
private MethodMetadata getValidatorMethod() {
// Define method name
JavaSymbolName methodName = new JavaSymbolName("validator");
// Define method parameter types
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
// Define method parameter names
List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
if (governorHasMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes))) {
return getGovernorMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes));
}
// Generate body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
// return new LocalValidatorFactoryBean();
bodyBuilder.appendFormalLine("return new %s();",
getNameOfJavaType(SpringJavaType.LOCAL_VALIDATOR_FACTORY_BEAN));
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder =
new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName,
SpringJavaType.LOCAL_VALIDATOR_FACTORY_BEAN, parameterTypes, parameterNames,
bodyBuilder);
// Add @Bean and @Primary annotations
methodBuilder.addAnnotation(new AnnotationMetadataBuilder(SpringJavaType.PRIMARY));
methodBuilder.addAnnotation(new AnnotationMetadataBuilder(SpringJavaType.BEAN));
// Build and return a MethodMetadata instance
return methodBuilder.build();
}
/**
* Method that generates "localeResolver" method.
*
* @return MethodMetadata
*/
private MethodMetadata getLocaleResolver(String defaultLanguage) {
// Define method name
JavaSymbolName methodName = new JavaSymbolName("localeResolver");
// Define method parameter types
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
// Define method parameter names
List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
// Define method return type
JavaType returnType = SpringJavaType.LOCALE_RESOLVER;
if (governorHasMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes))) {
return getGovernorMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes));
}
// Generate body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
// SessionLocaleResolver localeResolver = new SessionLocaleResolver();
bodyBuilder.appendFormalLine("%1$s localeResolver = new %1$s();",
getNameOfJavaType(SpringJavaType.SESSION_LOCALE_RESOLVER));
// localeResolver.setDefaultLocale(new Locale(\"en\", \"EN\"));
if (StringUtils.isNotBlank(defaultLanguage)) {
bodyBuilder.appendFormalLine("localeResolver.setDefaultLocale(new %s(\"%s\"));",
getNameOfJavaType(JdkJavaType.LOCALE), defaultLanguage);
}
// return
bodyBuilder.appendFormalLine("return localeResolver;");
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder =
new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName, returnType, parameterTypes,
parameterNames, bodyBuilder);
// Add Bean annotation
methodBuilder.addAnnotation(new AnnotationMetadataBuilder(SpringJavaType.BEAN));
return methodBuilder.build(); // Build and return a MethodMetadata
// instance
}
/**
* Method that generates "localeChangeInterceptor" method.
*
* @return MethodMetadata
*/
private MethodMetadata getLocaleChangeInterceptor() {
// Define method name
JavaSymbolName methodName = new JavaSymbolName("localeChangeInterceptor");
// Define method parameter types
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
// Define method parameter names
List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
// Define method return type
JavaType returnType =
new JavaType("org.springframework.web.servlet.i18n.LocaleChangeInterceptor");
if (governorHasMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes))) {
return getGovernorMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes));
}
// Generate body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
bodyBuilder
.appendFormalLine("LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();");
bodyBuilder.appendFormalLine("localeChangeInterceptor.setParamName(\"lang\");");
// return
bodyBuilder.appendFormalLine("return localeChangeInterceptor;");
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder =
new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName, returnType, parameterTypes,
parameterNames, bodyBuilder);
// Add Bean annotation
methodBuilder.addAnnotation(new AnnotationMetadataBuilder(SpringJavaType.BEAN));
return methodBuilder.build(); // Build and return a MethodMetadata
// instance
}
/**
* Method that generates "addInterceptors" method.
*
* @return MethodMetadata
*/
private MethodMetadata getAddInterceptors() {
// Define method name
JavaSymbolName methodName = new JavaSymbolName("addInterceptors");
// Define method parameter types
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
parameterTypes.add(AnnotatedJavaType.convertFromJavaType(new JavaType(
"org.springframework.web.servlet.config.annotation.InterceptorRegistry")));
// Define method parameter names
List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(new JavaSymbolName("registry"));
if (governorHasMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes))) {
return getGovernorMethod(methodName,
AnnotatedJavaType.convertFromAnnotatedJavaTypes(parameterTypes));
}
// Generate body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
bodyBuilder.appendFormalLine("registry.addInterceptor(localeChangeInterceptor());");
// Add TracEE interceptor
bodyBuilder.appendFormalLine("registry.addInterceptor(new %s());",
getNameOfJavaType(TRACEE_INTERCEPTOR_JAVATYPE));
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder =
new MethodMetadataBuilder(getId(), Modifier.PUBLIC, methodName, JavaType.VOID_PRIMITIVE,
parameterTypes, parameterNames, bodyBuilder);
// Add Bean annotation
methodBuilder.addAnnotation(new AnnotationMetadataBuilder(JavaType.OVERRIDE));
return methodBuilder.build(); // Build and return a MethodMetadata
// instance
}
@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();
}
}