package org.springframework.roo.addon.web.mvc.controller.addon.test;
import java.lang.reflect.Modifier;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.springframework.roo.addon.web.mvc.controller.annotations.test.RooJsonControllerIntegrationTest;
import org.springframework.roo.classpath.PhysicalTypeIdentifierNamingUtils;
import org.springframework.roo.classpath.PhysicalTypeMetadata;
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.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.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.SpringJavaType;
import org.springframework.roo.model.SpringletsJavaType;
import org.springframework.roo.project.LogicalPath;
/**
* Metadata for {@link RooJsonControllerIntegrationTest}.
*
* @author Sergio Clares
* @since 2.0
*/
public class JsonControllerIntegrationTestMetadata extends
AbstractItdTypeDetailsProvidingMetadataItem {
private static final String PROVIDES_TYPE_STRING = JsonControllerIntegrationTestMetadata.class
.getName();
private static final String PROVIDES_TYPE = MetadataIdentificationUtils
.create(PROVIDES_TYPE_STRING);
private static final JavaSymbolName MOCK_MVC_FIELD_NAME = new JavaSymbolName("mvc");
private static final JavaType RUN_WITH = new JavaType("org.junit.runner.RunWith");
private static final JavaType TEST = new JavaType("org.junit.Test");
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);
}
private final JavaType controller;
private final JavaType entityService;
private final JavaType entityFactory;
private final JavaSymbolName serviceFieldName;
private final JavaSymbolName entityFactoryFieldName;
/**
* Constructor
*
* @param identifier
* @param aspectName
* @param governorPhysicalTypeMetadata
* @param annotationValues
* @param controller
* @param managedEntity
* @param entityFactory
* @param entityService
*/
public JsonControllerIntegrationTestMetadata(final String identifier, final JavaType aspectName,
final PhysicalTypeMetadata governorPhysicalTypeMetadata,
final JsonControllerIntegrationTestAnnotationValues annotationValues,
final JavaType controller, final JavaType managedEntity, final JavaType entityFactory,
final JavaType entityService) {
super(identifier, aspectName, governorPhysicalTypeMetadata);
Validate.isTrue(isValid(identifier),
"Metadata identification string '%s' does not appear to be a valid", identifier);
Validate.notNull(annotationValues, "Annotation values required");
this.controller = controller;
this.entityService = entityService;
this.entityFactory = entityFactory;
this.serviceFieldName =
new JavaSymbolName(String.format("%sService",
StringUtils.uncapitalize(managedEntity.getSimpleTypeName())));
this.entityFactoryFieldName = new JavaSymbolName("factory");
// Add @RunWith(SpringRunner.class)
ensureGovernorIsAnnotated(getRunWithAnnotation());
// Add @SpringletsWebMvcTest
ensureGovernorIsAnnotated(getSpringletsWebMvcAnnotation());
// Add MockMvc field
ensureGovernorHasField(getMockMvcField());
// Add entity service field
ensureGovernorHasField(getEntityServiceField());
// Add entity factory field
ensureGovernorHasField(getEntityFactoryField());
// Add test method example
ensureGovernorHasMethod(new MethodMetadataBuilder(getTestExampleMethod()));
itdTypeDetails = builder.build();
}
/**
* Builds and return a test example method.
*
* @return {@link MethodMetadata}
*/
private MethodMetadata getTestExampleMethod() {
JavaSymbolName methodName = new JavaSymbolName("testMethodExample");
// Check if method exists in governor
MethodMetadata method = getGovernorMethod(methodName);
if (method != null) {
return method;
}
// Build method body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
// Setup
bodyBuilder.appendFormalLine("// Setup");
bodyBuilder.appendFormalLine("// Previous tasks");
bodyBuilder.newLine();
// Exercise
bodyBuilder.appendFormalLine("// Exercise");
bodyBuilder.appendFormalLine("// Execute method to test");
bodyBuilder.newLine();
// Verify
bodyBuilder.appendFormalLine("// Verify");
bodyBuilder.appendFormalLine("// Check results with assertions");
MethodMetadataBuilder methodBuilder =
new MethodMetadataBuilder(this.getId(), Modifier.PUBLIC, methodName,
JavaType.VOID_PRIMITIVE, bodyBuilder);
// Add @Test
methodBuilder.addAnnotation(new AnnotationMetadataBuilder(TEST));
CommentStructure commentStructure = new CommentStructure();
commentStructure.addComment(new JavadocComment(
"Test method example. To be implemented by developer."), CommentLocation.BEGINNING);
methodBuilder.setCommentStructure(commentStructure);
return methodBuilder.build();
}
/**
* Builds and returns the entity factory field.
*
* @return {@link FieldMetadataBuilder}
*/
private FieldMetadataBuilder getEntityFactoryField() {
FieldMetadataBuilder fieldBuilder =
new FieldMetadataBuilder(this.getId(), Modifier.PRIVATE, this.entityFactoryFieldName,
this.entityFactory, String.format("new %s()", getNameOfJavaType(this.entityFactory)));
return fieldBuilder;
}
/**
* Builds and returns the entity service field, annotated with @MockBean
*
* @return {@link FieldMetadataBuilder}
*/
private FieldMetadataBuilder getEntityServiceField() {
FieldMetadataBuilder fieldBuilder =
new FieldMetadataBuilder(this.getId(), Modifier.PRIVATE, this.serviceFieldName,
this.entityService, null);
// Add @Autowired
fieldBuilder.addAnnotation(new AnnotationMetadataBuilder(SpringJavaType.MOCK_BEAN));
return fieldBuilder;
}
/**
* Builds and returns a {@link MockMvc} field, annotated with @Autowired
*
* @return {@link FieldMetadataBuilder}
*/
private FieldMetadataBuilder getMockMvcField() {
FieldMetadataBuilder fieldBuilder =
new FieldMetadataBuilder(this.getId(), Modifier.PRIVATE, MOCK_MVC_FIELD_NAME,
SpringJavaType.MOCK_MVC, null);
// Add @Autowired
fieldBuilder.addAnnotation(new AnnotationMetadataBuilder(SpringJavaType.AUTOWIRED));
return fieldBuilder;
}
/**
* Builds and returns `@RunWith` annotation
*
* @return {@link AnnotationMetadataBuilder}
*/
private AnnotationMetadataBuilder getRunWithAnnotation() {
AnnotationMetadataBuilder annotationBuilder = new AnnotationMetadataBuilder(RUN_WITH);
annotationBuilder.addClassAttribute("value", SpringJavaType.SPRING_RUNNER);
return annotationBuilder;
}
/**
* Builds and returns @SpringletsWebMvcTest annotation
*
* @return {@link AnnotationMetadataBuilder}
*/
private AnnotationMetadataBuilder getSpringletsWebMvcAnnotation() {
AnnotationMetadataBuilder annotationBuilder =
new AnnotationMetadataBuilder(SpringletsJavaType.SPRINGLETS_WEB_MVC_TEST);
annotationBuilder.addClassAttribute("controllers", this.controller);
annotationBuilder.addBooleanAttribute("secure", false);
return annotationBuilder;
}
@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();
}
}