package org.springframework.roo.classpath.layers; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; import java.util.SortedSet; import java.util.TreeSet; 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.ReferenceCardinality; import org.apache.felix.scr.annotations.ReferencePolicy; import org.apache.felix.scr.annotations.ReferenceStrategy; import org.apache.felix.scr.annotations.Service; import org.springframework.roo.model.JavaType; /** * The {@link LayerService} implementation. * * @author Stefan Schmidt * @since 1.2.0 */ @Component @Service @Reference(name = "layerProvider", strategy = ReferenceStrategy.EVENT, policy = ReferencePolicy.DYNAMIC, referenceInterface = LayerProvider.class, cardinality = ReferenceCardinality.MANDATORY_MULTIPLE) public class LayerServiceImpl implements LayerService { /** * Sorts two {@link LayerProvider}s into descending order of position. * * @author Andrew Swan * @author Stefan Schmidt * @since 1.2.0 */ static class DescendingLayerComparator implements Comparator<LayerProvider>, Serializable { private static final long serialVersionUID = 2840103254559366403L; public int compare(final LayerProvider provider1, final LayerProvider provider2) { if (provider1.equals(provider2)) { return 0; } final int difference = provider2.getLayerPosition() - provider1.getLayerPosition(); Validate.validState(difference != 0, provider1.getClass().getSimpleName() + " and " + provider2.getClass().getSimpleName() + " both have position " + provider1.getLayerPosition()); return difference; } } // Mutex private final Object mutex = new Object(); private final SortedSet<LayerProvider> providers = new TreeSet<LayerProvider>( new DescendingLayerComparator()); protected void bindLayerProvider(final LayerProvider provider) { synchronized (mutex) { providers.add(provider); } } public MemberTypeAdditions getMemberTypeAdditions(final String metadataIdentificationString, final String methodIdentifier, final JavaType targetEntity, final JavaType idType, final int layerPosition, final Collection<? extends MethodParameter> methodParameters) { final MethodParameter[] methodParametersArray = methodParameters.toArray(new MethodParameter[methodParameters.size()]); return getMemberTypeAdditions(metadataIdentificationString, methodIdentifier, targetEntity, idType, layerPosition, methodParametersArray); } public MemberTypeAdditions getMemberTypeAdditions(final String metadataIdentificationString, final String methodIdentifier, final JavaType targetEntity, final JavaType idType, final int layerPosition, boolean autowire, final Collection<? extends MethodParameter> methodParameters) { final MethodParameter[] methodParametersArray = methodParameters.toArray(new MethodParameter[methodParameters.size()]); return getMemberTypeAdditions(metadataIdentificationString, methodIdentifier, targetEntity, idType, layerPosition, autowire, methodParametersArray); } public MemberTypeAdditions getMemberTypeAdditions(final String metadataIdentificationString, final String methodIdentifier, final JavaType targetEntity, final JavaType idType, final int layerPosition, final MethodParameter... methodParameters) { return getMemberTypeAdditions(metadataIdentificationString, methodIdentifier, targetEntity, idType, layerPosition, true, methodParameters); } public MemberTypeAdditions getMemberTypeAdditions(final String metadataIdentificationString, final String methodIdentifier, final JavaType targetEntity, final JavaType idType, final int layerPosition, final boolean autowire, final MethodParameter... methodParameters) { Validate.notBlank(metadataIdentificationString, "metadataIdentificationString is required"); Validate.notBlank(methodIdentifier, "methodIdentifier is required"); Validate.notNull(targetEntity, "targetEntity is required"); for (final LayerProvider provider : new ArrayList<LayerProvider>(providers)) { if (provider.getLayerPosition() >= layerPosition) { continue; } final MemberTypeAdditions additions = provider.getMemberTypeAdditions(metadataIdentificationString, methodIdentifier, targetEntity, idType, autowire, methodParameters); if (additions != null) { return additions; } } return null; } protected void unbindLayerProvider(final LayerProvider provider) { synchronized (mutex) { if (providers.contains(provider)) { providers.remove(provider); } } } }