package org.springframework.roo.addon.layers.repository.mongo;
import static org.springframework.roo.classpath.customdata.CustomDataKeys.COUNT_ALL_METHOD;
import static org.springframework.roo.classpath.customdata.CustomDataKeys.FIND_ALL_METHOD;
import static org.springframework.roo.classpath.customdata.CustomDataKeys.FIND_ENTRIES_METHOD;
import static org.springframework.roo.classpath.customdata.CustomDataKeys.FIND_METHOD;
import static org.springframework.roo.classpath.customdata.CustomDataKeys.MERGE_METHOD;
import static org.springframework.roo.classpath.customdata.CustomDataKeys.PERSIST_METHOD;
import static org.springframework.roo.classpath.customdata.CustomDataKeys.REMOVE_METHOD;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.apache.commons.lang3.Validate;
import org.springframework.roo.classpath.customdata.tagkeys.MethodMetadataCustomDataKey;
import org.springframework.roo.classpath.layers.LayerType;
import org.springframework.roo.classpath.layers.MethodParameter;
import org.springframework.roo.model.JavaSymbolName;
import org.springframework.roo.model.JavaType;
/**
* A method provided by the {@link LayerType#REPOSITORY} layer.
*
* @author Stefan Schmidt
* @since 1.2.0
*/
public enum RepositoryMongoLayerMethod {
COUNT("count", COUNT_ALL_METHOD) {
@Override
public String getCall(final List<MethodParameter> parameters) {
return "count()";
}
@Override
public List<JavaSymbolName> getParameterNames(
final JavaType entityType, final JavaType idType) {
return Collections.emptyList();
}
@Override
protected List<JavaType> getParameterTypes(final JavaType targetEntity,
final JavaType idType) {
return Collections.emptyList();
}
@Override
public JavaType getReturnType(final JavaType entityType) {
return JavaType.LONG_PRIMITIVE;
}
},
/**
* Deletes the passed-in entity (does not delete by ID).
*/
DELETE("delete", REMOVE_METHOD) {
@Override
public String getCall(final List<MethodParameter> parameters) {
return "delete(" + parameters.get(0).getValue() + ")";
}
@Override
public List<JavaSymbolName> getParameterNames(
final JavaType entityType, final JavaType idType) {
return Arrays.asList(JavaSymbolName
.getReservedWordSafeName(entityType));
}
@Override
protected List<JavaType> getParameterTypes(final JavaType targetEntity,
final JavaType idType) {
return Arrays.asList(targetEntity);
}
@Override
public JavaType getReturnType(final JavaType entityType) {
return JavaType.VOID_PRIMITIVE;
}
},
FIND("find", FIND_METHOD) {
@Override
public String getCall(final List<MethodParameter> parameters) {
return "findOne(" + parameters.get(0).getValue() + ")";
}
@Override
public List<JavaSymbolName> getParameterNames(
final JavaType entityType, final JavaType idType) {
return Arrays.asList(new JavaSymbolName("id"));
}
@Override
protected List<JavaType> getParameterTypes(final JavaType entityType,
final JavaType idType) {
return Arrays.asList(idType);
}
@Override
public JavaType getReturnType(final JavaType entityType) {
return entityType;
}
},
FIND_ALL("findAll", FIND_ALL_METHOD) {
@Override
public String getCall(final List<MethodParameter> parameters) {
return "findAll()";
}
@Override
public List<JavaSymbolName> getParameterNames(
final JavaType entityType, final JavaType idType) {
return Collections.emptyList();
}
@Override
protected List<JavaType> getParameterTypes(final JavaType targetEntity,
final JavaType idType) {
return Collections.emptyList();
}
@Override
public JavaType getReturnType(final JavaType entityType) {
return JavaType.listOf(entityType);
}
},
/**
* Finds entities starting from a given zero-based index, up to a given
* maximum number of results. This method isn't directly implemented by
* Spring Data JPA, so we use its findAll(Pageable) API.
*/
FIND_ENTRIES("findEntries", FIND_ENTRIES_METHOD) {
@Override
public String getCall(final List<MethodParameter> parameters) {
final JavaSymbolName firstResultParameter = parameters.get(0)
.getValue();
final JavaSymbolName maxResultsParameter = parameters.get(1)
.getValue();
final String pageNumberExpression = firstResultParameter + " / "
+ maxResultsParameter;
return "findAll(new org.springframework.data.domain.PageRequest("
+ pageNumberExpression + ", " + maxResultsParameter
+ ")).getContent()";
}
@Override
public List<JavaSymbolName> getParameterNames(
final JavaType entityType, final JavaType idType) {
return Arrays.asList(new JavaSymbolName("firstResult"),
new JavaSymbolName("maxResults"));
}
@Override
protected List<JavaType> getParameterTypes(final JavaType targetEntity,
final JavaType idType) {
return Arrays
.asList(JavaType.INT_PRIMITIVE, JavaType.INT_PRIMITIVE);
}
@Override
public JavaType getReturnType(final JavaType entityType) {
return JavaType.listOf(entityType);
}
},
/**
* Spring Data JPA makes no distinction between
* create/persist/save/update/merge
*/
SAVE("save", MERGE_METHOD, PERSIST_METHOD) {
@Override
public String getCall(final List<MethodParameter> parameters) {
return "save(" + parameters.get(0).getValue() + ")";
}
@Override
public List<JavaSymbolName> getParameterNames(
final JavaType entityType, final JavaType idType) {
return Arrays.asList(JavaSymbolName
.getReservedWordSafeName(entityType));
}
@Override
protected List<JavaType> getParameterTypes(final JavaType targetEntity,
final JavaType idType) {
return Arrays.asList(targetEntity);
}
@Override
public JavaType getReturnType(final JavaType entityType) {
return JavaType.VOID_PRIMITIVE;
}
};
/**
* Returns the {@link RepositoryMongoLayerMethod} with the given ID and
* parameter types.
*
* @param methodId the ID to match upon
* @param parameterTypes the parameter types to match upon
* @param targetEntity the entity type being managed by the repository
* @param idType specifies the ID type used by the target entity (required)
* @return <code>null</code> if no such method exists
*/
public static RepositoryMongoLayerMethod valueOf(final String methodId,
final List<JavaType> parameterTypes, final JavaType targetEntity,
final JavaType idType) {
for (final RepositoryMongoLayerMethod method : values()) {
if (method.ids.contains(methodId)
&& method.getParameterTypes(targetEntity, idType).equals(
parameterTypes)) {
return method;
}
}
return null;
}
private final List<String> ids;
private final String name;
/**
* Constructor
*
* @param key the unique key for this method (required)
* @param name the Java name of this method (required)
*/
private RepositoryMongoLayerMethod(final String name,
final MethodMetadataCustomDataKey... keys) {
Validate.notBlank(name, "Name is required");
Validate.isTrue(keys.length > 0, "One or more ids are required");
ids = new ArrayList<String>();
for (final MethodMetadataCustomDataKey key : keys) {
ids.add(key.name());
}
this.name = name;
}
/**
* Returns a Java snippet that invokes this method (minus the target)
*
* @param parameters the parameters used by the caller; can be
* <code>null</code>
* @return a non-blank Java snippet
*/
public abstract String getCall(List<MethodParameter> parameters);
/**
* Returns the name of this method
*
* @return a non-blank name
*/
public String getName() {
return name;
}
/**
* 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);
/**
* Instances must return the types of parameters they take
*
* @param targetEntity the type of entity being managed (required)
* @param idType specifies the ID type used by the target entity (required)
* @return a non-<code>null</code> list
*/
protected abstract List<JavaType> getParameterTypes(JavaType targetEntity,
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);
}