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(immediate = true)
@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,
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,
methodParameters);
if (additions != null) {
return additions;
}
}
return null;
}
protected void unbindLayerProvider(final LayerProvider provider) {
synchronized (mutex) {
if (providers.contains(provider)) {
providers.remove(provider);
}
}
}
}