1 package org.opendaylight.yangtools.sal.java.api.generator
3 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty
4 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType
6 import org.opendaylight.yangtools.sal.binding.model.api.Type
7 import org.opendaylight.yangtools.binding.generator.util.Types
8 import com.google.common.base.Splitter
9 import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature
10 import com.google.common.collect.Range
11 import java.util.ArrayList
13 import org.opendaylight.yangtools.sal.binding.model.api.ConcreteType
14 import org.opendaylight.yangtools.sal.binding.model.api.Restrictions
15 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject
16 import java.util.Collection
17 import java.util.Arrays
19 abstract class BaseTemplate {
21 protected val GeneratedType type;
22 protected val Map<String, String> importMap;
23 static val paragraphSplitter = Splitter.on("\n\n").omitEmptyStrings();
25 new(GeneratedType _type) {
27 throw new IllegalArgumentException("Generated type reference cannot be NULL!")
30 this.importMap = GeneratorUtil.createImports(type)
33 def packageDefinition() '''package «type.packageName»;'''
35 protected def getFullyQualifiedName() {
36 return type.fullyQualifiedName
39 final public def generate() {
49 protected def imports() '''
51 «FOR entry : importMap.entrySet»
52 «IF entry.value != fullyQualifiedName»
53 import «entry.value».«entry.key»;
60 protected abstract def CharSequence body();
63 final protected def fieldName(GeneratedProperty property) '''_«property.name»'''
65 final protected def propertyNameFromGetter(MethodSignature getter) {
67 if (getter.name.startsWith("is")) {
69 } else if (getter.name.startsWith("get")) {
72 throw new IllegalArgumentException("Not a getter")
74 return getter.name.substring(prefix).toFirstLower;
78 * Template method which generates the getter method for <code>field</code>
81 * generated property with data about field which is generated as the getter method
82 * @return string with the getter method source code in JAVA format
84 final protected def getterMethod(GeneratedProperty field) {
86 public «field.returnType.importedName» «field.getterMethodName»() {
87 return «field.fieldName»;
92 final protected def getterMethodName(GeneratedProperty field) {
93 val prefix = if(field.returnType.equals(Types.BOOLEAN)) "is" else "get"
94 return '''«prefix»«field.name.toFirstUpper»'''
98 * Template method which generates the setter method for <code>field</code>
101 * generated property with data about field which is generated as the setter method
102 * @return string with the setter method source code in JAVA format
104 final protected def setterMethod(GeneratedProperty field) '''
105 «val returnType = field.returnType.importedName»
106 public «type.name» set«field.name.toFirstUpper»(«returnType» value) {
107 this.«field.fieldName» = value;
112 final protected def importedName(Type intype) {
113 GeneratorUtil.putTypeIntoImports(type, intype, importMap);
114 GeneratorUtil.getExplicitType(type, intype, importMap)
117 final protected def importedName(Class<?> cls) {
118 importedName(Types.typeForClass(cls))
122 * Template method which generates method parameters with their types from <code>parameters</code>.
125 * group of generated property instances which are transformed to the method parameters
126 * @return string with the list of the method parameters with their types in JAVA format
128 def final protected asArgumentsDeclaration(Iterable<GeneratedProperty> parameters) '''«IF !parameters.empty»«FOR parameter : parameters SEPARATOR ", "»«parameter.
129 returnType.importedName» «parameter.fieldName»«ENDFOR»«ENDIF»'''
132 * Template method which generates sequence of the names of the class attributes from <code>parameters</code>.
135 * group of generated property instances which are transformed to the sequence of parameter names
136 * @return string with the list of the parameter names of the <code>parameters</code>
138 def final protected asArguments(Iterable<GeneratedProperty> parameters) '''«IF !parameters.empty»«FOR parameter : parameters SEPARATOR ", "»«parameter.
139 fieldName»«ENDFOR»«ENDIF»'''
142 * Template method which generates JAVA comments.
144 * @param comment string with the comment for whole JAVA class
145 * @return string with comment in JAVA format
147 def protected CharSequence asJavadoc(String comment) {
148 if(comment == null) return '';
150 if (txt.contains("*/")) {
151 txt = txt.replace("*/", "*/")
153 val paragraphs = paragraphSplitter.split(txt)
157 «FOR p : paragraphs SEPARATOR "<p>"»
164 def generateRestrictions(Type type, String paramName, Type returnType) '''
165 «val boolean isArray = returnType.name.contains("[")»
166 «processRestrictions(type, paramName, returnType, isArray)»
169 def generateRestrictions(GeneratedProperty field, String paramName) '''
170 «val Type type = field.returnType»
171 «IF type instanceof ConcreteType»
172 «processRestrictions(type, paramName, field.returnType, type.name.contains("["))»
173 «ELSEIF type instanceof GeneratedTransferObject»
174 «processRestrictions(type, paramName, field.returnType, isArrayType(type as GeneratedTransferObject))»
179 private def processRestrictions(Type type, String paramName, Type returnType, boolean isArray) '''
180 «val restrictions = type.getRestrictions»
181 «IF restrictions !== null»
182 «IF !restrictions.lengthConstraints.empty»
183 «generateLengthRestriction(type, restrictions, paramName, isArray,
184 !(returnType instanceof ConcreteType))»
186 «IF !restrictions.rangeConstraints.empty &&
187 ("java.lang".equals(returnType.packageName) || "java.math".equals(returnType.packageName))»
188 «generateRangeRestriction(type, returnType, restrictions, paramName,
189 !(returnType instanceof ConcreteType))»
194 def generateLengthRestriction(Type type, Restrictions restrictions, String paramName, boolean isArray,
195 boolean isNestedType) '''
196 if («paramName» != null) {
197 boolean isValidLength = false;
198 «List.importedName»<«Range.importedName»<«Integer.importedName»>> lengthConstraints = new «ArrayList.
200 «FOR r : restrictions.lengthConstraints»
201 lengthConstraints.add(«Range.importedName».closed(«r.min», «r.max»));
203 for («Range.importedName»<«Integer.importedName»> r : lengthConstraints) {
206 if (r.contains(«paramName».getValue().length)) {
208 if (r.contains(«paramName».length)) {
212 if (r.contains(«paramName».getValue().length())) {
214 if (r.contains(«paramName».length())) {
217 isValidLength = true;
220 if (!isValidLength) {
221 throw new IllegalArgumentException(String.format("Invalid length: {}, expected: {}.", «paramName», lengthConstraints));
226 def generateRangeRestriction(Type type, Type returnType, Restrictions restrictions, String paramName,
227 boolean isNestedType) '''
228 «val javaType = Class.forName(returnType.fullyQualifiedName)»
229 if («paramName» != null) {
230 boolean isValidRange = false;
231 «List.importedName»<«Range.importedName»<«javaType.importedName»>> rangeConstraints = new «ArrayList.
233 «FOR r : restrictions.rangeConstraints»
234 rangeConstraints.add(«Range.importedName».closed(new «javaType.importedName»(«r.min.toQuote»), new «javaType.
235 importedName»(«r.max.toQuote»)));
237 for («Range.importedName»<«javaType.importedName»> r : rangeConstraints) {
239 if (r.contains(«paramName».getValue())) {
241 if (r.contains(«paramName»)) {
247 throw new IllegalArgumentException(String.format("Invalid range: %s, expected: %s.", «paramName», rangeConstraints));
252 def protected generateToString(Collection<GeneratedProperty> properties) '''
253 «IF !properties.empty»
255 public String toString() {
256 StringBuilder builder = new StringBuilder();
257 builder.append("«type.name» [«properties.get(0).fieldName»=");
258 «IF properties.get(0).returnType.name.contains("[")»
259 builder.append(«Arrays.importedName».toString(«properties.get(0).fieldName»));
261 builder.append(«properties.get(0).fieldName»);
263 «FOR i : 1..<properties.size»
264 builder.append(", «properties.get(i).fieldName»=");
265 «IF properties.get(i).returnType.name.contains("[")»
266 builder.append(«Arrays.importedName».toString(«properties.get(i).fieldName»));
268 builder.append(«properties.get(i).fieldName»);
272 return builder.toString();
277 def GeneratedProperty getPropByName(GeneratedType gt, String name) {
278 for (GeneratedProperty prop : gt.properties) {
279 if (prop.name.equals(name)) {
286 def getRestrictions(Type type) {
287 var Restrictions restrictions = null
288 if (type instanceof ConcreteType) {
289 restrictions = (type as ConcreteType).restrictions
290 } else if (type instanceof GeneratedTransferObject) {
291 restrictions = (type as GeneratedTransferObject).restrictions
296 def boolean isArrayType(GeneratedTransferObject type) {
298 val GeneratedTransferObject superType = type.findSuperType
299 val GeneratedProperty value = superType.getPropByName("value")
300 if (value != null && value.returnType.name.contains("[")) {
306 def GeneratedTransferObject findSuperType(GeneratedTransferObject gto) {
307 var GeneratedTransferObject base = gto
308 var GeneratedTransferObject superType = base.superType
309 while (superType !== null) {
311 superType = base.superType
316 def String toQuote(Object obj) {
317 return "\"" + obj.toString + "\"";
321 * Template method which generates method parameters with their types from <code>parameters</code>.
324 * list of parameter instances which are transformed to the method parameters
325 * @return string with the list of the method parameters with their types in JAVA format
327 def protected generateParameters(List<MethodSignature.Parameter> parameters) '''«
328 IF !parameters.empty»«
329 FOR parameter : parameters SEPARATOR ", "»«
330 parameter.type.importedName» «parameter.name»«