package org.springframework.roo.addon.jpa.activerecord; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Iterator; 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.MethodParameter; import org.springframework.roo.model.JavaType; /** * Methods implemented by a user project entity. * * @author Andrew Swan * @author Stefan Schmidt * @since 1.2.0 */ enum EntityLayerMethod { // The names of these enum constants are arbitrary CLEAR(CustomDataKeys.CLEAR_METHOD, true) { @Override public String getName(final JpaCrudAnnotationValues annotationValues, final JavaType targetEntity, final String plural) { if (StringUtils.isNotBlank(annotationValues.getClearMethod())) { return annotationValues.getClearMethod(); } return null; } @Override protected List<JavaType> getParameterTypes(final JavaType targetEntity, final JavaType idType) { return Collections.emptyList(); } }, COUNT_ALL(CustomDataKeys.COUNT_ALL_METHOD, true) { @Override public String getName(final JpaCrudAnnotationValues annotationValues, final JavaType targetEntity, final String plural) { if (StringUtils.isNotBlank(annotationValues.getCountMethod())) { return annotationValues.getCountMethod() + plural; } return null; } @Override protected List<JavaType> getParameterTypes(final JavaType targetEntity, final JavaType idType) { return Collections.emptyList(); } }, FIND(CustomDataKeys.FIND_METHOD, true) { @Override public String getName(final JpaCrudAnnotationValues annotationValues, final JavaType targetEntity, final String plural) { if (StringUtils.isNotBlank(annotationValues.getFindMethod())) { return annotationValues.getFindMethod() + targetEntity.getSimpleTypeName(); } return null; } @Override protected List<JavaType> getParameterTypes(final JavaType targetEntity, final JavaType idType) { return Arrays.asList(idType); } }, FIND_ALL(CustomDataKeys.FIND_ALL_METHOD, true) { @Override public String getName(final JpaCrudAnnotationValues annotationValues, final JavaType targetEntity, final String plural) { if (StringUtils.isNotBlank(annotationValues.getFindAllMethod())) { return annotationValues.getFindAllMethod() + plural; } return null; } @Override protected List<JavaType> getParameterTypes(final JavaType targetEntity, final JavaType idType) { return Collections.emptyList(); } }, FIND_ENTRIES(CustomDataKeys.FIND_ENTRIES_METHOD, true) { @Override public String getName(final JpaCrudAnnotationValues annotationValues, final JavaType targetEntity, final String plural) { if (StringUtils.isNotBlank(annotationValues.getFindEntriesMethod())) { return annotationValues.getFindEntriesMethod() + targetEntity.getSimpleTypeName() + "Entries"; } return null; } @Override protected List<JavaType> getParameterTypes(final JavaType targetEntity, final JavaType idType) { return Arrays .asList(JavaType.INT_PRIMITIVE, JavaType.INT_PRIMITIVE); } }, FLUSH(CustomDataKeys.FLUSH_METHOD, false) { @Override public String getName(final JpaCrudAnnotationValues annotationValues, final JavaType targetEntity, final String plural) { if (StringUtils.isNotBlank(annotationValues.getFlushMethod())) { return annotationValues.getFlushMethod(); } return null; } @Override protected List<JavaType> getParameterTypes(final JavaType targetEntity, final JavaType idType) { return Arrays.asList(targetEntity); } }, MERGE(CustomDataKeys.MERGE_METHOD, false) { @Override public String getName(final JpaCrudAnnotationValues annotationValues, final JavaType targetEntity, final String plural) { if (StringUtils.isNotBlank(annotationValues.getMergeMethod())) { return annotationValues.getMergeMethod(); } return null; } @Override protected List<JavaType> getParameterTypes(final JavaType targetEntity, final JavaType idType) { return Arrays.asList(targetEntity); } }, PERSIST(CustomDataKeys.PERSIST_METHOD, false) { @Override public String getName(final JpaCrudAnnotationValues annotationValues, final JavaType targetEntity, final String plural) { if (StringUtils.isNotBlank(annotationValues.getPersistMethod())) { return annotationValues.getPersistMethod(); } return null; } @Override protected List<JavaType> getParameterTypes(final JavaType targetEntity, final JavaType idType) { return Arrays.asList(targetEntity); } }, REMOVE(CustomDataKeys.REMOVE_METHOD, false) { @Override public String getName(final JpaCrudAnnotationValues annotationValues, final JavaType targetEntity, final String plural) { if (StringUtils.isNotBlank(annotationValues.getRemoveMethod())) { return annotationValues.getRemoveMethod(); } return null; } @Override protected List<JavaType> getParameterTypes(final JavaType targetEntity, final JavaType idType) { return Arrays.asList(targetEntity); } }; /** * Returns the {@link EntityLayerMethod} with the given ID and parameter * types * * @param methodIdentifier the ID to seek; will not match if blank * @param callerParameters will not match if <code>null</code> * @param targetEntity * @param idType specifies the ID type used by the target entity (required) * @return */ public static EntityLayerMethod valueOf(final String methodIdentifier, final List<JavaType> callerParameters, final JavaType targetEntity, final JavaType idType) { // Look for matching method name and parameter types for (final EntityLayerMethod method : values()) { if (method.id.equals(methodIdentifier) && method.getParameterTypes(targetEntity, idType).equals( callerParameters)) { return method; } } return null; } private final String id; private final boolean isStatic; /** * Constructor * * @param id a unique id for this method (required) * @param isStatic whether this method is static */ private EntityLayerMethod(final MethodMetadataCustomDataKey key, final boolean isStatic) { Validate.notNull(key, "Key is required"); id = key.name(); this.isStatic = isStatic; } /** * Returns the Java snippet that invokes this method, including the target * if any * * @param annotationValues the CRUD-related values of the * {@link RooJpaActiveRecord} annotation on the entity type * @param targetEntity the type of entity being managed (required) * @param plural the plural form of the entity (required) * @param callerParameters the caller's method's parameters (required) * @return a non-blank Java snippet */ public String getCall(final JpaCrudAnnotationValues annotationValues, final JavaType targetEntity, final String plural, final List<MethodParameter> callerParameters) { final String target; if (isStatic) { target = targetEntity.getSimpleTypeName(); } else { target = callerParameters.get(0).getValue().getSymbolName(); } final List<MethodParameter> parameters = getParameters(callerParameters); return getCall(target, getName(annotationValues, targetEntity, plural), parameters.iterator()); } /** * Generates a method call from the given inputs * * @param targetName the name of the target on which the method is being * invoked (required) * @param methodName the name of the method being invoked (required) * @param parameterNames the names of the parameters (from the caller's POV) * @return a non-blank Java snippet ending in ")" */ private String getCall(final String targetName, final String methodName, final Iterator<MethodParameter> parameters) { final StringBuilder methodCall = new StringBuilder(); methodCall.append(targetName); methodCall.append("."); methodCall.append(methodName); methodCall.append("("); while (parameters.hasNext()) { methodCall.append(parameters.next().getValue().getSymbolName()); if (parameters.hasNext()) { methodCall.append(", "); } } methodCall.append(")"); return methodCall.toString(); } /** * Returns the desired name of this method based on the given annotation * values * * @param annotationValues the values of the {@link RooJpaActiveRecord} * annotation on the entity type * @param targetEntity the entity type (required) * @param plural the plural form of the entity (required) * @return <code>null</code> if the method isn't desired for that entity */ public abstract String getName(JpaCrudAnnotationValues annotationValues, JavaType targetEntity, String plural); /** * Returns the parameters to be passed when this method is invoked * * @param callerParameters the parameters provided by the caller (required) * @return a non-<code>null</code> List */ public List<MethodParameter> getParameters( final Collection<MethodParameter> callerParameters) { final List<MethodParameter> parameters = new ArrayList<MethodParameter>( callerParameters); if (!isStatic) { parameters.remove(0); // the instance doesn't need itself as a // parameter } return parameters; } /** * Returns the type of parameters taken by this method * * @param targetEntity the type of entity being managed * @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); /** * Indicates whether this method is static * * @return */ public boolean isStatic() { return isStatic; } }