/* * Copyright (c) 2016. 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.codegen.customization.processors; import com.amazonaws.codegen.customization.CodegenCustomizationProcessor; import com.amazonaws.codegen.internal.Constants; import com.amazonaws.codegen.model.config.customization.OperationModifier; import com.amazonaws.codegen.model.intermediate.IntermediateModel; import com.amazonaws.codegen.model.intermediate.MemberModel; import com.amazonaws.codegen.model.intermediate.ShapeModel; import com.amazonaws.codegen.model.intermediate.customization.ArtificialResultWrapper; import com.amazonaws.codegen.model.service.Member; import com.amazonaws.codegen.model.service.Operation; import com.amazonaws.codegen.model.service.ServiceModel; import com.amazonaws.codegen.model.service.Shape; import com.amazonaws.codegen.model.service.ShapeTypes; import java.util.Collections; import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; import java.util.Set; /** * This processor internally keeps track of all the result wrapper shapes it * created during pre-processing, therefore the caller needs to make sure this * processor is only invoked once. */ final class OperationModifiersProcessor implements CodegenCustomizationProcessor { private final Map<String, OperationModifier> operationModifiers; private final Set<String> createdWrapperShapes = new HashSet<String>(); OperationModifiersProcessor(Map<String, OperationModifier> operationModifiers) { this.operationModifiers = operationModifiers; } @Override public void preprocess(ServiceModel serviceModel) { if (operationModifiers == null) return; for (Entry<String, OperationModifier> entry : operationModifiers.entrySet()) { String operationName = entry.getKey(); OperationModifier modifier = entry.getValue(); if (modifier.isExclude()) { preprocess_Exclude(serviceModel, operationName); continue; } if (modifier.isUseWrappingResult()) { String createdWrapperShape = preprocess_CreateResultWrapperShape( serviceModel, operationName, modifier); // Keep track of all the wrappers we created createdWrapperShapes.add(createdWrapperShape); continue; } } } @Override public void postprocess(IntermediateModel intermediateModel) { if (operationModifiers == null) return; // Find all the wrapper shapes in the intermediate model (by its // "original" c2j name), and add the customization metadata for (ShapeModel shape : intermediateModel.getShapes().values()) { if ( !createdWrapperShapes.contains(shape.getC2jName()) ) { continue; } if (shape.getMembers().size() != 1) { throw new IllegalStateException("Result wrapper " + shape.getShapeName() + " has not just one member!"); } MemberModel wrappedMember = shape.getMembers().get(0); /* * "RunInstancesResult" : { * "customization" : { * "artificialResultWrapper" : { * "wrappedMemberName" : "Reservation", * "wrappedMemberSimpleType" : "Reservation" * } * } * } */ shape.getCustomization().setArtificialResultWrapper( createArtificialResultWrapperInfo( shape, wrappedMember)); } } private void preprocess_Exclude(ServiceModel serviceModel, String operationName) { serviceModel.getOperations().remove(operationName); } private String preprocess_CreateResultWrapperShape(ServiceModel serviceModel, String operationName, OperationModifier modifier) { String wrappedShapeName = modifier.getWrappedResultShape(); Shape wrappedShape = serviceModel.getShapes().get(wrappedShapeName); String wrapperShapeName = operationName + Constants.RESPONSE_CLASS_SUFFIX; String wrappedAsMember = modifier.getWrappedResultMember(); if (serviceModel.getShapes().containsKey(wrapperShapeName)) { throw new IllegalStateException(wrapperShapeName + " shape already exists in the service model."); } Shape wrapperShape = createWrapperShape(wrapperShapeName, wrappedShapeName, wrappedShape, wrappedAsMember); // Add the new shape to the model serviceModel.getShapes().put(wrapperShapeName, wrapperShape); // Update the operation model to point to this new shape Operation operation = serviceModel.getOperations().get(operationName); operation.getOutput().setShape(wrapperShapeName); return wrapperShapeName; } private Shape createWrapperShape(String wrapperShapeName, String wrappedShapeName, Shape wrapped, String wrappedAsMember) { Shape wrapper = new Shape(); wrapper.setType(ShapeTypes.Structure.getName()); wrapper.setDocumentation("A simple result wrapper around the " + wrappedShapeName + " object that was sent over the wire."); Member member = new Member(); member.setShape(wrappedShapeName); member.setDocumentation(wrapped.getDocumentation()); wrapper.setMembers(Collections.singletonMap(wrappedAsMember, member)); return wrapper; } private ArtificialResultWrapper createArtificialResultWrapperInfo(ShapeModel shape, MemberModel wrappedMember) { ArtificialResultWrapper wrapper = new ArtificialResultWrapper(); wrapper.setWrappedMemberName(wrappedMember.getName()); wrapper.setWrappedMemberSimpleType(wrappedMember.getVariable().getSimpleType()); return wrapper; } }