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