package org.springframework.roo.addon.layers.repository.jpa; import static org.springframework.roo.model.RooJavaType.ROO_REPOSITORY_JPA; import java.util.LinkedHashMap; 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.classpath.PhysicalTypeIdentifier; import org.springframework.roo.classpath.PhysicalTypeMetadata; import org.springframework.roo.classpath.customdata.taggers.CustomDataKeyDecorator; 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.model.JavaSymbolName; import org.springframework.roo.model.JavaType; import org.springframework.roo.project.LogicalPath; /** * Implementation of {@link RepositoryJpaMetadataProvider}. * * @author Stefan Schmidt * @author Andrew Swan * @since 1.2.0 */ @Component(immediate = true) @Service public class RepositoryJpaMetadataProviderImpl extends AbstractMemberDiscoveringItdMetadataProvider implements RepositoryJpaMetadataProvider { @Reference private CustomDataKeyDecorator customDataKeyDecorator; private final Map<JavaType, String> domainTypeToRepositoryMidMap = new LinkedHashMap<JavaType, String>(); private final Map<String, JavaType> repositoryMidToDomainTypeMap = new LinkedHashMap<String, JavaType>(); protected void activate(final ComponentContext context) { super.setDependsOnGovernorBeingAClass(false); metadataDependencyRegistry.addNotificationListener(this); metadataDependencyRegistry.registerDependency( PhysicalTypeIdentifier.getMetadataIdentiferType(), getProvidesType()); addMetadataTrigger(ROO_REPOSITORY_JPA); registerMatchers(); } @Override protected String createLocalIdentifier(final JavaType javaType, final LogicalPath path) { return RepositoryJpaMetadata.createIdentifier(javaType, path); } protected void deactivate(final ComponentContext context) { metadataDependencyRegistry.removeNotificationListener(this); metadataDependencyRegistry.deregisterDependency( PhysicalTypeIdentifier.getMetadataIdentiferType(), getProvidesType()); removeMetadataTrigger(ROO_REPOSITORY_JPA); customDataKeyDecorator.unregisterMatchers(getClass()); } @Override protected String getGovernorPhysicalTypeIdentifier( final String metadataIdentificationString) { final JavaType javaType = RepositoryJpaMetadata .getJavaType(metadataIdentificationString); final LogicalPath path = RepositoryJpaMetadata .getPath(metadataIdentificationString); return PhysicalTypeIdentifier.createIdentifier(javaType, path); } public String getItdUniquenessFilenameSuffix() { return "Jpa_Repository"; } @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 = domainTypeToRepositoryMidMap.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 = domainTypeToRepositoryMidMap .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 RepositoryJpaAnnotationValues annotationValues = new RepositoryJpaAnnotationValues( governorPhysicalTypeMetadata); final JavaType domainType = annotationValues.getDomainType(); final JavaType identifierType = persistenceMemberLocator .getIdentifierType(domainType); if (identifierType == null) { return null; } // Remember that this entity JavaType matches up with this metadata // identification string // Start by clearing any previous association final JavaType oldEntity = repositoryMidToDomainTypeMap .get(metadataIdentificationString); if (oldEntity != null) { domainTypeToRepositoryMidMap.remove(oldEntity); } domainTypeToRepositoryMidMap.put(domainType, metadataIdentificationString); repositoryMidToDomainTypeMap.put(metadataIdentificationString, domainType); return new RepositoryJpaMetadata(metadataIdentificationString, aspectName, governorPhysicalTypeMetadata, annotationValues, identifierType); } public String getProvidesType() { return RepositoryJpaMetadata.getMetadataIdentiferType(); } @SuppressWarnings("unchecked") private void registerMatchers() { customDataKeyDecorator.registerMatchers(getClass(), new LayerTypeMatcher(ROO_REPOSITORY_JPA, new JavaSymbolName( RooJpaRepository.DOMAIN_TYPE_ATTRIBUTE))); } }