Generate stringValue() in union types
[mdsal.git] / binding / mdsal-binding-java-api-generator / src / main / java / org / opendaylight / mdsal / binding / java / api / generator / UnionTemplate.xtend
1 /*
2  * Copyright (c) 2014 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.java.api.generator
9
10 import static org.opendaylight.mdsal.binding.model.util.Types.BOOLEAN;
11 import static org.opendaylight.mdsal.binding.model.util.Types.getOuterClassName;
12
13 import com.google.common.base.Preconditions;
14 import com.google.common.io.BaseEncoding
15 import java.beans.ConstructorProperties
16 import java.util.Arrays
17 import org.opendaylight.mdsal.binding.model.api.GeneratedProperty
18 import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject
19 import org.opendaylight.mdsal.binding.model.api.Enumeration
20 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition
21
22 /**
23  * Template for generating JAVA class.
24  */
25 class UnionTemplate extends ClassTemplate {
26
27     /**
28      * Creates instance of this class with concrete <code>genType</code>.
29      *
30      * @param genType generated transfer object which will be transformed to JAVA class source code
31      */
32     new(NestedJavaGeneratedType javaType, GeneratedTransferObject genType) {
33         super(javaType, genType)
34     }
35
36     /**
37      * Creates instance of this class with concrete <code>genType</code>.
38      *
39      * @param genType generated transfer object which will be transformed to JAVA class source code
40      */
41     new(GeneratedTransferObject genType) {
42         super(genType)
43     }
44
45     override constructors() '''
46         «unionConstructorsParentProperties»
47         «unionConstructors»
48         «IF !allProperties.empty»
49             «copyConstructor»
50         «ENDIF»
51         «IF properties.empty && !parentProperties.empty»
52             «parentConstructor»
53         «ENDIF»
54
55         «generateStringValue»
56     '''
57
58     private def unionConstructors() '''
59         «FOR property : finalProperties SEPARATOR "\n"»
60             «val propRet = property.returnType»
61             «IF "char[]".equals(propRet.name)»
62                 /**
63                  * Constructor provided only for using in JMX. Don't use it for
64                  * construction new object of this union type.
65                  */
66                 @«ConstructorProperties.importedName»("«property.name»")
67                 public «type.name»(«propRet.importedName» «property.fieldName») {
68                     «String.importedName» defVal = new «String.importedName»(«property.fieldName»);
69                     «type.name» defInst = «typeBuilder()».getDefaultInstance(defVal);
70                     «FOR other : finalProperties»
71                         «IF other.name.equals("value")»
72                             «IF other.returnType.importedName.contains("[]")»
73                             this.«other.fieldName» = «other.fieldName» == null ? null : «other.fieldName».clone();
74                             «ELSE»
75                             this.«other.fieldName» = «other.fieldName»;
76                             «ENDIF»
77                         «ELSE»
78                             this.«other.fieldName» = defInst.«other.fieldName»;
79                         «ENDIF»
80                     «ENDFOR»
81                 }
82             «ELSE»
83                 «val actualType = property.returnType»
84                 «val restrictions = restrictionsForSetter(actualType)»
85                 «IF restrictions !== null»
86                     «generateCheckers(property, restrictions, actualType)»
87
88                 «ENDIF»
89                 «val propertyAndTopParentProperties = parentProperties + #[property]»
90                 public «type.name»(«propertyAndTopParentProperties.asArgumentsDeclaration») {
91                     super(«parentProperties.asArguments»);
92                     «IF restrictions !== null»
93                         «checkArgument(property, restrictions, actualType, property.fieldName.toString)»
94                     «ENDIF»
95                     this.«property.fieldName» = «property.fieldName»;
96                     «FOR other : finalProperties»
97                         «IF property != other && !"value".equals(other.name)»
98                              this.«other.fieldName» = null;
99                         «ENDIF»
100                     «ENDFOR»
101                 }
102             «ENDIF»
103         «ENDFOR»
104     '''
105
106     def typeBuilder() {
107         val outerCls = getOuterClassName(type);
108         if(outerCls !== null) {
109             return outerCls + type.name + "Builder"
110         }
111         return type.name + "Builder"
112     }
113
114     private def unionConstructorsParentProperties() '''
115         «FOR property : parentProperties SEPARATOR "\n"»
116             public «type.name»(«property.returnType.importedName» «property.fieldName») {
117                 super(«property.fieldName»);
118             }
119         «ENDFOR»
120     '''
121
122     def generateStringValue()
123     '''
124         public «String.importedName» stringValue() {
125             «FOR property : finalProperties.filter([ p | !"value".equals(p.name)])»
126                 «val field = property.fieldName»
127             if («field» != null) {
128                 «val propRet = property.returnType»
129                 «IF "java.lang.String".equals(propRet.fullyQualifiedName)»
130                     ««« type string
131                 return «field»;
132                 «ELSEIF "org.opendaylight.yangtools.yang.binding.InstanceIdentifier".equals(propRet.fullyQualifiedName)»
133                     ««« type instance-identifier
134                 return «field».toString();
135                 «ELSEIF "byte[]".equals(propRet.name)»
136                     ««« type binary
137                 return new «String.importedName»(«field»);
138                 «ELSEIF propRet.fullyQualifiedName.startsWith("java.lang") || propRet instanceof Enumeration
139                         || propRet.fullyQualifiedName.startsWith("java.math")»
140                    ««« type int*, uint, decimal64 or enumeration*
141                 return «field».toString();
142                 «ELSEIF propRet instanceof GeneratedTransferObject
143                         && (propRet as GeneratedTransferObject).unionType»
144                     ««« union type
145                 return «field».stringValue();
146                 «ELSEIF propRet instanceof GeneratedTransferObject // Is it a GeneratedTransferObject
147                         && (propRet as GeneratedTransferObject).typedef  // Is it a typedef
148                         && (propRet as GeneratedTransferObject).properties !== null
149                         && !(propRet as GeneratedTransferObject).properties.empty
150                         && ((propRet as GeneratedTransferObject).properties.size == 1)
151                         && (propRet as GeneratedTransferObject).properties.get(0).name.equals("value")
152                         && BOOLEAN.equals((propRet as GeneratedTransferObject).properties.get(0).returnType) // And the property value is of type boolean»
153                     ««« generated boolean typedef
154                 return «field».isValue().toString();
155                 «ELSEIF propRet instanceof GeneratedTransferObject // Is it a GeneratedTransferObject
156                         && (propRet as GeneratedTransferObject).typedef  // Is it a typedef
157                         && (propRet as GeneratedTransferObject).properties !== null
158                         && !(propRet as GeneratedTransferObject).properties.empty
159                         && ((propRet as GeneratedTransferObject).properties.size == 1)
160                         && (propRet as GeneratedTransferObject).properties.get(0).name.equals("value")
161                         && "byte[]".equals((propRet as GeneratedTransferObject).properties.get(0).returnType.name)»
162                     ««« generated byte[] typedef
163                 return «BaseEncoding.importedName».base64().encode(«field».getValue());
164                 «ELSEIF propRet instanceof GeneratedTransferObject // Is it a GeneratedTransferObject
165                         && (propRet as GeneratedTransferObject).typedef  // Is it a typedef
166                         && (propRet as GeneratedTransferObject).baseType instanceof BitsTypeDefinition»
167                     ««« generated bits typedef
168                 return «Arrays.importedName».toString(«field».getValue());
169                 «ELSE»
170                     ««« generated type
171                 return «field».getValue().toString();
172                 «ENDIF»
173             }
174             «ENDFOR»
175
176             throw new IllegalStateException("No value assinged");
177         }
178     '''
179
180     override protected getterMethod(GeneratedProperty field) {
181         if (!"value".equals(field.name)) {
182             return super.getterMethod(field)
183         }
184
185         Preconditions.checkArgument("char[]".equals(field.returnType.importedName))
186
187         '''
188             @«Deprecated.importedName»
189             public char[] «field.getterMethodName»() {
190                 if («field.fieldName» == null) {
191                     «field.fieldName» = stringValue().toCharArray();
192                 }
193                 return «field.fieldName».clone();
194             }
195         '''
196     }
197
198     override isReadOnly(GeneratedProperty field) {
199         return !"value".equals(field.name) && super.isReadOnly(field)
200     }
201
202     override protected copyConstructor() '''
203         /**
204          * Creates a copy from Source Object.
205          *
206          * @param source Source object
207          */
208         public «type.name»(«type.name» source) {
209             «IF !parentProperties.empty»
210                 super(source);
211             «ENDIF»
212             «IF !properties.empty»
213                 «FOR p : properties»
214                     «IF !"value".equals(p.name) && p.returnType.importedName.contains("[]")»
215                     this.«p.fieldName» = source.«p.fieldName» == null ? null : source.«p.fieldName».clone();
216                     «ELSE»
217                     this.«p.fieldName» = source.«p.fieldName»;
218                     «ENDIF»
219                 «ENDFOR»
220             «ENDIF»
221         }
222     '''
223
224 }