package org.springframework.roo.addon.layers.service;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.springframework.roo.classpath.customdata.CustomDataKeys;
import org.springframework.roo.classpath.customdata.tagkeys.MethodMetadataCustomDataKey;
import org.springframework.roo.classpath.layers.MemberTypeAdditions;
import org.springframework.roo.model.JavaSymbolName;
import org.springframework.roo.model.JavaType;
import org.springframework.roo.support.util.PairList;
/**
* A method provided by a user project's service layer
*
* @author Andrew Swan
* @author Stefan Schmidt
* @since 1.2.0
*/
enum ServiceLayerMethod {
// The names of these enum constants are arbitrary; calling code refers to
// these methods by their String key.
COUNT(CustomDataKeys.COUNT_ALL_METHOD) {
@Override
public String getName(final ServiceAnnotationValues annotationValues,
final JavaType entityType, final String plural) {
if (StringUtils.isNotBlank(annotationValues.getCountAllMethod())) {
return annotationValues.getCountAllMethod() + plural;
}
return null;
}
@Override
public List<JavaSymbolName> getParameterNames(
final JavaType entityType, final JavaType idType) {
return Collections.emptyList();
}
@Override
public List<JavaType> getParameterTypes(final JavaType entityType,
final JavaType idType) {
return Collections.emptyList();
}
@Override
public JavaType getReturnType(final JavaType entityType) {
return JavaType.LONG_PRIMITIVE;
}
},
DELETE(CustomDataKeys.REMOVE_METHOD) {
@Override
public String getName(final ServiceAnnotationValues annotationValues,
final JavaType entityType, final String plural) {
if (StringUtils.isNotBlank(annotationValues.getDeleteMethod())) {
return annotationValues.getDeleteMethod()
+ entityType.getSimpleTypeName();
}
return null;
}
@Override
public List<JavaSymbolName> getParameterNames(
final JavaType entityType, final JavaType idType) {
return Arrays.asList(JavaSymbolName
.getReservedWordSafeName(entityType));
}
@Override
public List<JavaType> getParameterTypes(final JavaType entityType,
final JavaType idType) {
return Arrays.asList(entityType);
}
@Override
public JavaType getReturnType(final JavaType entityType) {
return JavaType.VOID_PRIMITIVE;
}
},
FIND(CustomDataKeys.FIND_METHOD) {
@Override
public String getName(final ServiceAnnotationValues annotationValues,
final JavaType entityType, final String plural) {
if (StringUtils.isNotBlank(annotationValues.getFindMethod())) {
return annotationValues.getFindMethod()
+ entityType.getSimpleTypeName();
}
return null;
}
@Override
public List<JavaSymbolName> getParameterNames(
final JavaType entityType, final JavaType idType) {
return Arrays.asList(new JavaSymbolName("id"));
}
@Override
public List<JavaType> getParameterTypes(final JavaType entityType,
final JavaType idType) {
return Arrays.asList(idType);
}
@Override
public JavaType getReturnType(final JavaType entityType) {
return entityType;
}
},
FIND_ALL(CustomDataKeys.FIND_ALL_METHOD) {
@Override
public String getName(final ServiceAnnotationValues annotationValues,
final JavaType entityType, final String plural) {
if (StringUtils.isNotBlank(annotationValues.getFindAllMethod())) {
return annotationValues.getFindAllMethod() + plural;
}
return null;
}
@Override
public List<JavaSymbolName> getParameterNames(
final JavaType entityType, final JavaType idType) {
return Collections.emptyList();
}
@Override
public List<JavaType> getParameterTypes(final JavaType entityType,
final JavaType idType) {
return Collections.emptyList();
}
@Override
public JavaType getReturnType(final JavaType entityType) {
return JavaType.listOf(entityType);
}
},
FIND_ENTRIES(CustomDataKeys.FIND_ENTRIES_METHOD) {
@Override
public String getName(final ServiceAnnotationValues annotationValues,
final JavaType entityType, final String plural) {
if (StringUtils.isNotBlank(annotationValues.getFindEntriesMethod())) {
return annotationValues.getFindEntriesMethod()
+ entityType.getSimpleTypeName() + "Entries";
}
return null;
}
@Override
public List<JavaSymbolName> getParameterNames(
final JavaType entityType, final JavaType idType) {
return Arrays.asList(new JavaSymbolName("firstResult"),
new JavaSymbolName("maxResults"));
}
@Override
public List<JavaType> getParameterTypes(final JavaType entityType,
final JavaType idType) {
return Arrays
.asList(JavaType.INT_PRIMITIVE, JavaType.INT_PRIMITIVE);
}
@Override
public JavaType getReturnType(final JavaType entityType) {
return JavaType.listOf(entityType);
}
},
SAVE(CustomDataKeys.PERSIST_METHOD) {
@Override
public String getName(final ServiceAnnotationValues annotationValues,
final JavaType entityType, final String plural) {
if (StringUtils.isNotBlank(annotationValues.getSaveMethod())) {
return annotationValues.getSaveMethod()
+ entityType.getSimpleTypeName();
}
return null;
}
@Override
public List<JavaSymbolName> getParameterNames(
final JavaType entityType, final JavaType idType) {
return Arrays.asList(JavaSymbolName
.getReservedWordSafeName(entityType));
}
@Override
public List<JavaType> getParameterTypes(final JavaType entityType,
final JavaType idType) {
return Arrays.asList(entityType);
}
@Override
public JavaType getReturnType(final JavaType entityType) {
return JavaType.VOID_PRIMITIVE;
}
},
UPDATE(CustomDataKeys.MERGE_METHOD) {
@Override
public String getName(final ServiceAnnotationValues annotationValues,
final JavaType entityType, final String plural) {
if (StringUtils.isNotBlank(annotationValues.getUpdateMethod())) {
return annotationValues.getUpdateMethod()
+ entityType.getSimpleTypeName();
}
return null;
}
@Override
public List<JavaSymbolName> getParameterNames(
final JavaType entityType, final JavaType idType) {
return Arrays.asList(JavaSymbolName
.getReservedWordSafeName(entityType));
}
@Override
public List<JavaType> getParameterTypes(final JavaType entityType,
final JavaType idType) {
return Arrays.asList(entityType);
}
@Override
public JavaType getReturnType(final JavaType entityType) {
return entityType;
}
};
/**
* Returns the {@link ServiceLayerMethod} with the given properties, if any
*
* @param methodIdentifier the internal ID of the method (can be blank)
* @param callerParameters the types of parameter to be passed to the method
* (required)
* @param targetEntity the type of entity being managed (required)
* @param idType specifies the ID type used by the target entity (required)
* @return <code>null</code> if a blank or unknown ID is given
*/
public static ServiceLayerMethod valueOf(final String methodIdentifier,
final List<JavaType> callerParameters, final JavaType targetEntity,
final JavaType idType) {
// Look for matching method name and parameter types
for (final ServiceLayerMethod method : values()) {
if (method.getKey().equals(methodIdentifier)
&& method.getParameterTypes(targetEntity, idType).equals(
callerParameters)) {
return method;
}
}
return null;
}
private final MethodMetadataCustomDataKey key;
/**
* Constructor
*
* @param key the internal key for this method (required)
*/
private ServiceLayerMethod(final MethodMetadataCustomDataKey key) {
Validate.notNull(key, "Method key is required");
this.key = key;
}
/**
* Returns the line(s) of Java code that implement this method
*
* @param lowerLayerAdditions the details of a call to a lower layer, if any
* @return a non-blank string
*/
public String getBody(final MemberTypeAdditions lowerLayerAdditions) {
if (lowerLayerAdditions == null) {
// No lower layer implements this method; so we stub it
return "throw new UnsupportedOperationException(\"Implement me!\");";
}
// A lower layer implements it; generate a delegation call
String line = "";
if (!isVoid()) {
line = "return ";
}
line += lowerLayerAdditions.getMethodCall() + ";";
return line;
}
/**
* Returns the key identifying this method
*
* @return a non-blank string that's unique within this enum
*/
public String getKey() {
return key.name();
}
/**
* Returns the name of this method, based on the given inputs
*
* @param annotationValues the values of the {@link RooService} annotation
* on the service
* @param entityType the type of domain entity managed by the service
* @param plural the plural form of the entity
* @return <code>null</code> if the method is not implemented
*/
public abstract String getName(ServiceAnnotationValues annotationValues,
JavaType entityType, String plural);
/**
* Returns the names of this method's declared parameters
*
* @param entityType the type of domain entity managed by the service
* (required)
* @param idType specifies the ID type used by the target entity (required)
* @return a non-<code>null</code> list (might be empty)
*/
public abstract List<JavaSymbolName> getParameterNames(JavaType entityType,
JavaType idType);
/**
* Returns the types and names of the parameters declared by this method for
* the given domain type
*
* @param domainType the domain type to which the method applies (required)
* @param idType specifies the ID type used by the target entity (required)
* @return a non-<code>null</code> list
*/
public PairList<JavaType, JavaSymbolName> getParameters(
final JavaType domainType, final JavaType idType) {
return new PairList<JavaType, JavaSymbolName>(getParameterTypes(
domainType, idType), getParameterNames(domainType, idType));
}
/**
* Returns the types of parameters taken by this method
*
* @param entityType the type of entity to which this method applies
* (required)
* @param idType specifies the ID type used by the target entity (required)
* @return a non-<code>null</code> copy of list (might be empty)
*/
public abstract List<JavaType> getParameterTypes(JavaType entityType,
JavaType idType);
/**
* Returns this method's return type
*
* @param entityType the type of entity being managed
* @return a non-<code>null</code> type
*/
public abstract JavaType getReturnType(JavaType entityType);
/**
* Returns the name of this method, based on the given inputs
*
* @param annotationValues the values of the {@link RooService} annotation
* on the service
* @param entityType the type of domain entity managed by the service
* @param plural the plural form of the entity
* @return <code>null</code> if the method is not implemented
*/
public JavaSymbolName getSymbolName(
final ServiceAnnotationValues annotationValues,
final JavaType entityType, final String plural) {
final String methodName = getName(annotationValues, entityType, plural);
if (StringUtils.isNotBlank(methodName)) {
return new JavaSymbolName(methodName);
}
return null;
}
/**
* Indicates whether this method is void, i.e. returns nothing
*
* @return see above
*/
boolean isVoid() {
return JavaType.VOID_PRIMITIVE.equals(getReturnType(null));
}
}