Package org.springframework.roo.addon.web.mvc.controller.json

Source Code of org.springframework.roo.addon.web.mvc.controller.json.WebJsonMetadata

package org.springframework.roo.addon.web.mvc.controller.json;

import static java.lang.reflect.Modifier.PUBLIC;
import static org.springframework.roo.classpath.customdata.CustomDataKeys.FIND_ALL_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 static org.springframework.roo.model.JdkJavaType.CALENDAR;
import static org.springframework.roo.model.JdkJavaType.DATE;
import static org.springframework.roo.model.SpringJavaType.DATE_TIME_FORMAT;
import static org.springframework.roo.model.SpringJavaType.HTTP_HEADERS;
import static org.springframework.roo.model.SpringJavaType.HTTP_STATUS;
import static org.springframework.roo.model.SpringJavaType.PATH_VARIABLE;
import static org.springframework.roo.model.SpringJavaType.REQUEST_BODY;
import static org.springframework.roo.model.SpringJavaType.REQUEST_MAPPING;
import static org.springframework.roo.model.SpringJavaType.REQUEST_METHOD;
import static org.springframework.roo.model.SpringJavaType.REQUEST_PARAM;
import static org.springframework.roo.model.SpringJavaType.RESPONSE_BODY;
import static org.springframework.roo.model.SpringJavaType.RESPONSE_ENTITY;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.springframework.roo.addon.json.JsonMetadata;
import org.springframework.roo.addon.web.mvc.controller.details.FinderMetadataDetails;
import org.springframework.roo.addon.web.mvc.controller.scaffold.RooWebScaffold;
import org.springframework.roo.classpath.PhysicalTypeIdentifierNamingUtils;
import org.springframework.roo.classpath.PhysicalTypeMetadata;
import org.springframework.roo.classpath.customdata.tagkeys.MethodMetadataCustomDataKey;
import org.springframework.roo.classpath.details.FieldMetadata;
import org.springframework.roo.classpath.details.MemberFindingUtils;
import org.springframework.roo.classpath.details.MethodMetadataBuilder;
import org.springframework.roo.classpath.details.annotations.AnnotatedJavaType;
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.BooleanAttributeValue;
import org.springframework.roo.classpath.details.annotations.EnumAttributeValue;
import org.springframework.roo.classpath.details.annotations.StringAttributeValue;
import org.springframework.roo.classpath.itd.AbstractItdTypeDetailsProvidingMetadataItem;
import org.springframework.roo.classpath.itd.InvocableMemberBodyBuilder;
import org.springframework.roo.classpath.layers.MemberTypeAdditions;
import org.springframework.roo.metadata.MetadataIdentificationUtils;
import org.springframework.roo.model.DataType;
import org.springframework.roo.model.EnumDetails;
import org.springframework.roo.model.JavaSymbolName;
import org.springframework.roo.model.JavaType;
import org.springframework.roo.project.LogicalPath;

