package org.springframework.roo.addon.layers.service.addon;
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.Service;
import org.osgi.service.component.ComponentContext;
import org.springframework.roo.classpath.MetadataLocatorUtils;
import org.springframework.roo.classpath.TypeLocationService;
import org.springframework.roo.classpath.details.ClassOrInterfaceTypeDetails;
import org.springframework.roo.classpath.details.DefaultPhysicalTypeMetadata;
import org.springframework.roo.metadata.MetadataDependencyRegistry;
import org.springframework.roo.model.JavaType;
import org.springframework.roo.model.RooJavaType;
import java.util.Collection;
/**
* The {@link ServiceLocator} implementation.
*
* @author Jose Manuel Vivó
* @since 2.0.0
*/
@Component
@Service
public class ServiceLocatorImpl implements ServiceLocator {
@Reference
private TypeLocationService typeLocationService;
@Reference
private MetadataDependencyRegistry dependencyRegistry;
private MetadataLocatorUtils<JavaType> util;
protected void activate(final ComponentContext cContext) {
util = new MetadataLocatorUtils<JavaType>(new Evaluator(typeLocationService));
dependencyRegistry.addNotificationListener(util);
}
public Collection<ClassOrInterfaceTypeDetails> getServices(final JavaType domainType) {
return util.getValue(domainType, RooJavaType.ROO_SERVICE);
}
@Override
public ClassOrInterfaceTypeDetails getService(final JavaType domainType) {
Validate.notNull(domainType, "domainType is required");
Collection<ClassOrInterfaceTypeDetails> repositories = getServices(domainType);
if (repositories.isEmpty()) {
return null;
} else if (repositories.size() > 1) {
throw new IllegalStateException("Found " + repositories.size() + " services for "
+ domainType.getFullyQualifiedTypeName());
}
return repositories.iterator().next();
}
@Override
public ClassOrInterfaceTypeDetails getFirstService(final JavaType domainType) {
Validate.notNull(domainType, "domainType is required");
Collection<ClassOrInterfaceTypeDetails> repositories = getServices(domainType);
if (repositories.isEmpty()) {
return null;
}
return repositories.iterator().next();
}
public Collection<ClassOrInterfaceTypeDetails> getServiceImpls(final JavaType serviceType) {
return util.getValue(serviceType, RooJavaType.ROO_SERVICE_IMPL);
}
@Override
public ClassOrInterfaceTypeDetails getServiceImpl(final JavaType serviceType) {
Validate.notNull(serviceType, "serviceType is required");
Collection<ClassOrInterfaceTypeDetails> repositories = getServices(serviceType);
if (repositories.isEmpty()) {
return null;
} else if (repositories.size() > 1) {
throw new IllegalStateException("Found " + repositories.size() + " serviceImpl for "
+ serviceType.getFullyQualifiedTypeName());
}
return repositories.iterator().next();
}
@Override
public ClassOrInterfaceTypeDetails getFirstServiceImpl(final JavaType serviceType) {
Validate.notNull(serviceType, "serviceType is required");
Collection<ClassOrInterfaceTypeDetails> repositories = getServices(serviceType);
if (repositories.isEmpty()) {
return null;
}
return repositories.iterator().next();
}
private class Evaluator extends MetadataLocatorUtils.LocatorEvaluatorByAnnotation {
public Evaluator(TypeLocationService typeLocationService) {
super(typeLocationService);
}
@Override
public boolean evaluateForKey(JavaType key, ClassOrInterfaceTypeDetails valueToEvalueate,
JavaType context) {
if (RooJavaType.ROO_SERVICE.equals(context)) {
final ServiceAnnotationValues annotationValues =
new ServiceAnnotationValues(new DefaultPhysicalTypeMetadata(
valueToEvalueate.getDeclaredByMetadataId(),
typeLocationService.getPhysicalTypeCanonicalPath(valueToEvalueate
.getDeclaredByMetadataId()), valueToEvalueate));
return annotationValues.getEntity() != null && annotationValues.getEntity().equals(key);
}
if (RooJavaType.ROO_SERVICE_IMPL.equals(context)) {
final ServiceImplAnnotationValues annotationValues =
new ServiceImplAnnotationValues(new DefaultPhysicalTypeMetadata(
valueToEvalueate.getDeclaredByMetadataId(),
typeLocationService.getPhysicalTypeCanonicalPath(valueToEvalueate
.getDeclaredByMetadataId()), valueToEvalueate));
return annotationValues.getService() != null && annotationValues.getService().equals(key);
}
return false;
}
@Override
public JavaType evalueteForEvict(String streamDependency) {
if (ServiceMetadata.isValid(streamDependency)) {
return ServiceMetadata.getJavaType(streamDependency);
} else if (ServiceImplMetadata.isValid(streamDependency)) {
return ServiceImplMetadata.getJavaType(streamDependency);
}
return null;
}
}
}