package org.springframework.roo.addon.web.mvc.controller.finder;
import java.util.HashSet;
import java.util.Set;
import org.apache.commons.lang3.Validate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.springframework.roo.addon.web.mvc.controller.ControllerOperations;
import org.springframework.roo.addon.web.mvc.controller.scaffold.WebScaffoldAnnotationValues;
import org.springframework.roo.classpath.PhysicalTypeDetails;
import org.springframework.roo.classpath.PhysicalTypeIdentifier;
import org.springframework.roo.classpath.PhysicalTypeMetadata;
import org.springframework.roo.classpath.TypeLocationService;
import org.springframework.roo.classpath.TypeManagementService;
import org.springframework.roo.classpath.details.ClassOrInterfaceTypeDetails;
import org.springframework.roo.classpath.details.ClassOrInterfaceTypeDetailsBuilder;
import org.springframework.roo.classpath.details.MemberFindingUtils;
import org.springframework.roo.classpath.details.annotations.AnnotationMetadataBuilder;
import org.springframework.roo.metadata.MetadataService;
import org.springframework.roo.model.JavaType;
import org.springframework.roo.model.RooJavaType;
/**
* Implementation of {@link WebFinderOperations}
*
* @author Stefan Schmidt
* @since 1.2.0
*/
@Component
@Service
public class WebFinderOperationsImpl implements WebFinderOperations {
@Reference private ControllerOperations controllerOperations;
@Reference private MetadataService metadataService;
@Reference private TypeLocationService typeLocationService;
@Reference private TypeManagementService typeManagementService;
public void annotateAll() {
// First, find all entities with finders.
final Set<JavaType> finderEntities = new HashSet<JavaType>();
for (final ClassOrInterfaceTypeDetails cod : typeLocationService
.findClassesOrInterfaceDetailsWithAnnotation(RooJavaType.ROO_JPA_ACTIVE_RECORD)) {
if (MemberFindingUtils.getAnnotationOfType(cod.getAnnotations(),
RooJavaType.ROO_JPA_ACTIVE_RECORD).getAttribute("finders") != null) {
finderEntities.add(cod.getName());
}
}
// Second, find controllers for those entities.
for (final ClassOrInterfaceTypeDetails cod : typeLocationService
.findClassesOrInterfaceDetailsWithAnnotation(RooJavaType.ROO_WEB_SCAFFOLD)) {
final PhysicalTypeMetadata ptm = (PhysicalTypeMetadata) metadataService
.get(typeLocationService.getPhysicalTypeIdentifier(cod
.getName()));
Validate.notNull(ptm, "Java source code unavailable for type "
+ cod.getName().getFullyQualifiedTypeName());
final WebScaffoldAnnotationValues webScaffoldAnnotationValues = new WebScaffoldAnnotationValues(
ptm);
for (final JavaType finderEntity : finderEntities) {
if (finderEntity.equals(webScaffoldAnnotationValues
.getFormBackingObject())) {
annotateType(cod.getName(), finderEntity);
break;
}
}
}
}
public void annotateType(final JavaType controllerType,
final JavaType entityType) {
Validate.notNull(controllerType, "Controller type required");
Validate.notNull(entityType, "Entity type required");
final String id = typeLocationService
.getPhysicalTypeIdentifier(controllerType);
if (id == null) {
throw new IllegalArgumentException("Cannot locate source for '"
+ controllerType.getFullyQualifiedTypeName() + "'");
}
// Obtain the physical type and itd mutable details
final PhysicalTypeMetadata ptm = (PhysicalTypeMetadata) metadataService
.get(id);
Validate.notNull(ptm, "Java source code unavailable for type "
+ PhysicalTypeIdentifier.getFriendlyName(id));
final WebScaffoldAnnotationValues webScaffoldAnnotationValues = new WebScaffoldAnnotationValues(
ptm);
if (!webScaffoldAnnotationValues.isAnnotationFound()
|| !webScaffoldAnnotationValues.getFormBackingObject().equals(
entityType)) {
throw new IllegalArgumentException(
"Aborting, this controller type does not manage the "
+ entityType.getSimpleTypeName()
+ " form backing type.");
}
final PhysicalTypeDetails ptd = ptm.getMemberHoldingTypeDetails();
Validate.notNull(ptd, "Java source code details unavailable for type "
+ PhysicalTypeIdentifier.getFriendlyName(id));
final ClassOrInterfaceTypeDetails cid = (ClassOrInterfaceTypeDetails) ptd;
if (null == MemberFindingUtils.getAnnotationOfType(
cid.getAnnotations(), RooJavaType.ROO_WEB_FINDER)) {
final ClassOrInterfaceTypeDetailsBuilder cidBuilder = new ClassOrInterfaceTypeDetailsBuilder(
cid);
cidBuilder.addAnnotation(new AnnotationMetadataBuilder(
RooJavaType.ROO_WEB_FINDER));
typeManagementService.createOrUpdateTypeOnDisk(cidBuilder.build());
}
}
public boolean isWebFinderInstallationPossible() {
return controllerOperations.isControllerInstallationPossible();
}
}