7f4420e9a60138ebdacf1fe3eab6346164e3fe4f
[mdsal.git] / binding2 / mdsal-binding2-java-api-generator / src / main / java / org / opendaylight / mdsal / binding / javav2 / java / api / generator / renderers / UnionRenderer.java
1 /*
2  * Copyright (c) 2017 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.mdsal.binding.javav2.java.api.generator.renderers;
9
10 import static org.opendaylight.mdsal.binding.javav2.generator.util.Types.BOOLEAN;
11
12 import com.google.common.base.Preconditions;
13 import com.google.common.collect.Collections2;
14 import java.beans.ConstructorProperties;
15 import java.util.ArrayList;
16 import java.util.HashMap;
17 import java.util.List;
18 import java.util.Map;
19 import org.opendaylight.mdsal.binding.javav2.java.api.generator.txt.unionTemplate;
20 import org.opendaylight.mdsal.binding.javav2.java.api.generator.util.TextTemplateUtil;
21 import org.opendaylight.mdsal.binding.javav2.model.api.Enumeration;
22 import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedProperty;
23 import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedTransferObject;
24 import org.opendaylight.mdsal.binding.javav2.model.api.Type;
25 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
26
27 public class UnionRenderer extends ClassRenderer {
28     public UnionRenderer(final GeneratedTransferObject type) {
29         super(type);
30     }
31
32     @Override
33     protected String generateConstructors() {
34         // list of all imported names for template
35         final Map<String, String> importedNames = new HashMap<>();
36
37         if(isBaseEncodingImportRequired()) {
38             this.putToImportMap("BaseEncoding","com.google.common.io");
39         }
40         for (GeneratedProperty finalProperty : getFinalProperties()) {
41             importedNames.put("constructorProperties", importedName(ConstructorProperties.class));
42             importedNames.put("string", importedName(String.class));
43             importedNames.put(finalProperty.getName(), importedName(finalProperty.getReturnType()));
44         }
45
46         for (GeneratedProperty property : getProperties()) {
47             if("char[]".equals(property.getReturnType().getName())) {
48                 importedNames.put("constructorProperties", importedName(ConstructorProperties.class));
49                 importedNames.put("string", importedName(String.class));
50                 importedNames.put(property.getName(), importedName(property.getReturnType()));
51             }
52         }
53
54         final StringBuilder sb = new StringBuilder();
55         if (!getProperties().isEmpty()) {
56             for (GeneratedProperty property : getProperties()) {
57                 sb.append(generateField(property));
58             }
59         }
60
61         if (getProperties().isEmpty() && !getParentProperties().isEmpty()) {
62             importedNames.put("superType", importedName(genTO.getSuperType()));
63         }
64
65         for (GeneratedProperty parentProperty : getParentProperties()) {
66             importedNames.put(parentProperty.getName(), importedName(parentProperty.getReturnType()));
67         }
68
69         return unionTemplate.render(getType(), importedNames, getFinalProperties(), getParentProperties(),
70                 getProperties(), sb.toString()).body();
71     }
72
73     private boolean isBaseEncodingImportRequired() {
74         for (GeneratedProperty property : getFinalProperties()) {
75             final Type returnType = property.getReturnType();
76             if (returnType instanceof GeneratedTransferObject) {
77                 final GeneratedTransferObject returnTypeGto = (GeneratedTransferObject)returnType;
78                 if (returnTypeGto.isTypedef() && returnTypeGto.getProperties() != null &&
79                         !returnTypeGto.getProperties().isEmpty() && returnTypeGto.getProperties().size() == 1 &&
80                         "value".equals(returnTypeGto.getProperties().get(0).getName()) &&
81                         "byte[]".equals(returnTypeGto.getProperties().get(0).getReturnType().getName())) {
82                     return true;
83                 }
84             }
85         }
86         return false;
87     }
88
89     private String generateField(final GeneratedProperty generatedProperty) {
90         final StringBuilder sb = new StringBuilder();
91         final String name = TextTemplateUtil.fieldName(generatedProperty);
92         sb.append("this.")
93             .append(name)
94             .append(" = source.")
95             .append(name);
96         if (!"value".equals(name) && importedName(generatedProperty.getReturnType()).contains("[]")) {
97             sb.append(" == null ? null : source.")
98                 .append(name)
99                 .append(".clone()");
100         }
101         sb.append(";\n");
102         return sb.toString();
103     }
104
105     private String generateCharArrayFieldForTypedef(final String fieldName, GeneratedTransferObject typedefType) {
106         Preconditions.checkState(typedefType.isTypedef(),"Not a typedef type!");
107
108         final StringBuilder sb = new StringBuilder();
109         final List<GeneratedProperty> retTypeCastProperties = typedefType.getProperties();
110
111         if (retTypeCastProperties != null &&
112                 !retTypeCastProperties.isEmpty() && retTypeCastProperties.size() == 1 &&
113                 retTypeCastProperties.get(0).getName().equals("value")) {
114
115             final StringBuilder sb1 = new StringBuilder(fieldName);
116             sb1.append(".")
117                     .append(TextTemplateUtil.getterMethodName(retTypeCastProperties.get(0)))
118                     .append("()");
119
120             sb.append(generateCharArrayField(sb1.toString(), retTypeCastProperties.get(0)));
121             // generated bits typedef
122         } else if (retTypeCastProperties != null && !retTypeCastProperties.isEmpty() &&
123                 typedefType.getBaseType() instanceof BitsTypeDefinition) {
124             sb.append("java.util.Arrays.toString(")
125                     .append(fieldName)
126                     .append(".getValue()).toCharArray();");
127
128             //generated typedef typedef
129         } else if ((retTypeCastProperties == null || retTypeCastProperties.isEmpty())) {
130             Preconditions.checkState(typedefType.getSuperType() != null );
131
132             sb.append(generateCharArrayFieldForTypedef(fieldName,
133                     (GeneratedTransferObject) typedefType.getSuperType()));
134         }
135
136         return sb.toString();
137     }
138
139     private String generateCharArrayField(final String fieldName, final GeneratedProperty generatedProperty) {
140         final StringBuilder sb = new StringBuilder();
141         final Type propertyReturnType = generatedProperty.getReturnType();
142
143         // generated type String
144         if ("java.lang.String".equals(propertyReturnType.getFullyQualifiedName())) {
145             sb.append(fieldName).append(".toCharArray();");
146             // generated type InstanceIdentifier
147         } else if ("org.opendaylight.mdsal.binding.javav2.spec.base.InstanceIdentifier".equals(propertyReturnType
148                 .getFullyQualifiedName())) {
149                     sb.append(fieldName)
150                     .append(".toString().toCharArray();");
151             //generated type binary, boolean, empty
152         } else if (BOOLEAN.equals(propertyReturnType)) {
153             sb.append(fieldName).append(".toString().toCharArray();");
154             //generated type byte[]
155         } else if ("byte[]".equals(propertyReturnType.getName())) {
156             sb.append("BaseEncoding.base64().encode(").append(fieldName)
157                     .append(").toCharArray();");
158             //generated type int*, uint, decimal64 or enumeration*
159         } else if (propertyReturnType.getFullyQualifiedName().startsWith("java.lang") ||
160                 propertyReturnType instanceof Enumeration ||
161                 propertyReturnType.getFullyQualifiedName().startsWith("java.math") ||
162                 propertyReturnType.getFullyQualifiedName().startsWith("org.opendaylight.yangtools.yang.common")) {
163             sb.append(fieldName).append(".toString().toCharArray();");
164
165         } else if (propertyReturnType instanceof GeneratedTransferObject) {
166             final GeneratedTransferObject propRetTypeCast = (GeneratedTransferObject) propertyReturnType;
167
168             // generated union type
169             if (propRetTypeCast.isUnionType()) {
170                 sb.append(fieldName).append(".getValue();");
171
172                 // generated  typedef type
173             } else if (propRetTypeCast.isTypedef()) {
174                 sb.append(generateCharArrayFieldForTypedef(fieldName, propRetTypeCast));
175             }
176             // generated type
177         } else {
178             sb.append(fieldName)
179                     .append(".getValue().toString().toCharArray();");
180         }
181
182         return sb.toString();
183     }
184
185     @Override
186     protected String getterMethod(final GeneratedProperty field) {
187         if (!"value".equals(field.getName())) {
188             return super.getterMethod(field);
189         }
190
191         final StringBuilder sb1 = new StringBuilder();
192         final String name = TextTemplateUtil.fieldName(field);
193         final String importedName = Preconditions.checkNotNull(importedName(field.getReturnType()));
194         sb1.append("public ")
195                 .append(importedName)
196                 .append(' ')
197                 .append(TextTemplateUtil.getterMethodName(field))
198                 .append("() {\n");
199
200         final List<GeneratedProperty> filtered = new ArrayList<>(Collections2.filter(this.getFinalProperties(),
201             input -> !"value".equals(input.getName())));
202
203         final List<CharSequence> strings = new ArrayList<>(filtered.size());
204
205         for (GeneratedProperty property : filtered) {
206             final Type propertyReturnType = property.getReturnType();
207             //string builder for current property
208             final StringBuilder sb = new StringBuilder();
209             sb.append("if (")
210                 .append(TextTemplateUtil.fieldName(property))
211                 .append(" != null) {")
212                 .append(TextTemplateUtil.fieldName(field))
213                 .append(" = ")
214                 .append(generateCharArrayField(TextTemplateUtil.fieldName(property), property))
215                 .append("}\n");
216             strings.add(sb);
217         }
218
219         sb1.append(String.join(" else ", strings))
220                 .append("\n");
221
222         sb1.append("return ")
223                 .append(name);
224         if (importedName.contains("[]")) {
225             sb1.append(" == null ? null : ")
226                     .append(name)
227                     .append(".clone()");
228         }
229         sb1.append(";\n}\n");
230
231         return sb1.toString();
232     }
233
234     @Override
235     protected String generateInnerClassBody(GeneratedTransferObject innerClass) {
236         final UnionRenderer unionRenderer = new UnionRenderer((GeneratedTransferObject) innerClass);
237         final String body = unionRenderer.generateAsInnerClass();
238         this.putAllToImportMap(unionRenderer.getImportMap());
239         return body;
240     }
241 }