/* * 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.model.intermediate; import com.amazonaws.codegen.model.intermediate.customization.ShapeCustomizationInfo; import com.amazonaws.util.StringUtils; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import static com.amazonaws.codegen.internal.Constants.REQUEST_CLASS_SUFFIX; import static com.amazonaws.codegen.internal.Constants.RESPONSE_CLASS_SUFFIX; import static com.amazonaws.codegen.internal.DocumentationUtils.removeFromEnd; public class ShapeModel extends DocumentationModel { private final String c2jName; // shapeName might be later modified by the customization. private String shapeName; // the local variable name inside marshaller/unmarshaller implementation private boolean deprecated; private String type; private List<String> required; private boolean hasPayloadMember; private boolean hasHeaderMember; private boolean hasStatusCodeMember; private boolean hasStreamingMember; private boolean wrapper; // For APIG generated requests private String requestSignerClassFqcn; // For AWS service requests private String signerType; private List<MemberModel> members; // Any constructor in addition to the default no-arg private List<ConstructorModel> additionalConstructors; private List<EnumModel> enums; private VariableModel variable; private ShapeMarshaller marshaller; private ShapeUnmarshaller unmarshaller; private String errorCode; private ShapeCustomizationInfo customization = new ShapeCustomizationInfo(); public ShapeModel(@JsonProperty("c2jName") String c2jName) { this.c2jName = c2jName; } public String getShapeName() { return shapeName; } public void setShapeName(String shapeName) { this.shapeName = shapeName; } public boolean isDeprecated() { return deprecated; } public void setDeprecated(boolean deprecated) { this.deprecated = deprecated; } public String getC2jName() { return c2jName; } public String getType() { return type; } @JsonIgnore public ShapeType getShapeType() { return ShapeType.fromValue(type); } @JsonIgnore public void setType(ShapeType shapeType) { setType(shapeType.getValue()); } public void setType(String type) { this.type = type; } public ShapeModel withType(String type) { this.type = type; return this; } // Returns the list of C2j member names that are required for this shape. public List<String> getRequired() { return required; } public void setRequired(List<String> required) { this.required = required; } public boolean isHasPayloadMember() { return hasPayloadMember; } public void setHasPayloadMember(boolean hasPayloadMember) { this.hasPayloadMember = hasPayloadMember; } public ShapeModel withHasPayloadMember(boolean hasPayloadMember) { setHasPayloadMember(hasPayloadMember); return this; } /** * @return The member explicitly designated as the payload member */ @JsonIgnore public MemberModel getPayloadMember() { MemberModel payloadMember = null; for (MemberModel member : members) { if (member.getHttp().getIsPayload()) { if (payloadMember == null) { payloadMember = member; } else { throw new IllegalStateException( String.format( "Only one payload member can be explicitly set on %s. This is likely an error in the C2J model", c2jName)); } } } return payloadMember; } /** * @return The list of members whose location is not specified. If no payload member is * explicitly set then these members will appear in the payload */ @JsonIgnore public List<MemberModel> getUnboundMembers() { List<MemberModel> unboundMembers = new ArrayList<MemberModel>(); if (members != null) { for (MemberModel member : members) { if (member.getHttp().getLocation() == null) { if (hasPayloadMember) { throw new IllegalStateException(String.format( "C2J Shape %s has both an explicit payload member and unbound (no explicit location) members. " + "This is undefined behavior, verify the correctness of the C2J model", c2jName)); } unboundMembers.add(member); } } } return unboundMembers; } /** * @return True if the shape has an explicit payload member or implicit payload member(s). */ public boolean hasPayloadMembers() { return hasPayloadMember || getUnboundMembers().size() > 0; } public boolean isHasStreamingMember() { return hasStreamingMember; } public void setHasStreamingMember(boolean hasStreamingMember) { this.hasStreamingMember = hasStreamingMember; } public ShapeModel withHasStreamingMember(boolean hasStreamingMember) { setHasStreamingMember(hasStreamingMember); return this; } public boolean isHasHeaderMember() { return hasHeaderMember; } public void setHasHeaderMember(boolean hasHeaderMember) { this.hasHeaderMember = hasHeaderMember; } public ShapeModel withHasHeaderMember(boolean hasHeaderMember) { setHasHeaderMember(hasHeaderMember); return this; } public boolean isHasStatusCodeMember() { return hasStatusCodeMember; } public void setHasStatusCodeMember(boolean hasStatusCodeMember) { this.hasStatusCodeMember = hasStatusCodeMember; } public boolean isWrapper() { return wrapper; } public void setWrapper(boolean wrapper) { this.wrapper = wrapper; } public ShapeModel withHasStatusCodeMember(boolean hasStatusCodeMember) { setHasStatusCodeMember(hasStatusCodeMember); return this; } public MemberModel getMemberByVariableName(String memberVariableName) { for (MemberModel memberModel: members) { if (memberModel.getVariable().getVariableName().equals(memberVariableName)) return memberModel; } throw new IllegalArgumentException("Unknown member variable name: " + memberVariableName); } public MemberModel getMemberByName(String memberName) { for (MemberModel memberModel : members) { if (memberModel.getName().equals(memberName)) { return memberModel; } } return null; } public MemberModel getMemberByC2jName(String memberName) { for (MemberModel memberModel : members) { if (memberModel.getC2jName().equals(memberName)) { return memberModel; } } return null; } public List<MemberModel> getMembers() { return members; } public void setMembers(List<MemberModel> members) { this.members = members; } public void addMember(MemberModel member) { if (this.members == null) { this.members = new ArrayList<MemberModel>(); } members.add(member); } @JsonIgnore public List<ConstructorModel> getAdditionalConstructors() { return additionalConstructors; } public void setAdditionalConstructors(List<ConstructorModel> additionalConstructors) { this.additionalConstructors = additionalConstructors; } public void addConstructor(ConstructorModel constructor) { if (this.additionalConstructors == null) { this.additionalConstructors = new ArrayList<ConstructorModel>(); } this.additionalConstructors.add(constructor); } public List<EnumModel> getEnums() { return enums; } public void setEnums(List<EnumModel> enums) { this.enums = enums; } public void addEnum(EnumModel enumModel) { if (this.enums == null) { this.enums = new ArrayList<EnumModel>(); } this.enums.add(enumModel); } public VariableModel getVariable() { return variable; } public void setVariable(VariableModel variable) { this.variable = variable; } public ShapeMarshaller getMarshaller() { return marshaller; } public void setMarshaller(ShapeMarshaller marshaller) { this.marshaller = marshaller; } public ShapeUnmarshaller getUnmarshaller() { return unmarshaller; } public void setUnmarshaller(ShapeUnmarshaller unmarshaller) { this.unmarshaller = unmarshaller; } public ShapeCustomizationInfo getCustomization() { return customization; } public void setCustomization(ShapeCustomizationInfo customization) { this.customization = customization; } public Map<String, MemberModel> getMembersAsMap() { final Map<String, MemberModel> shapeMembers = new HashMap<String, MemberModel>(); // Creating a map of shape's members. This map is used below when // fetching the details of a memeber. final List<MemberModel> memberModels = getMembers(); if (memberModels != null) { for (MemberModel model : memberModels) { shapeMembers.put(model.getName(), model); } } return shapeMembers; } /** * Tries to find the member model associated with the given c2j member name from this shape * model. Returns the member model if present else returns null. */ private MemberModel tryFindMemberModelByC2jName(String memberC2jName, boolean ignoreCase) { final List<MemberModel> memberModels = getMembers(); final String expectedName = ignoreCase ? StringUtils.lowerCase(memberC2jName) : memberC2jName; if (memberModels != null) { for (MemberModel member : memberModels) { String actualName = ignoreCase ? StringUtils.lowerCase(member.getC2jName()) : member.getC2jName(); if (expectedName.equals(actualName)) { return member; } } } return null; } /** * Returns the member model associated with the given c2j member name from this shape model. */ public MemberModel findMemberModelByC2jName(String memberC2jName) { MemberModel model = tryFindMemberModelByC2jName(memberC2jName, false); if (model == null) { throw new IllegalArgumentException(memberC2jName + " member (c2j name) does not exist in the shape."); } return model; } /** * Takes in the c2j member name as input and removes if the shape contains a member with the * given name. Return false otherwise. */ public boolean removeMemberByC2jName(String memberC2jName, boolean ignoreCase) { // Implicitly depending on the default equals and hashcode // implementation of the class MemberModel MemberModel model = tryFindMemberModelByC2jName(memberC2jName, ignoreCase); return model == null ? false : members.remove(model); } /** * Returns the enum model for the given enum value. * Returns null if no such enum value exists. */ public EnumModel findEnumModelByValue(String enumValue) { if (enums != null) { for (EnumModel enumModel : enums) { if (enumValue.equals(enumModel.getValue())) { return enumModel; } } } return null; } @JsonIgnore public String getDocumentationShapeName() { switch (getShapeType()) { case Request: return removeFromEnd(shapeName, REQUEST_CLASS_SUFFIX); case Response: return removeFromEnd(shapeName, RESPONSE_CLASS_SUFFIX); default: return c2jName; } } @Override public String toString() { return shapeName; } public String getErrorCode() { return errorCode; } public void setErrorCode(String errorCode) { this.errorCode = errorCode; } public boolean isRequestSignerAware() { return requestSignerClassFqcn != null; } public String getRequestSignerClassFqcn() { return requestSignerClassFqcn; } public boolean isSignerAware() { return getSignerType() != null; } public String getSignerType() { return signerType; } public void setSignerType(String signerType) { this.signerType = signerType; } public void setRequestSignerClassFqcn(String authorizerClass) { this.requestSignerClassFqcn = authorizerClass; } }