package org.springframework.roo.addon.web.mvc.controller.addon;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import org.apache.commons.lang3.StringUtils;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Service;
import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.component.ComponentContext;
import org.springframework.roo.classpath.TypeLocationService;
import org.springframework.roo.classpath.details.MethodMetadata;
import org.springframework.roo.classpath.details.annotations.AnnotationAttributeValue;
import org.springframework.roo.classpath.details.annotations.AnnotationMetadata;
import org.springframework.roo.classpath.details.annotations.AnnotationMetadataBuilder;
import org.springframework.roo.classpath.details.annotations.EnumAttributeValue;
import org.springframework.roo.classpath.details.annotations.StringAttributeValue;
import org.springframework.roo.classpath.scanner.MemberDetails;
import org.springframework.roo.classpath.scanner.MemberDetailsScanner;
import org.springframework.roo.model.EnumDetails;
import org.springframework.roo.model.JavaSymbolName;
import org.springframework.roo.model.JavaType;
import org.springframework.roo.model.SpringEnumDetails;
import org.springframework.roo.model.SpringJavaType;
import org.springframework.roo.support.logging.HandlerUtils;
/**
* Implementation of {@link ControllerMVCService}.
*
* @author Juan Carlos GarcĂa
* @since 2.0
* @deprecated this method isn't needed
*/
@Component
@Service
public class ControllerMVCServiceImpl implements ControllerMVCService {
private static final Logger LOGGER = HandlerUtils.getLogger(ControllerMVCServiceImpl.class);
// ------------ OSGi component attributes ----------------
private BundleContext context;
private TypeLocationService typeLocationService;
private MemberDetailsScanner memberDetailsScanner;
protected void activate(final ComponentContext context) {
this.context = context.getBundleContext();
}
@Override
public MethodMetadata getMVCMethodByRequestMapping(JavaType controller, EnumDetails method,
String path, List<String> params, String consumes, String produces, String headers) {
// Replacing null values with empty
path = path == null ? "" : path;
consumes = consumes == null ? "" : consumes;
produces = produces == null ? "" : produces;
headers = headers == null ? "" : headers;
// Getting controller member details
MemberDetails controllerDetails =
getMemberDetailsScanner().getMemberDetails(getClass().toString(),
getTypeLocationService().getTypeDetails(controller));
// Getting all controller methods
List<MethodMetadata> methods = controllerDetails.getMethods();
for (MethodMetadata definedMethod : methods) {
// Getting request mapping annotation
AnnotationMetadata requesMappingAnnotation =
definedMethod.getAnnotation(SpringJavaType.REQUEST_MAPPING);
if (requesMappingAnnotation != null) {
// Get all attributes
String methodAttr =
requesMappingAnnotation.getAttribute("method") == null ? "" : requesMappingAnnotation
.getAttribute("method").getValue().toString();
String valueAttr =
requesMappingAnnotation.getAttribute("value") == null ? "" : requesMappingAnnotation
.getAttribute("value").getValue().toString();
// TODO: Get params and compare them
String consumesAttr =
requesMappingAnnotation.getAttribute("consumes") == null ? "" : requesMappingAnnotation
.getAttribute("consumes").getValue().toString();
String producesAttr =
requesMappingAnnotation.getAttribute("produces") == null ? "" : requesMappingAnnotation
.getAttribute("produces").getValue().toString();
String headersAttr =
requesMappingAnnotation.getAttribute("headers") == null ? "" : requesMappingAnnotation
.getAttribute("headers").getValue().toString();
// If every attribute match, return this method
if (method.toString().equals(methodAttr) && valueAttr.equals(path)
&& consumesAttr.equals(consumes) && producesAttr.equals(produces)
&& headersAttr.equals(headers)) {
return definedMethod;
}
}
}
return null;
}
@Override
public AnnotationMetadataBuilder getRequestMappingAnnotation(EnumDetails method, String path,
List<String> params, EnumDetails consumes, EnumDetails produces, String headers) {
List<AnnotationAttributeValue<?>> requestMappingAttributes =
new ArrayList<AnnotationAttributeValue<?>>();
// Adding path attribute
if (StringUtils.isNotBlank(path)) {
requestMappingAttributes.add(new StringAttributeValue(new JavaSymbolName("value"), path));
}
// Adding method attribute. Force GET method if empty
if (method != null) {
requestMappingAttributes.add(new EnumAttributeValue(new JavaSymbolName("method"), method));
} else {
requestMappingAttributes.add(new EnumAttributeValue(new JavaSymbolName("method"),
SpringEnumDetails.REQUEST_METHOD_GET));
}
// TODO: Adding params attribute
// Adding consumes attribute
if (consumes != null) {
requestMappingAttributes
.add(new EnumAttributeValue(new JavaSymbolName("consumes"), consumes));
}
// Adding produces attribute
if (produces != null) {
requestMappingAttributes
.add(new EnumAttributeValue(new JavaSymbolName("produces"), produces));
}
// Adding headers attribute
if (StringUtils.isNotBlank(headers)) {
requestMappingAttributes
.add(new StringAttributeValue(new JavaSymbolName("headers"), headers));
}
return new AnnotationMetadataBuilder(SpringJavaType.REQUEST_MAPPING, requestMappingAttributes);
}
@Override
public AnnotationMetadataBuilder getRequestMappingAnnotation(EnumDetails method, String path,
List<String> params, String consumes, String produces, String headers) {
List<AnnotationAttributeValue<?>> requestMappingAttributes =
new ArrayList<AnnotationAttributeValue<?>>();
// Adding method attribute. Force GET method if empty
if (method != null) {
requestMappingAttributes.add(new EnumAttributeValue(new JavaSymbolName("method"), method));
} else {
requestMappingAttributes.add(new EnumAttributeValue(new JavaSymbolName("method"),
SpringEnumDetails.REQUEST_METHOD_GET));
}
// Adding path attribute
if (StringUtils.isNotBlank(path)) {
requestMappingAttributes.add(new StringAttributeValue(new JavaSymbolName("value"), path));
}
// TODO: Adding params attribute
// Adding consumes attribute
if (StringUtils.isNotBlank(consumes)) {
requestMappingAttributes.add(new StringAttributeValue(new JavaSymbolName("consumes"),
consumes));
}
// Adding produces attribute
if (StringUtils.isNotBlank(produces)) {
requestMappingAttributes.add(new StringAttributeValue(new JavaSymbolName("produces"),
produces));
}
// Adding headers attribute
if (StringUtils.isNotBlank(headers)) {
requestMappingAttributes
.add(new StringAttributeValue(new JavaSymbolName("headers"), headers));
}
return new AnnotationMetadataBuilder(SpringJavaType.REQUEST_MAPPING, requestMappingAttributes);
}
// Methods to obtain OSGi Services
public TypeLocationService getTypeLocationService() {
if (typeLocationService == null) {
// Get all Services implement TypeLocationService interface
try {
ServiceReference<?>[] references =
this.context.getAllServiceReferences(TypeLocationService.class.getName(), null);
for (ServiceReference<?> ref : references) {
typeLocationService = (TypeLocationService) this.context.getService(ref);
return typeLocationService;
}
return null;
} catch (InvalidSyntaxException e) {
LOGGER.warning("Cannot load TypeLocationService on ControllerMVCServiceImpl.");
return null;
}
} else {
return typeLocationService;
}
}
public MemberDetailsScanner getMemberDetailsScanner() {
if (memberDetailsScanner == null) {
// Get all Services implement MemberDetailsScanner interface
try {
ServiceReference<?>[] references =
this.context.getAllServiceReferences(MemberDetailsScanner.class.getName(), null);
for (ServiceReference<?> ref : references) {
memberDetailsScanner = (MemberDetailsScanner) this.context.getService(ref);
return memberDetailsScanner;
}
return null;
} catch (InvalidSyntaxException e) {
LOGGER.warning("Cannot load MemberDetailsScanner on ControllerMVCServiceImpl.");
return null;
}
} else {
return memberDetailsScanner;
}
}
}