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