package org.springframework.roo.addon.layers.service;
import static org.springframework.roo.model.RooJavaType.ROO_SERVICE;
import java.util.HashMap;
import java.util.Map;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.osgi.service.component.ComponentContext;
import org.springframework.roo.addon.plural.PluralMetadata;
import org.springframework.roo.classpath.PhysicalTypeIdentifier;
import org.springframework.roo.classpath.PhysicalTypeMetadata;
import org.springframework.roo.classpath.customdata.taggers.CustomDataKeyDecorator;
import org.springframework.roo.classpath.details.ClassOrInterfaceTypeDetails;
import org.springframework.roo.classpath.details.ItdTypeDetails;
import org.springframework.roo.classpath.details.MemberHoldingTypeDetails;
import org.springframework.roo.classpath.itd.AbstractMemberDiscoveringItdMetadataProvider;
import org.springframework.roo.classpath.itd.ItdTypeDetailsProvidingMetadataItem;
import org.springframework.roo.classpath.layers.LayerTypeMatcher;
import org.springframework.roo.classpath.scanner.MemberDetails;
import org.springframework.roo.metadata.MetadataProvider;
import org.springframework.roo.model.JavaSymbolName;
import org.springframework.roo.model.JavaType;
import org.springframework.roo.project.LogicalPath;
/**
* {@link MetadataProvider} providing {@link ServiceInterfaceMetadata}
*
* @author Stefan Schmidt
* @since 1.2.0
*/
@Component(immediate = true)
@Service
public class ServiceInterfaceMetadataProvider extends
AbstractMemberDiscoveringItdMetadataProvider {
@Reference private CustomDataKeyDecorator customDataKeyDecorator;
private final Map<JavaType, String> managedEntityTypes = new HashMap<JavaType, String>();
@SuppressWarnings("unchecked")
protected void activate(final ComponentContext context) {
super.setDependsOnGovernorBeingAClass(false);
metadataDependencyRegistry.addNotificationListener(this);
metadataDependencyRegistry.registerDependency(
PhysicalTypeIdentifier.getMetadataIdentiferType(),
getProvidesType());
addMetadataTrigger(ROO_SERVICE);
customDataKeyDecorator.registerMatchers(getClass(),
new LayerTypeMatcher(ROO_SERVICE, new JavaSymbolName(
RooService.DOMAIN_TYPES_ATTRIBUTE)));
}
@Override
protected String createLocalIdentifier(final JavaType javaType,
final LogicalPath path) {
return ServiceInterfaceMetadata.createIdentifier(javaType, path);
}
protected void deactivate(final ComponentContext context) {
metadataDependencyRegistry.removeNotificationListener(this);
metadataDependencyRegistry.deregisterDependency(
PhysicalTypeIdentifier.getMetadataIdentiferType(),
getProvidesType());
removeMetadataTrigger(ROO_SERVICE);
}
@Override
protected String getGovernorPhysicalTypeIdentifier(
final String metadataIdentificationString) {
final JavaType javaType = ServiceInterfaceMetadata
.getJavaType(metadataIdentificationString);
final LogicalPath path = ServiceInterfaceMetadata
.getPath(metadataIdentificationString);
return PhysicalTypeIdentifier.createIdentifier(javaType, path);
}
public String getItdUniquenessFilenameSuffix() {
return "Service";
}
@Override
protected String getLocalMidToRequest(final ItdTypeDetails itdTypeDetails) {
// Determine the governor for this ITD, and whether any metadata is even
// hoping to hear about changes to that JavaType and its ITDs
final JavaType governor = itdTypeDetails.getName();
final String localMid = managedEntityTypes.get(governor);
if (localMid != null) {
return localMid;
}
final MemberHoldingTypeDetails memberHoldingTypeDetails = typeLocationService
.getTypeDetails(governor);
if (memberHoldingTypeDetails != null) {
for (final JavaType type : memberHoldingTypeDetails
.getLayerEntities()) {
final String localMidType = managedEntityTypes.get(type);
if (localMidType != null) {
return localMidType;
}
}
}
return null;
}
@Override
protected ItdTypeDetailsProvidingMetadataItem getMetadata(
final String metadataIdentificationString,
final JavaType aspectName,
final PhysicalTypeMetadata governorPhysicalTypeMetadata,
final String itdFilename) {
final ServiceAnnotationValues annotationValues = new ServiceAnnotationValues(
governorPhysicalTypeMetadata);
final ClassOrInterfaceTypeDetails cid = governorPhysicalTypeMetadata
.getMemberHoldingTypeDetails();
if (cid == null) {
return null;
}
final MemberDetails memberDetails = memberDetailsScanner
.getMemberDetails(getClass().getName(), cid);
final JavaType[] domainTypes = annotationValues.getDomainTypes();
if (domainTypes == null || domainTypes.length == 0) {
return null;
}
final Map<JavaType, String> domainTypePlurals = new HashMap<JavaType, String>();
final Map<JavaType, JavaType> domainTypeToIdTypeMap = new HashMap<JavaType, JavaType>();
for (final JavaType type : domainTypes) {
final JavaType idType = persistenceMemberLocator
.getIdentifierType(type);
if (idType == null) {
continue;
}
// We simply take the first disregarding any further fields which
// may be identifiers
domainTypeToIdTypeMap.put(type, idType);
final String domainTypeId = typeLocationService
.getPhysicalTypeIdentifier(type);
if (domainTypeId == null) {
return null;
}
final LogicalPath path = PhysicalTypeIdentifier
.getPath(domainTypeId);
final String pluralId = PluralMetadata.createIdentifier(type, path);
final PluralMetadata pluralMetadata = (PluralMetadata) metadataService
.get(pluralId);
if (pluralMetadata == null) {
return null;
}
// Maintain a list of entities that are being handled by this layer
managedEntityTypes.put(type, metadataIdentificationString);
metadataDependencyRegistry.registerDependency(pluralId,
metadataIdentificationString);
domainTypePlurals.put(type, pluralMetadata.getPlural());
}
return new ServiceInterfaceMetadata(metadataIdentificationString,
aspectName, governorPhysicalTypeMetadata, memberDetails,
domainTypeToIdTypeMap, annotationValues, domainTypePlurals);
}
public String getProvidesType() {
return ServiceInterfaceMetadata.getMetadataIdentiferType();
}
}