package org.springframework.roo.addon.jpa.addon.test;
import static org.springframework.roo.model.RooJavaType.ROO_JPA_UNIT_TEST;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import org.apache.commons.lang3.Validate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Service;
import org.osgi.service.component.ComponentContext;
import org.springframework.roo.addon.jpa.addon.entity.JpaEntityMetadata;
import org.springframework.roo.addon.jpa.addon.entity.JpaEntityMetadata.RelationInfo;
import org.springframework.roo.classpath.PhysicalTypeIdentifier;
import org.springframework.roo.classpath.PhysicalTypeMetadata;
import org.springframework.roo.classpath.details.ClassOrInterfaceTypeDetails;
import org.springframework.roo.classpath.details.ItdTypeDetails;
import org.springframework.roo.classpath.itd.AbstractMemberDiscoveringItdMetadataProvider;
import org.springframework.roo.classpath.itd.ItdTypeDetailsProvidingMetadataItem;
import org.springframework.roo.metadata.MetadataDependencyRegistry;
import org.springframework.roo.metadata.internal.MetadataDependencyRegistryTracker;
import org.springframework.roo.model.JavaType;
import org.springframework.roo.model.RooJavaType;
import org.springframework.roo.project.LogicalPath;
/**
* Implementation of {@link JpaUnitTestMetadataProvider}.
*
* @author Sergio Clares
* @since 2.0
*/
@Component
@Service
public class JpaUnitTestMetadataProviderImpl extends AbstractMemberDiscoveringItdMetadataProvider
implements JpaUnitTestMetadataProvider {
// TODO: This class is under construction. It can contain several commented code
protected MetadataDependencyRegistryTracker registryTracker = null;
/**
* This service is being activated so setup it:
* <ul>
* <li>Create and open the {@link MetadataDependencyRegistryTracker}.</li>
* <li>Registers {@link RooJavaType#ROO_JPA_UNIT_TEST} as additional
* JavaType that will trigger metadata registration.</li>
* <li>Set ensure the governor type details represent a class.</li>
* </ul>
*/
@Override
protected void activate(final ComponentContext cContext) {
super.activate(cContext);
this.registryTracker =
new MetadataDependencyRegistryTracker(cContext.getBundleContext(), this,
PhysicalTypeIdentifier.getMetadataIdentiferType(), getProvidesType());
this.registryTracker.open();
addMetadataTrigger(ROO_JPA_UNIT_TEST);
}
/**
* This service is being deactivated so unregister upstream-downstream
* dependencies, triggers, matchers and listeners.
*
* @param context
*/
protected void deactivate(final ComponentContext context) {
MetadataDependencyRegistry registry = this.registryTracker.getService();
registry.removeNotificationListener(this);
registry.deregisterDependency(PhysicalTypeIdentifier.getMetadataIdentiferType(),
getProvidesType());
this.registryTracker.close();
removeMetadataTrigger(ROO_JPA_UNIT_TEST);
}
@Override
protected String createLocalIdentifier(final JavaType javaType, final LogicalPath path) {
return JpaUnitTestMetadata.createIdentifier(javaType, path);
}
@Override
protected String getGovernorPhysicalTypeIdentifier(final String metadataIdentificationString) {
final JavaType javaType = JpaUnitTestMetadata.getJavaType(metadataIdentificationString);
final LogicalPath path = JpaUnitTestMetadata.getPath(metadataIdentificationString);
return PhysicalTypeIdentifier.createIdentifier(javaType, path);
}
@Override
protected String getLocalMidToRequest(final ItdTypeDetails itdTypeDetails) {
return getLocalMid(itdTypeDetails);
}
@Override
public String getItdUniquenessFilenameSuffix() {
return "JpaUnitTest";
}
@Override
protected ItdTypeDetailsProvidingMetadataItem getMetadata(
final String metadataIdentificationString, final JavaType aspectName,
final PhysicalTypeMetadata governorPhysicalTypeMetadata, final String itdFilename) {
final JpaUnitTestAnnotationValues annotationValues =
new JpaUnitTestAnnotationValues(governorPhysicalTypeMetadata);
JavaType targetType = annotationValues.getTargetClass();
Validate.notNull(targetType,
targetType.getSimpleTypeName().concat(" doesn't exist in the project."));
// Obtain target type child related entities
final ClassOrInterfaceTypeDetails cid = getTypeLocationService().getTypeDetails(targetType);
JpaEntityMetadata entityMetadata =
getMetadataService().get(JpaEntityMetadata.createIdentifier(cid));
List<JavaType> relatedEntities = new ArrayList<JavaType>();
// Add the current entity first
relatedEntities.add(targetType);
Map<String, RelationInfo> relationInfos = entityMetadata.getRelationInfos();
for (RelationInfo relation : relationInfos.values()) {
// Get child entity type
JavaType childType = relation.childType;
if (!relatedEntities.contains(childType)) {
relatedEntities.add(childType);
}
}
// Get all entity factories for this entity and child related entities
Set<ClassOrInterfaceTypeDetails> entityFactories =
getTypeLocationService().findClassesOrInterfaceDetailsWithAnnotation(
RooJavaType.ROO_JPA_ENTITY_FACTORY);
Map<JavaType, JavaType> entityAndItsFactoryMap = new TreeMap<JavaType, JavaType>();
for (ClassOrInterfaceTypeDetails entityFactory : entityFactories) {
JavaType entity =
(JavaType) entityFactory.getAnnotation(RooJavaType.ROO_JPA_ENTITY_FACTORY)
.getAttribute("entity").getValue();
if (entity != null && relatedEntities.contains(entity)) {
entityAndItsFactoryMap.put(entity, entityFactory.getType());
}
}
// final List<FieldMetadata> fieldDependencies = new ArrayList<FieldMetadata>();
// final MemberDetails targetTypeDetails =
// getMemberDetailsScanner().getMemberDetails(this.getClass().getName(), cid);
//
// // Obtain all governor external field dependencies
// List<FieldMetadata> fields = targetTypeDetails.getFields();
// for (FieldMetadata field : fields) {
// if (field.getAnnotation(JpaJavaType.ONE_TO_ONE) != null
// || field.getAnnotation(JpaJavaType.MANY_TO_ONE) != null) {
// fieldDependencies.add(field);
// }
// }
//
// // Obtain all methods of target type
// final List<MethodMetadata> targetTypeMethods = targetTypeDetails.getMethods();
// final List<MethodMetadata> methods = new ArrayList<MethodMetadata>();
// for (MethodMetadata method : targetTypeMethods) {
//
// // Check if method is an accesor or mutator
// boolean isAccesorOrMutator = false;
// for (FieldMetadata field : fields) {
// JavaSymbolName accesorName = BeanInfoUtils.getAccessorMethodName(field);
// JavaSymbolName mutatorName = BeanInfoUtils.getMutatorMethodName(field);
// if (method.getMethodName().equals(accesorName)
// || method.getMethodName().equals(mutatorName)) {
// isAccesorOrMutator = true;
// }
// }
//
// // Only add "custom" methods. Avoid adding accesors, mutators, toString and hashCode
// if (!method.getMethodName().equals(TO_STRING) && !method.getMethodName().equals(HASH_CODE)
// && !isAccesorOrMutator) {
// methods.add(method);
// }
// }
return new JpaUnitTestMetadata(metadataIdentificationString, aspectName,
governorPhysicalTypeMetadata, annotationValues, relationInfos.values(),
entityAndItsFactoryMap);
}
public String getProvidesType() {
return JpaUnitTestMetadata.getMetadataIdentiferType();
}
}