com.amazonaws.util.awsclientgenerator.transform.C2jModelToGeneratorModelTransformer.java Source code

Java tutorial

Introduction

Here is the source code for com.amazonaws.util.awsclientgenerator.transform.C2jModelToGeneratorModelTransformer.java

Source

/*
* Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
*  http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

package com.amazonaws.util.awsclientgenerator.transform;

import com.amazonaws.util.awsclientgenerator.domainmodels.c2j.*;
import com.amazonaws.util.awsclientgenerator.domainmodels.codegeneration.Error;
import com.amazonaws.util.awsclientgenerator.domainmodels.codegeneration.*;
import com.amazonaws.util.awsclientgenerator.domainmodels.codegeneration.cpp.CppViewHelper;
import org.apache.commons.lang.WordUtils;

import java.util.*;
import java.util.stream.Collectors;

public class C2jModelToGeneratorModelTransformer {

    private final C2jServiceModel c2jServiceModel;
    Map<String, Shape> shapes;
    Map<String, Operation> operations;
    Set<Error> allErrors;

    public C2jModelToGeneratorModelTransformer(C2jServiceModel c2jServiceModel) {
        this.c2jServiceModel = c2jServiceModel;
    }

    public ServiceModel convert() {
        ServiceModel serviceModel = new ServiceModel();
        serviceModel.setMetadata(convertMetadata());
        serviceModel.setVersion(c2jServiceModel.getVersion());
        serviceModel.setDocumentation(formatDocumentation(c2jServiceModel.getDocumentation(), 3));

        convertShapes();
        convertOperations();
        removeUnreferencedShapes();
        postProcessShapes();

        serviceModel.setShapes(shapes);
        serviceModel.setOperations(operations);
        serviceModel.setServiceErrors(filterOutCoreErrors(allErrors));
        return serviceModel;
    }

    String formatDocumentation(String documentation, int indentDepth) {
        if (documentation != null) {
            String tabString = "";
            for (int i = 0; i < indentDepth; ++i) {
                tabString += " ";
            }
            String wrappedString = WordUtils.wrap(documentation, 80, System.lineSeparator() + tabString + "* ",
                    false);
            return wrappedString.replace("/*", "/ *").replace("*/", "* /");
        }
        return null;
    }

    void removeUnreferencedShapes() {
        Iterator<String> iterator = shapes.keySet().iterator();
        while (iterator.hasNext()) {
            String key = iterator.next();
            if (!shapes.get(key).isReferenced()) {
                iterator.remove();
            }
        }
    }

    Metadata convertMetadata() {
        C2jMetadata c2jMetadata = c2jServiceModel.getMetadata();

        Metadata metadata = new Metadata();
        metadata.setApiVersion(c2jMetadata.getApiVersion());
        metadata.setEndpointPrefix(c2jMetadata.getEndpointPrefix());
        metadata.setSigningName(c2jMetadata.getSigningName() != null ? c2jMetadata.getSigningName()
                : c2jMetadata.getEndpointPrefix());
        metadata.setJsonVersion(c2jMetadata.getJsonVersion());
        metadata.setProtocol(c2jMetadata.getProtocol());
        metadata.setNamespace(c2jMetadata.getServiceAbbreviation());
        metadata.setServiceFullName(c2jMetadata.getServiceFullName());
        metadata.setSignatureVersion(c2jMetadata.getSignatureVersion());
        metadata.setTargetPrefix(c2jMetadata.getTargetPrefix());
        metadata.setGlobalEndpoint(c2jMetadata.getGlobalEndpoint());

        if (metadata.getNamespace() == null || metadata.getNamespace().isEmpty()) {
            metadata.setNamespace(sanitizeServiceAbbreviation(metadata.getServiceFullName()));
        } else {
            metadata.setNamespace(sanitizeServiceAbbreviation(metadata.getNamespace()));
        }

        metadata.setClassNamePrefix(CppViewHelper.convertToUpperCamel(
                ifNotNullOrEmpty(c2jMetadata.getClientClassNamePrefix(), metadata.getNamespace())));
        metadata.setProjectName(
                ifNotNullOrEmpty(c2jMetadata.getClientProjectName(), c2jMetadata.getEndpointPrefix()));

        if (metadata.getProjectName().contains(".")) {
            metadata.setProjectName(metadata.getProjectName().replace(".", ""));
        }

        return metadata;
    }

    static String ifNotNullOrEmpty(final String target, final String fallback) {
        if (target != null && !target.isEmpty()) {
            return target;
        } else {
            return fallback;
        }
    }

    void postProcessShapes() {
        for (Map.Entry<String, Shape> entry : shapes.entrySet()) {
            Shape shape = entry.getValue();

            /*
            If this shape ends up deriving from AmazonStreamingWebServiceRequest, then we already have implemented accessors for ContentType and the
            header insertion there.  So strip this out of the model (affects S3's PutObjectRequest).
            */
            if (shape.hasStreamMembers() && shape.isRequest()) {
                shape.RemoveMember("contentType");
                shape.RemoveMember("ContentType");
            }
        }
    }

    void convertShapes() {
        shapes = new LinkedHashMap<>(c2jServiceModel.getShapes().size());

        // First pass adds basic information
        for (Map.Entry<String, C2jShape> entry : c2jServiceModel.getShapes().entrySet()) {
            Shape shape = convertShapeBasics(entry.getValue(), entry.getKey());
            shapes.put(CppViewHelper.convertToUpperCamel(entry.getKey()), shape);
        }

        // Second Pass adds references to other shapes
        for (Map.Entry<String, C2jShape> entry : c2jServiceModel.getShapes().entrySet()) {
            Shape shape = shapes.get(CppViewHelper.convertToUpperCamel(entry.getKey()));
            convertShapeReferences(entry.getValue(), shape);
        }
    }

    Shape convertShapeBasics(C2jShape c2jShape, String shapeName) {

        Shape shape = new Shape();
        shape.setName(CppViewHelper.convertToUpperCamel(shapeName));

        shape.setDocumentation(formatDocumentation(c2jShape.getDocumentation(), 3));

        if (c2jShape.getEnums() != null) {
            shape.setEnumValues(new ArrayList<>(c2jShape.getEnums()));
        } else {
            shape.setEnumValues(Collections.emptyList());
        }

        shape.setMax(c2jShape.getMax());
        shape.setMin(c2jShape.getMin());
        shape.setType(c2jShape.getType());
        shape.setLocationName(c2jShape.getLocationName());
        shape.setPayload(c2jShape.getPayload());
        shape.setFlattened(c2jShape.isFlattened());

        return shape;
    }

    void convertShapeReferences(C2jShape c2jShape, Shape shape) {

        Map<String, ShapeMember> shapeMemberMap = new LinkedHashMap<>();

        Set<String> required;
        if (c2jShape.getRequired() != null) {
            required = new LinkedHashSet<>(c2jShape.getRequired());
        } else {
            required = Collections.emptySet();
        }

        if (c2jShape.getMembers() != null) {
            c2jShape.getMembers().entrySet().stream().filter(entry -> !entry.getValue().isDeprecated())
                    .forEach(entry -> {
                        ShapeMember shapeMember = convertMember(entry.getValue(),
                                required.contains(entry.getKey()));
                        shapeMemberMap.put(entry.getKey(), shapeMember);
                    });
        }

        shape.setMembers(shapeMemberMap);

        // Shape is a List
        if (c2jShape.getMember() != null && !c2jShape.getMember().isDeprecated()) {
            shape.setListMember(convertMember(c2jShape.getMember(), false));
        }

        if (c2jShape.getKey() != null && !c2jShape.getKey().isDeprecated()) {
            shape.setMapKey(convertMember(c2jShape.getKey(), false));
        }

        if (c2jShape.getValue() != null && !c2jShape.getValue().isDeprecated()) {
            shape.setMapValue(convertMember(c2jShape.getValue(), false));
        }
    }

    ShapeMember convertMember(C2jShapeMember c2jShapeMember, boolean required) {
        ShapeMember shapeMember = new ShapeMember();
        shapeMember.setRequired(required);
        shapeMember.setDocumentation(formatDocumentation(c2jShapeMember.getDocumentation(), 5));
        shapeMember.setFlattened(c2jShapeMember.isFlattened());
        Shape referencedShape = shapes.get(CppViewHelper.convertToUpperCamel(c2jShapeMember.getShape()));
        referencedShape.setReferenced(true);
        shapeMember.setShape(referencedShape);
        shapeMember.setLocationName(c2jShapeMember.getLocationName());
        shapeMember.setLocation(c2jShapeMember.getLocation());
        shapeMember.setStreaming(c2jShapeMember.isStreaming());
        if (shapeMember.isStreaming()) {
            shapeMember.setRequired(true);
        }

        if (shapeMember.isUsedForHeader()) {
            shapeMember.setLocationName(shapeMember.getLocationName().toLowerCase());
        }

        if (c2jShapeMember.getXmlNamespace() != null) {
            shapeMember.setXmlnsUri(c2jShapeMember.getXmlNamespace().getUri());
        }

        return shapeMember;
    }

    void convertOperations() {
        allErrors = new HashSet<>();
        operations = new LinkedHashMap<>(c2jServiceModel.getOperations().size());
        for (Map.Entry<String, C2jOperation> entry : c2jServiceModel.getOperations().entrySet()) {
            if (!entry.getValue().isDeprecated()) {
                operations.put(entry.getKey(), convertOperation(entry.getValue()));
            }
        }
    }

    Operation convertOperation(C2jOperation c2jOperation) {
        Operation operation = new Operation();

        // Documentation
        operation.setDocumentation(formatDocumentation(c2jOperation.getDocumentation(), 9));

        // input
        if (c2jOperation.getInput() != null) {
            String requestName = c2jOperation.getName() + "Request";
            Shape requestShape = renameShape(shapes.get(c2jOperation.getInput().getShape()), requestName);
            requestShape.setRequest(true);
            requestShape.setReferenced(true);
            ShapeMember requestMember = new ShapeMember();
            requestMember.setShape(requestShape);
            requestMember.setDocumentation(formatDocumentation(c2jOperation.getInput().getDocumentation(), 3));
            operation.setRequest(requestMember);
        }

        // output
        if (c2jOperation.getOutput() != null) {
            String resultName = c2jOperation.getName() + "Result";
            Shape resultShape = renameShape(shapes.get(c2jOperation.getOutput().getShape()), resultName);
            resultShape.setResult(true);
            resultShape.setReferenced(true);
            ShapeMember resultMember = new ShapeMember();
            resultMember.setShape(resultShape);
            resultMember.setDocumentation(formatDocumentation(c2jOperation.getOutput().getDocumentation(), 3));
            operation.setResult(resultMember);
        }
        // http
        operation.setHttp(convertHttp(c2jOperation.getHttp()));

        // name
        operation.setName(c2jOperation.getName());

        // errors

        List<Error> operationErrors = new ArrayList<>();
        if (c2jOperation.getErrors() != null) {
            operationErrors
                    .addAll(c2jOperation.getErrors().stream().map(this::convertError).collect(Collectors.toList()));
        }

        operation.setErrors(operationErrors);

        return operation;
    }

    Shape renameShape(Shape shape, String name) {
        if (shape.getName().equals(name)) {
            return shape;
        }
        if (shapes.containsKey(name)) {
            return shapes.get(name);
        }

        Shape cloned = cloneShape(shape);
        cloned.setName(name);
        shapes.put(name, cloned);
        return cloned;
    }

    Shape cloneShape(Shape shape) {
        Shape cloned = new Shape();
        cloned.setDocumentation(shape.getDocumentation());
        cloned.setEnumValues(shape.getEnumValues());
        cloned.setListMember(shape.getListMember());
        cloned.setMapKey(shape.getMapKey());
        cloned.setMapValue(shape.getMapValue());
        cloned.setMax(shape.getMax());
        cloned.setMin(shape.getMin());
        cloned.setMembers(shape.getMembers());
        cloned.setResult(shape.isResult());
        cloned.setRequest(shape.isRequest());
        cloned.setType(shape.getType());
        cloned.setPayload(shape.getPayload());
        cloned.setFlattened(shape.isFlattened());
        return cloned;
    }

    Http convertHttp(C2jHttp c2jHttp) {
        Http http = new Http();
        http.setMethod(c2jHttp.getMethod());
        http.setRequestUri(c2jHttp.getRequestUri());
        http.setResponseCode(c2jHttp.getResponseCode());
        return http;
    }

    Error convertError(C2jError c2jError) {
        if (c2jServiceModel.getShapes().get(c2jError.getShape()) != null) {
            C2jShape shape = c2jServiceModel.getShapes().get(c2jError.getShape());
            c2jError.setError(shape.getError());
            c2jError.setException(shape.isException());
        }

        Error error = new Error();
        error.setDocumentation(formatDocumentation(c2jError.getDocumentation(), 3));
        error.setName(c2jError.getShape());
        error.setText(c2jError.getShape());
        error.setException(c2jError.isException());
        error.setFault(c2jError.isFault());

        //query xml loads this inner structure to do this work.
        if (c2jError.getError() != null && c2jError.getError().getCode() != null) {
            if (c2jError.getError().getHttpStatusCode() >= 500 || !c2jError.getError().isSenderFault()) {
                error.setRetryable(true);
            }

            error.setText(c2jError.getError().getCode());
        }

        allErrors.add(error);
        return error;
    }

    Set<Error> filterOutCoreErrors(Set<Error> errors) {
        return errors.stream().filter(e -> !CoreErrors.VARIANTS.contains(e.getName())).collect(Collectors.toSet());
    }

    String sanitizeServiceAbbreviation(String serviceAbbreviation) {
        return serviceAbbreviation.replace(" ", "").replace("-", "").replace("_", "").replace("Amazon", "")
                .replace("AWS", "").replace("/", "");
    }
}