1 /*
2  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License").
5  * You may not use this file except in compliance with the License.
6  * A copy of the License is located at
7  *
8  *  http://aws.amazon.com/apache2.0
9  *
10  * or in the "license" file accompanying this file. This file is distributed
11  * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12  * express or implied. See the License for the specific language governing
13  * permissions and limitations under the License.
14  */
15 
16 package software.amazon.awssdk.codegen.poet.model;
17 
18 import com.squareup.javapoet.ClassName;
19 import java.util.Collection;
20 import java.util.HashMap;
21 import java.util.Locale;
22 import java.util.Map;
23 import java.util.Optional;
24 import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
25 import software.amazon.awssdk.codegen.model.intermediate.MemberModel;
26 import software.amazon.awssdk.codegen.poet.ClassSpec;
27 import software.amazon.awssdk.codegen.poet.PoetExtension;
28 
29 public class ServiceModelCopiers {
30     private final IntermediateModel intermediateModel;
31     private final PoetExtension poetExtensions;
32     private final TypeProvider typeProvider;
33 
ServiceModelCopiers(IntermediateModel intermediateModel)34     public ServiceModelCopiers(IntermediateModel intermediateModel) {
35         this.intermediateModel = intermediateModel;
36         this.poetExtensions = new PoetExtension(intermediateModel);
37         this.typeProvider = new TypeProvider(intermediateModel);
38     }
39 
copierSpecs()40     public Collection<ClassSpec> copierSpecs() {
41         Map<ClassName, ClassSpec> memberSpecs = new HashMap<>();
42         allShapeMembers().values().stream()
43                 .filter(m -> !canCopyReference(m))
44                 .map(m -> new MemberCopierSpec(m, this, typeProvider, poetExtensions))
45                 .forEach(spec -> memberSpecs.put(spec.className(), spec));
46 
47         return memberSpecs.values();
48     }
49 
copierClassFor(MemberModel memberModel)50     public Optional<ClassName> copierClassFor(MemberModel memberModel) {
51         if (canCopyReference(memberModel)) {
52             return Optional.empty();
53         }
54 
55         // FIXME: Some services (Health) have shapes with names
56         // that differ only in the casing of the first letter, and generating
57         // classes for them breaks on case insensitive filesystems...
58         String shapeName = memberModel.getC2jShape();
59         if (shapeName.substring(0, 1).toLowerCase(Locale.ENGLISH).equals(shapeName.substring(0, 1))) {
60             shapeName = "_" + shapeName;
61         }
62 
63         return Optional.of(poetExtensions.getModelClass(shapeName + "Copier"));
64     }
65 
copyMethodName()66     public String copyMethodName() {
67         return "copy";
68     }
69 
enumToStringCopyMethodName()70     public String enumToStringCopyMethodName() {
71         return "copyEnumToString";
72     }
73 
stringToEnumCopyMethodName()74     public String stringToEnumCopyMethodName() {
75         return "copyStringToEnum";
76     }
77 
copyFromBuilderMethodName()78     public String copyFromBuilderMethodName() {
79         return "copyFromBuilder";
80     }
81 
copyToBuilderMethodName()82     public String copyToBuilderMethodName() {
83         return "copyToBuilder";
84     }
85 
allShapeMembers()86     private Map<String, MemberModel> allShapeMembers() {
87         Map<String, MemberModel> shapeMembers = new HashMap<>();
88         intermediateModel.getShapes().values().stream()
89                 .flatMap(s -> s.getMembersAsMap().values().stream())
90                 .forEach(m -> shapeMembers.put(m.getC2jShape(), m));
91         return shapeMembers;
92     }
93 
canCopyReference(MemberModel m)94     private boolean canCopyReference(MemberModel m) {
95         return !m.isList() && !m.isMap();
96     }
97 }
98