/**
* Metadata for Json functionality provided through {@link RooWebScaffold}.
*
* @author Stefan Schmidt
* @since 1.1.3
*/
public class WebJsonMetadata extends
        AbstractItdTypeDetailsProvidingMetadataItem {

    private static final String CONTENT_TYPE = "application/json";
    private static final String PROVIDES_TYPE_STRING = WebJsonMetadata.class
            .getName();
    private static final String PROVIDES_TYPE = MetadataIdentificationUtils
            .create(PROVIDES_TYPE_STRING);
    private static final JavaType RESPONSE_ENTITY_STRING = new JavaType(
            RESPONSE_ENTITY.getFullyQualifiedTypeName(), 0, DataType.TYPE,
            null, Arrays.asList(JavaType.STRING));

    public static String createIdentifier(final JavaType javaType,
            final LogicalPath path) {
        return PhysicalTypeIdentifierNamingUtils.createIdentifier(
                PROVIDES_TYPE_STRING, javaType, path);
    }

    public static JavaType getJavaType(final String metadataIdentificationString) {
        return PhysicalTypeIdentifierNamingUtils.getJavaType(
                PROVIDES_TYPE_STRING, metadataIdentificationString);
    }

    public static String getMetadataIdentiferType() {
        return PROVIDES_TYPE;
    }

    public static LogicalPath getPath(final String metadataIdentificationString) {
        return PhysicalTypeIdentifierNamingUtils.getPath(PROVIDES_TYPE_STRING,
                metadataIdentificationString);
    }

    public static boolean isValid(final String metadataIdentificationString) {
        return PhysicalTypeIdentifierNamingUtils.isValid(PROVIDES_TYPE_STRING,
                metadataIdentificationString);
    }

    private WebJsonAnnotationValues annotationValues;
    private boolean introduceLayerComponents;
    private JavaType jsonEnabledType;
    private String jsonEnabledTypeShortName;
    private JsonMetadata jsonMetadata;
    private String jsonBeanName;

    /**
     * Constructor
     *
     * @param identifier
     * @param aspectName
     * @param governorPhysicalTypeMetadata
     * @param annotationValues
     * @param persistenceAdditions
     * @param identifierField
     * @param plural
     * @param finderDetails (required)
     * @param jsonMetadata
     * @param introduceLayerComponents whether to introduce any required layer
     *            components (services, repositories, etc.)
     */
    public WebJsonMetadata(
            final String identifier,
            final JavaType aspectName,
            final PhysicalTypeMetadata governorPhysicalTypeMetadata,
            final WebJsonAnnotationValues annotationValues,
            final Map<MethodMetadataCustomDataKey, MemberTypeAdditions> persistenceAdditions,
            final FieldMetadata identifierField, final String plural,
            final Set<FinderMetadataDetails> finderDetails,
            final JsonMetadata jsonMetadata,
            final boolean introduceLayerComponents) {
        super(identifier, aspectName, governorPhysicalTypeMetadata);
        Validate.isTrue(isValid(identifier),
                "Metadata identification string '%s' is invalid", identifier);
        Validate.notNull(annotationValues, "Annotation values required");
        Validate.notNull(persistenceAdditions, "Persistence additions required");
        Validate.notNull(finderDetails,
                "Set of dynamic finder methods cannot be null");
        Validate.notNull(jsonMetadata, "Json metadata required");

        if (!isValid()) {
            return;
        }

        this.annotationValues = annotationValues;
        jsonEnabledType = annotationValues.getJsonObject();
        jsonEnabledTypeShortName = getShortName(jsonEnabledType);
        jsonBeanName = JavaSymbolName.getReservedWordSafeName(jsonEnabledType)
                .getSymbolName();

        this.introduceLayerComponents = introduceLayerComponents;
        this.jsonMetadata = jsonMetadata;

        final MemberTypeAdditions findMethod = persistenceAdditions
                .get(FIND_METHOD);
        builder.addMethod(getShowJsonMethod(identifierField, findMethod));

        final MemberTypeAdditions findAllMethod = persistenceAdditions
                .get(FIND_ALL_METHOD);
        builder.addMethod(getListJsonMethod(findAllMethod));

        final MemberTypeAdditions persistMethod = persistenceAdditions
                .get(PERSIST_METHOD);
        builder.addMethod(getCreateFromJsonMethod(persistMethod));
        builder.addMethod(getCreateFromJsonArrayMethod(persistMethod));

        final MemberTypeAdditions mergeMethod = persistenceAdditions
                .get(MERGE_METHOD);
        builder.addMethod(getUpdateFromJsonMethod(identifierField, mergeMethod));
//        builder.addMethod(getUpdateFromJsonArrayMethod(mergeMethod));

        final MemberTypeAdditions removeMethod = persistenceAdditions
                .get(REMOVE_METHOD);
        builder.addMethod(getDeleteFromJsonMethod(removeMethod,
                identifierField, findMethod));

        if (annotationValues.isExposeFinders()) {
            for (final FinderMetadataDetails finder : finderDetails) {
                builder.addMethod(getJsonFindMethod(finder, plural));
            }
        }

        itdTypeDetails = builder.build();
    }

    private void openTry(InvocableMemberBodyBuilder bodyBuilder) {
        bodyBuilder.appendFormalLine("try {");
        bodyBuilder.indent();
    }

    private void closeTry(InvocableMemberBodyBuilder bodyBuilder,
        String responseEntityShortName, String httpStatusShortName) {
        bodyBuilder.indentRemove();
        bodyBuilder.appendFormalLine("} catch (Exception e) {");
        bodyBuilder.indent();
        bodyBuilder.appendFormalLine("return new " + responseEntityShortName
                + "<String>(\"{\\\"ERROR\\\":\"+e.getMessage()+\"\\\"}\", headers, "
                + httpStatusShortName + ".INTERNAL_SERVER_ERROR);");
        bodyBuilder.indentRemove();
        bodyBuilder.appendFormalLine("}");
    }

    private MethodMetadataBuilder getCreateFromJsonArrayMethod(
            final MemberTypeAdditions persistMethod) {
        if (StringUtils
                .isBlank(annotationValues.getCreateFromJsonArrayMethod())
                || persistMethod == null) {
            return null;
        }
        final JavaSymbolName methodName = new JavaSymbolName(
                annotationValues.getCreateFromJsonArrayMethod());
        if (governorHasMethodWithSameName(methodName)) {
            return null;
        }

        final JavaSymbolName fromJsonArrayMethodName = jsonMetadata
                .getFromJsonArrayMethodName();

        final AnnotationMetadataBuilder requestBodyAnnotation = new AnnotationMetadataBuilder(
                REQUEST_BODY);
        final List<AnnotatedJavaType> parameterTypes = Arrays
                .asList(new AnnotatedJavaType(JavaType.STRING,
                        requestBodyAnnotation.build()));
        final List<JavaSymbolName> parameterNames = Arrays
                .asList(new JavaSymbolName("json"));

        final List<AnnotationAttributeValue<?>> requestMappingAttributes = new ArrayList<AnnotationAttributeValue<?>>();
        requestMappingAttributes.add(new StringAttributeValue(
                new JavaSymbolName("value"), "/jsonArray"));
        requestMappingAttributes.add(new EnumAttributeValue(new JavaSymbolName(
                "method"), new EnumDetails(REQUEST_METHOD, new JavaSymbolName(
                "POST"))));
        requestMappingAttributes.add(new StringAttributeValue(
                new JavaSymbolName("headers"), "Accept=application/json"));
        final AnnotationMetadataBuilder requestMapping = new AnnotationMetadataBuilder(
                REQUEST_MAPPING, requestMappingAttributes);
        final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
        annotations.add(requestMapping);

        final List<JavaType> params = new ArrayList<JavaType>();
        params.add(jsonEnabledType);

        final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
        final String httpHeadersShortName = getShortName(HTTP_HEADERS);
        bodyBuilder.appendFormalLine(httpHeadersShortName + " headers = new "
                + httpHeadersShortName + "();");
        bodyBuilder.appendFormalLine("headers.add(\"Content-Type\", \""
                + CONTENT_TYPE + "\");");
        openTry(bodyBuilder);
        bodyBuilder.appendFormalLine("for (" + jsonEnabledTypeShortName + " "
                + jsonBeanName + ": " + jsonEnabledTypeShortName + "."
                + fromJsonArrayMethodName.getSymbolName() + "(json)) {");
        bodyBuilder.indent();
        bodyBuilder.appendFormalLine(persistMethod.getMethodCall() + ";");
        bodyBuilder.indentRemove();
        bodyBuilder.appendFormalLine("}");
        bodyBuilder
                .appendFormalLine("return new ResponseEntity<String>(headers, "
                + getShortName(HTTP_STATUS) + ".CREATED);");
        closeTry(bodyBuilder, getShortName(RESPONSE_ENTITY),
                getShortName(HTTP_STATUS));

        if (introduceLayerComponents) {
            persistMethod.copyAdditionsTo(builder, governorTypeDetails);
        }

        final MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
                getId(), PUBLIC, methodName, RESPONSE_ENTITY_STRING,
                parameterTypes, parameterNames, bodyBuilder);
        methodBuilder.setAnnotations(annotations);
        return methodBuilder;
    }

    private MethodMetadataBuilder getCreateFromJsonMethod(
            final MemberTypeAdditions persistMethod) {
        if (StringUtils.isBlank(annotationValues.getCreateFromJsonMethod())
                || persistMethod == null) {
            return null;
        }
        final JavaSymbolName methodName = new JavaSymbolName(
                annotationValues.getCreateFromJsonMethod());
        if (governorHasMethodWithSameName(methodName)) {
            return null;
        }

        final JavaSymbolName fromJsonMethodName = jsonMetadata
                .getFromJsonMethodName();

        final AnnotationMetadataBuilder requestBodyAnnotation = new AnnotationMetadataBuilder(
                REQUEST_BODY);
        final List<AnnotatedJavaType> parameterTypes = Arrays
                .asList(new AnnotatedJavaType(JavaType.STRING,
                    requestBodyAnnotation.build()),
        AnnotatedJavaType.convertFromJavaType(new JavaType(
            "org.springframework.web.util.UriComponentsBuilder")));
        final List<JavaSymbolName> parameterNames = Arrays
            .asList(
        new JavaSymbolName("json"), new JavaSymbolName("uriBuilder"));

        final List<AnnotationAttributeValue<?>> requestMappingAttributes = new ArrayList<AnnotationAttributeValue<?>>();
        requestMappingAttributes.add(new EnumAttributeValue(new JavaSymbolName(
                "method"), new EnumDetails(REQUEST_METHOD, new JavaSymbolName(
                "POST"))));
        requestMappingAttributes.add(new StringAttributeValue(
                new JavaSymbolName("headers"), "Accept=application/json"));
        final AnnotationMetadataBuilder requestMapping = new AnnotationMetadataBuilder(
                REQUEST_MAPPING, requestMappingAttributes);
        final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
        annotations.add(requestMapping);

        final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
        final String httpHeadersShortName = getShortName(HTTP_HEADERS);
        bodyBuilder.appendFormalLine(httpHeadersShortName + " headers = new "
                + httpHeadersShortName + "();");
        bodyBuilder.appendFormalLine("headers.add(\"Content-Type\", \""
                + CONTENT_TYPE + "\");");
        openTry(bodyBuilder);
        bodyBuilder.appendFormalLine(jsonEnabledTypeShortName + " "
                + jsonBeanName + " = " + jsonEnabledTypeShortName + "."
                + fromJsonMethodName.getSymbolName() + "(json);");
        bodyBuilder.appendFormalLine(persistMethod.getMethodCall() + ";");
        bodyBuilder.appendFormalLine(
                "RequestMapping a = (RequestMapping) getClass().getAnnotation(RequestMapping.class);");
        bodyBuilder.appendFormalLine(
                "headers.add(\"Location\",uriBuilder.path(a.value()[0]+\"/\"+"
                + jsonBeanName
                + ".getId().toString()).build().toUriString());");
        bodyBuilder
                .appendFormalLine("return new ResponseEntity<String>(headers, "
                + getShortName(HTTP_STATUS) + ".CREATED);");
        closeTry(bodyBuilder, getShortName(RESPONSE_ENTITY),
                getShortName(HTTP_STATUS));

        if (introduceLayerComponents) {
            persistMethod.copyAdditionsTo(builder, governorTypeDetails);
        }

        final MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
                getId(), PUBLIC, methodName, RESPONSE_ENTITY_STRING,
                parameterTypes, parameterNames, bodyBuilder);
        methodBuilder.setAnnotations(annotations);
        return methodBuilder;
    }

    private MethodMetadataBuilder getDeleteFromJsonMethod(
            final MemberTypeAdditions removeMethod,
            final FieldMetadata identifierField,
            final MemberTypeAdditions findMethod) {
        if (StringUtils.isBlank(annotationValues.getDeleteFromJsonMethod())
                || removeMethod == null || identifierField == null
                || findMethod == null) {
            return null;
        }
        final JavaSymbolName methodName = new JavaSymbolName(
                annotationValues.getDeleteFromJsonMethod());
        if (governorHasMethodWithSameName(methodName)) {
            return null;
        }

        final List<AnnotationAttributeValue<?>> attributes = new ArrayList<AnnotationAttributeValue<?>>();
        attributes.add(new StringAttributeValue(new JavaSymbolName("value"),
                identifierField.getFieldName().getSymbolName()));
        final AnnotationMetadataBuilder pathVariableAnnotation = new AnnotationMetadataBuilder(
                PATH_VARIABLE, attributes);

        final List<AnnotatedJavaType> parameterTypes = Arrays
                .asList(new AnnotatedJavaType(identifierField.getFieldType(),
                        pathVariableAnnotation.build()));
        final List<JavaSymbolName> parameterNames = Arrays
                .asList(identifierField.getFieldName());

        final List<AnnotationAttributeValue<?>> requestMappingAttributes = new ArrayList<AnnotationAttributeValue<?>>();
        requestMappingAttributes
                .add(new StringAttributeValue(new JavaSymbolName("value"), "/{"
                        + identifierField.getFieldName().getSymbolName() + "}"));
        requestMappingAttributes.add(new EnumAttributeValue(new JavaSymbolName(
                "method"), new EnumDetails(REQUEST_METHOD, new JavaSymbolName(
                "DELETE"))));
        requestMappingAttributes.add(new StringAttributeValue(
                new JavaSymbolName("headers"), "Accept=application/json"));
        final AnnotationMetadataBuilder requestMapping = new AnnotationMetadataBuilder(
                REQUEST_MAPPING, requestMappingAttributes);

        final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
        annotations.add(requestMapping);

        final String httpHeadersShortName = getShortName(HTTP_HEADERS);

        final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
        bodyBuilder.appendFormalLine(httpHeadersShortName + " headers = new "
                + httpHeadersShortName + "();");
        bodyBuilder.appendFormalLine("headers.add(\"Content-Type\", \""
                + CONTENT_TYPE + "\");");
        openTry(bodyBuilder);
        bodyBuilder.appendFormalLine(jsonEnabledTypeShortName + " "
                + jsonBeanName + " = " + findMethod.getMethodCall() + ";");
        bodyBuilder.appendFormalLine("if (" + jsonBeanName + " == null) {");
        bodyBuilder.indent();
        bodyBuilder.appendFormalLine("return new "
                + getShortName(RESPONSE_ENTITY) + "<String>(headers, "
                + getShortName(HTTP_STATUS) + ".NOT_FOUND);");
        bodyBuilder.indentRemove();
        bodyBuilder.appendFormalLine("}");
        bodyBuilder.appendFormalLine(removeMethod.getMethodCall() + ";");
        bodyBuilder.appendFormalLine(
                "return new ResponseEntity<String>(headers, "
                + getShortName(HTTP_STATUS) + ".OK);");
        closeTry(bodyBuilder, getShortName(RESPONSE_ENTITY),
                getShortName(HTTP_STATUS));

        if (introduceLayerComponents) {
            removeMethod.copyAdditionsTo(builder, governorTypeDetails);
            findMethod.copyAdditionsTo(builder, governorTypeDetails);
        }
        final MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
                getId(), PUBLIC, methodName, RESPONSE_ENTITY_STRING,
                parameterTypes, parameterNames, bodyBuilder);
        methodBuilder.setAnnotations(annotations);
        return methodBuilder;
    }

    private MethodMetadataBuilder getJsonFindMethod(
            final FinderMetadataDetails finderDetails, final String plural) {
        if (finderDetails == null
                || jsonMetadata.getToJsonArrayMethodName() == null) {
            return null;
        }
        final JavaSymbolName finderMethodName = new JavaSymbolName("json"
                + StringUtils.capitalize(finderDetails
                        .getFinderMethodMetadata().getMethodName()
                        .getSymbolName()));
        if (governorHasMethodWithSameName(finderMethodName)) {
            return null;
        }

        final List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
        final List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
        final StringBuilder methodParams = new StringBuilder();

        for (final FieldMetadata field : finderDetails
                .getFinderMethodParamFields()) {
            final JavaSymbolName fieldName = field.getFieldName();
            final List<AnnotationMetadata> annotations = new ArrayList<AnnotationMetadata>();
            final List<AnnotationAttributeValue<?>> attributes = new ArrayList<AnnotationAttributeValue<?>>();
            attributes.add(new StringAttributeValue(
                    new JavaSymbolName("value"), StringUtils
                            .uncapitalize(fieldName.getSymbolName())));
            if (field.getFieldType().equals(JavaType.BOOLEAN_PRIMITIVE)
                    || field.getFieldType().equals(JavaType.BOOLEAN_OBJECT)) {
                attributes.add(new BooleanAttributeValue(new JavaSymbolName(
                        "required"), false));
            }
            final AnnotationMetadataBuilder requestParamAnnotation = new AnnotationMetadataBuilder(
                    REQUEST_PARAM, attributes);
            annotations.add(requestParamAnnotation.build());
            if (field.getFieldType().equals(DATE)
                    || field.getFieldType().equals(CALENDAR)) {
                final AnnotationMetadata annotation = MemberFindingUtils
                        .getAnnotationOfType(field.getAnnotations(),
                                DATE_TIME_FORMAT);
                if (annotation != null) {
                    annotations.add(annotation);
                }
            }
            parameterNames.add(fieldName);
            parameterTypes.add(new AnnotatedJavaType(field.getFieldType(),
                    annotations));

            if (field.getFieldType().equals(JavaType.BOOLEAN_OBJECT)) {
                methodParams.append(field.getFieldName()
                        + " == null ? Boolean.FALSE : " + field.getFieldName()
                        + ", ");
            }
            else {
                methodParams.append(field.getFieldName() + ", ");
            }
        }

        if (methodParams.length() > 0) {
            methodParams.delete(methodParams.length() - 2,
                    methodParams.length());
        }

        final List<JavaSymbolName> newParamNames = new ArrayList<JavaSymbolName>();
        newParamNames.addAll(parameterNames);

        final List<AnnotationAttributeValue<?>> requestMappingAttributes = new ArrayList<AnnotationAttributeValue<?>>();
        requestMappingAttributes.add(new StringAttributeValue(
                new JavaSymbolName("params"), "find="
                        + finderDetails.getFinderMethodMetadata()
                                .getMethodName().getSymbolName()
                                .replaceFirst("find" + plural, "")));
        requestMappingAttributes.add(new StringAttributeValue(
                new JavaSymbolName("headers"), "Accept=application/json"));
        final AnnotationMetadataBuilder requestMapping = new AnnotationMetadataBuilder(
                REQUEST_MAPPING, requestMappingAttributes);
        final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
        annotations.add(requestMapping);
        annotations.add(new AnnotationMetadataBuilder(RESPONSE_BODY));

        final String httpHeadersShortName = getShortName(HTTP_HEADERS);
        final String responseEntityShortName = getShortName(RESPONSE_ENTITY);
        final String httpStatusShortName = getShortName(HTTP_STATUS);

        final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
        bodyBuilder.appendFormalLine(httpHeadersShortName + " headers = new "
                + httpHeadersShortName + "();");
        openTry(bodyBuilder);
        bodyBuilder.appendFormalLine("headers.add(\"Content-Type\", \""
                + CONTENT_TYPE + "; charset=utf-8\");");
        bodyBuilder.appendFormalLine("return new "
                + responseEntityShortName
                + "<String>("
                + jsonEnabledTypeShortName
                + "."
                + jsonMetadata.getToJsonArrayMethodName().getSymbolName()
                        .toString()
                + "("
                + jsonEnabledTypeShortName
                + "."
                + finderDetails.getFinderMethodMetadata().getMethodName()
                        .getSymbolName() + "(" + methodParams.toString()
                + ").getResultList()), headers, " + httpStatusShortName
                + ".OK);");
        closeTry(bodyBuilder, responseEntityShortName, httpStatusShortName);

        final MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
                getId(), PUBLIC, finderMethodName, RESPONSE_ENTITY_STRING,
                parameterTypes, newParamNames, bodyBuilder);
        methodBuilder.setAnnotations(annotations);
        return methodBuilder;
    }

    private MethodMetadataBuilder getListJsonMethod(
            final MemberTypeAdditions findAllMethod) {
        if (StringUtils.isBlank(annotationValues.getListJsonMethod())
                || findAllMethod == null) {
            return null;
        }
        final JavaSymbolName methodName = new JavaSymbolName(
                annotationValues.getListJsonMethod());
        if (governorHasMethodWithSameName(methodName)) {
            return null;
        }

        final JavaSymbolName toJsonArrayMethodName = jsonMetadata
                .getToJsonArrayMethodName();

        final List<AnnotationAttributeValue<?>> requestMappingAttributes = new ArrayList<AnnotationAttributeValue<?>>();
        requestMappingAttributes.add(new StringAttributeValue(
                new JavaSymbolName("headers"), "Accept=application/json"));
        final AnnotationMetadataBuilder requestMapping = new AnnotationMetadataBuilder(
                REQUEST_MAPPING, requestMappingAttributes);
        final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
        annotations.add(requestMapping);

        annotations.add(new AnnotationMetadataBuilder(RESPONSE_BODY));

        final String httpHeadersShortName = getShortName(HTTP_HEADERS);
        final String responseEntityShortName = getShortName(RESPONSE_ENTITY);
        final String httpStatusShortName = getShortName(HTTP_STATUS);

        final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
        bodyBuilder.appendFormalLine(httpHeadersShortName + " headers = new "
                + httpHeadersShortName + "();");
        bodyBuilder.appendFormalLine("headers.add(\"Content-Type\", \""
                + CONTENT_TYPE + "; charset=utf-8\");");
        openTry(bodyBuilder);
        final JavaType list = new JavaType(List.class.getName(), 0,
                DataType.TYPE, null, Arrays.asList(jsonEnabledType));
        bodyBuilder.appendFormalLine(getShortName(list) + " result = "
                + findAllMethod.getMethodCall() + ";");
        bodyBuilder.appendFormalLine("return new " + responseEntityShortName
                + "<String>(" + jsonEnabledTypeShortName + "."
                + toJsonArrayMethodName.getSymbolName() + "(result), headers, "
                + httpStatusShortName + ".OK);");
        closeTry(bodyBuilder, responseEntityShortName, httpStatusShortName);

        if (introduceLayerComponents) {
            findAllMethod.copyAdditionsTo(builder, governorTypeDetails);
        }

        final MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
                getId(), PUBLIC, methodName, RESPONSE_ENTITY_STRING,
                bodyBuilder);
        methodBuilder.setAnnotations(annotations);
        return methodBuilder;
    }

    private String getShortName(final JavaType type) {
        return type.getNameIncludingTypeParameters(false,
                builder.getImportRegistrationResolver());
    }

    private MethodMetadataBuilder getShowJsonMethod(
            final FieldMetadata identifierField,
            final MemberTypeAdditions findMethod) {
        if (StringUtils.isBlank(annotationValues.getShowJsonMethod())
                || identifierField == null || findMethod == null) {
            return null;
        }
        final JavaSymbolName methodName = new JavaSymbolName(
                annotationValues.getShowJsonMethod());
        if (governorHasMethodWithSameName(methodName)) {
            return null;
        }

        final JavaSymbolName toJsonMethodName = jsonMetadata
                .getToJsonMethodName();

        final List<AnnotationAttributeValue<?>> attributes = new ArrayList<AnnotationAttributeValue<?>>();
        attributes.add(new StringAttributeValue(new JavaSymbolName("value"),
                identifierField.getFieldName().getSymbolName()));
        final AnnotationMetadataBuilder pathVariableAnnotation = new AnnotationMetadataBuilder(
                PATH_VARIABLE, attributes);

        final List<AnnotatedJavaType> parameterTypes = Arrays
                .asList(new AnnotatedJavaType(identifierField.getFieldType(),
                        pathVariableAnnotation.build()));
        final List<JavaSymbolName> parameterNames = Arrays
                .asList(new JavaSymbolName(identifierField.getFieldName()
                        .getSymbolName()));

        final List<AnnotationAttributeValue<?>> requestMappingAttributes = new ArrayList<AnnotationAttributeValue<?>>();
        requestMappingAttributes
                .add(new StringAttributeValue(new JavaSymbolName("value"), "/{"
                        + identifierField.getFieldName().getSymbolName() + "}"));
        requestMappingAttributes
                .add(new EnumAttributeValue(new JavaSymbolName(
                "method"), new EnumDetails(REQUEST_METHOD, new JavaSymbolName(
                "GET"))));
        requestMappingAttributes.add(new StringAttributeValue(
                new JavaSymbolName("headers"), "Accept=application/json"));
        final AnnotationMetadataBuilder requestMapping = new AnnotationMetadataBuilder(
                REQUEST_MAPPING, requestMappingAttributes);

        final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
        annotations.add(requestMapping);
        annotations.add(new AnnotationMetadataBuilder(RESPONSE_BODY));

        final String httpHeadersShortName = getShortName(HTTP_HEADERS);
        final String responseEntityShortName = getShortName(RESPONSE_ENTITY);
        final String httpStatusShortName = getShortName(HTTP_STATUS);

        final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
        bodyBuilder.appendFormalLine(httpHeadersShortName + " headers = new "
                + httpHeadersShortName + "();");
        bodyBuilder.appendFormalLine("headers.add(\"Content-Type\", \""
                + CONTENT_TYPE + "; charset=utf-8\");");
        openTry(bodyBuilder);
        bodyBuilder.appendFormalLine(jsonEnabledTypeShortName + " "
                + jsonBeanName + " = " + findMethod.getMethodCall() + ";");
        bodyBuilder.appendFormalLine("if (" + jsonBeanName + " == null) {");
        bodyBuilder.indent();
        bodyBuilder.appendFormalLine("return new " + responseEntityShortName
                + "<String>(headers, " + httpStatusShortName + ".NOT_FOUND);");
        bodyBuilder.indentRemove();
        bodyBuilder.appendFormalLine("}");
        bodyBuilder.appendFormalLine("return new " + responseEntityShortName
                + "<String>(" + jsonBeanName + "."
                + toJsonMethodName.getSymbolName() + "(), headers, "
                + httpStatusShortName + ".OK);");
        closeTry(bodyBuilder, responseEntityShortName, httpStatusShortName);

        if (introduceLayerComponents) {
            findMethod.copyAdditionsTo(builder, governorTypeDetails);
        }

        final MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
                getId(), PUBLIC, methodName, RESPONSE_ENTITY_STRING,
                parameterTypes, parameterNames, bodyBuilder);
        methodBuilder.setAnnotations(annotations);
        return methodBuilder;
    }

    private MethodMetadataBuilder getUpdateFromJsonArrayMethod(
            final MemberTypeAdditions mergeMethod) {
        if (StringUtils
                .isBlank(annotationValues.getUpdateFromJsonArrayMethod())
                || mergeMethod == null) {
            return null;
        }
        final JavaSymbolName methodName = new JavaSymbolName(
                annotationValues.getUpdateFromJsonArrayMethod());
        if (governorHasMethodWithSameName(methodName)) {
            return null;
        }

        final JavaSymbolName fromJsonArrayMethodName = jsonMetadata
                .getFromJsonArrayMethodName();

        final AnnotationMetadataBuilder requestBodyAnnotation = new AnnotationMetadataBuilder(
                REQUEST_BODY);

        final List<AnnotatedJavaType> parameterTypes = Arrays
                .asList(new AnnotatedJavaType(JavaType.STRING,
                        requestBodyAnnotation.build()));
        final List<JavaSymbolName> parameterNames = Arrays
                .asList(new JavaSymbolName("json"));

        final List<AnnotationAttributeValue<?>> requestMappingAttributes = new ArrayList<AnnotationAttributeValue<?>>();
        requestMappingAttributes.add(new StringAttributeValue(
                new JavaSymbolName("value"), "/jsonArray"));
        requestMappingAttributes.add(new EnumAttributeValue(new JavaSymbolName(
                "method"), new EnumDetails(REQUEST_METHOD, new JavaSymbolName(
                "PUT"))));
        requestMappingAttributes.add(new StringAttributeValue(
                new JavaSymbolName("headers"), "Accept=application/json"));
        final AnnotationMetadataBuilder requestMapping = new AnnotationMetadataBuilder(
                REQUEST_MAPPING, requestMappingAttributes);
        final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
        annotations.add(requestMapping);

        final List<JavaType> params = new ArrayList<JavaType>();
        params.add(jsonEnabledType);

        final String httpHeadersShortName = getShortName(HTTP_HEADERS);
        final String responseEntityShortName = getShortName(RESPONSE_ENTITY);
        final String httpStatusShortName = getShortName(HTTP_STATUS);

        final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
        bodyBuilder.appendFormalLine(httpHeadersShortName + " headers = new "
                + httpHeadersShortName + "();");
        bodyBuilder.appendFormalLine("headers.add(\"Content-Type\", \""
                + CONTENT_TYPE + "\");");
        openTry(bodyBuilder);
        bodyBuilder.appendFormalLine("for (" + jsonEnabledTypeShortName + " "
                + jsonBeanName + ": " + jsonEnabledTypeShortName + "."
                + fromJsonArrayMethodName.getSymbolName() + "(json)) {");
        bodyBuilder.indent();
        bodyBuilder.appendFormalLine("if (" + mergeMethod.getMethodCall()
                + " == null) {");
        bodyBuilder.indent();
        bodyBuilder
                .appendFormalLine("return new ResponseEntity<String>(headers, "
                        + getShortName(HTTP_STATUS) + ".NOT_FOUND);");
        bodyBuilder.indentRemove();
        bodyBuilder.appendFormalLine("}");
        bodyBuilder.indentRemove();
        bodyBuilder.appendFormalLine("}");
        bodyBuilder
                .appendFormalLine("return new ResponseEntity<String>(headers, "
                        + getShortName(HTTP_STATUS) + ".OK);");
        closeTry(bodyBuilder, responseEntityShortName, httpStatusShortName);

        if (introduceLayerComponents) {
            mergeMethod.copyAdditionsTo(builder, governorTypeDetails);
        }

        final MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
                getId(), PUBLIC, methodName, RESPONSE_ENTITY_STRING,
                parameterTypes, parameterNames, bodyBuilder);
        methodBuilder.setAnnotations(annotations);
        return methodBuilder;
    }

    private MethodMetadataBuilder getUpdateFromJsonMethod(
        final FieldMetadata identifierField,
            final MemberTypeAdditions mergeMethod) {
        if (StringUtils.isBlank(annotationValues.getUpdateFromJsonMethod())
                || mergeMethod == null) {
            return null;
        }
        final JavaSymbolName methodName = new JavaSymbolName(
                annotationValues.getUpdateFromJsonMethod());
        if (governorHasMethodWithSameName(methodName)) {
            return null;
        }

        final JavaSymbolName fromJsonMethodName = jsonMetadata
                .getFromJsonMethodName();
        final JavaSymbolName identifierFieldName = identifierField.getFieldName();

        final AnnotationMetadataBuilder requestBodyAnnotation = new AnnotationMetadataBuilder(
                REQUEST_BODY);

        final List<AnnotationAttributeValue<?>> attributes = new ArrayList<AnnotationAttributeValue<?>>();
        attributes.add(new StringAttributeValue(new JavaSymbolName("value"),
                identifierFieldName.getSymbolName()));
        final AnnotationMetadataBuilder pathVariableAnnotation = new AnnotationMetadataBuilder(
                PATH_VARIABLE, attributes);

        final List<AnnotatedJavaType> parameterTypes = Arrays
                .asList(new AnnotatedJavaType(JavaType.STRING,
                          requestBodyAnnotation.build()),
                        new AnnotatedJavaType(identifierField.getFieldType(),
                            pathVariableAnnotation.build()));
        final List<JavaSymbolName> parameterNames = Arrays
                .asList(new JavaSymbolName("json"),
                        identifierFieldName);

        final List<AnnotationAttributeValue<?>> requestMappingAttributes = new ArrayList<AnnotationAttributeValue<?>>();
        requestMappingAttributes.add(new StringAttributeValue(new JavaSymbolName("value"),
                "/{" + identifierFieldName.getSymbolName() + "}" ));
        requestMappingAttributes.add(new EnumAttributeValue(new JavaSymbolName(
                "method"), new EnumDetails(REQUEST_METHOD, new JavaSymbolName(
                "PUT"))));
        requestMappingAttributes.add(new StringAttributeValue(
                new JavaSymbolName("headers"), "Accept=application/json"));
        final AnnotationMetadataBuilder requestMapping = new AnnotationMetadataBuilder(
                REQUEST_MAPPING, requestMappingAttributes);
        final List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
        annotations.add(requestMapping);

        final String httpHeadersShortName = getShortName(HTTP_HEADERS);

        final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
        bodyBuilder.appendFormalLine(httpHeadersShortName + " headers = new "
                + httpHeadersShortName + "();");
        bodyBuilder.appendFormalLine("headers.add(\"Content-Type\", \""
                + CONTENT_TYPE + "\");");
        openTry(bodyBuilder);
        bodyBuilder.appendFormalLine(jsonEnabledTypeShortName + " "
                + jsonBeanName + " = " + jsonEnabledTypeShortName + "."
                + fromJsonMethodName.getSymbolName() + "(json);");
        bodyBuilder.appendFormalLine(jsonBeanName + "." +
                getMutatorMethod(identifierFieldName, jsonEnabledType).getMethodName() +
                "(" + identifierFieldName.getSymbolName() + ");");
        bodyBuilder.appendFormalLine("if (" + mergeMethod.getMethodCall()
                + " == null) {");
        bodyBuilder.indent();
        bodyBuilder
                .appendFormalLine("return new ResponseEntity<String>(headers, "
                        + getShortName(HTTP_STATUS) + ".NOT_FOUND);");
        bodyBuilder.indentRemove();
        bodyBuilder.appendFormalLine("}");
        bodyBuilder
                .appendFormalLine("return new ResponseEntity<String>(headers, "
                        + getShortName(HTTP_STATUS) + ".OK);");
        closeTry(bodyBuilder, getShortName(RESPONSE_ENTITY),
                getShortName(HTTP_STATUS));

        if (introduceLayerComponents) {
            mergeMethod.copyAdditionsTo(builder, governorTypeDetails);
        }

        final MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
                getId(), PUBLIC, methodName, RESPONSE_ENTITY_STRING,
                parameterTypes, parameterNames, bodyBuilder);
        methodBuilder.setAnnotations(annotations);
        return methodBuilder;
    }

    @Override
    public String toString() {
        final ToStringBuilder builder = new ToStringBuilder(this);
        builder.append("identifier", getId());
        builder.append("valid", valid);
        builder.append("aspectName", aspectName);
        builder.append("destinationType", destination);
        builder.append("governor", governorPhysicalTypeMetadata.getId());
        builder.append("itdTypeDetails", itdTypeDetails);
        return builder.toString();
    }
}
TOP

Related Classes of org.springframework.roo.addon.web.mvc.controller.json.WebJsonMetadata

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.