2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.yangtools.sal.java.api.generator
10 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty
11 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType
13 import org.opendaylight.yangtools.sal.binding.model.api.Type
14 import org.opendaylight.yangtools.binding.generator.util.Types
15 import com.google.common.base.Splitter
16 import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature
17 import com.google.common.collect.Range
18 import java.util.ArrayList
20 import org.opendaylight.yangtools.sal.binding.model.api.ConcreteType
21 import org.opendaylight.yangtools.sal.binding.model.api.Restrictions
22 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject
23 import java.util.Collection
24 import java.util.Arrays
25 import java.util.HashMap
27 abstract class BaseTemplate {
29 protected val GeneratedType type;
30 protected val Map<String, String> importMap;
31 static val paragraphSplitter = Splitter.on("\n\n").omitEmptyStrings();
33 new(GeneratedType _type) {
35 throw new IllegalArgumentException("Generated type reference cannot be NULL!")
38 this.importMap = new HashMap<String,String>()
41 def packageDefinition() '''package «type.packageName»;'''
43 protected def getFullyQualifiedName() {
44 return type.fullyQualifiedName
47 final public def generate() {
57 protected def imports() '''
59 «FOR entry : importMap.entrySet»
60 «IF entry.value != fullyQualifiedName»
61 import «entry.value».«entry.key»;
68 protected abstract def CharSequence body();
71 final protected def fieldName(GeneratedProperty property) '''_«property.name»'''
73 final protected def propertyNameFromGetter(MethodSignature getter) {
75 if (getter.name.startsWith("is")) {
77 } else if (getter.name.startsWith("get")) {
80 throw new IllegalArgumentException("Not a getter")
82 return getter.name.substring(prefix).toFirstLower;
86 * Template method which generates the getter method for <code>field</code>
89 * generated property with data about field which is generated as the getter method
90 * @return string with the getter method source code in JAVA format
92 final protected def getterMethod(GeneratedProperty field) {
94 public «field.returnType.importedName» «field.getterMethodName»() {
95 return «field.fieldName»;
100 final protected def getterMethodName(GeneratedProperty field) {
101 val prefix = if(field.returnType.equals(Types.BOOLEAN)) "is" else "get"
102 return '''«prefix»«field.name.toFirstUpper»'''
106 * Template method which generates the setter method for <code>field</code>
109 * generated property with data about field which is generated as the setter method
110 * @return string with the setter method source code in JAVA format
112 final protected def setterMethod(GeneratedProperty field) '''
113 «val returnType = field.returnType.importedName»
114 public «type.name» set«field.name.toFirstUpper»(«returnType» value) {
115 this.«field.fieldName» = value;
120 final protected def importedName(Type intype) {
121 GeneratorUtil.putTypeIntoImports(type, intype, importMap);
122 GeneratorUtil.getExplicitType(type, intype, importMap)
125 final protected def importedName(Class<?> cls) {
126 importedName(Types.typeForClass(cls))
130 * Template method which generates method parameters with their types from <code>parameters</code>.
133 * group of generated property instances which are transformed to the method parameters
134 * @return string with the list of the method parameters with their types in JAVA format
136 def final protected asArgumentsDeclaration(Iterable<GeneratedProperty> parameters) '''«IF !parameters.empty»«FOR parameter : parameters SEPARATOR ", "»«parameter.
137 returnType.importedName» «parameter.fieldName»«ENDFOR»«ENDIF»'''
140 * Template method which generates sequence of the names of the class attributes from <code>parameters</code>.
143 * group of generated property instances which are transformed to the sequence of parameter names
144 * @return string with the list of the parameter names of the <code>parameters</code>
146 def final protected asArguments(Iterable<GeneratedProperty> parameters) '''«IF !parameters.empty»«FOR parameter : parameters SEPARATOR ", "»«parameter.
147 fieldName»«ENDFOR»«ENDIF»'''
150 * Template method which generates JAVA comments.
152 * @param comment string with the comment for whole JAVA class
153 * @return string with comment in JAVA format
155 def protected CharSequence asJavadoc(String comment) {
156 if(comment == null) return '';
158 if (txt.contains("*/")) {
159 txt = txt.replace("*/", "*/")
161 val paragraphs = paragraphSplitter.split(txt)
165 «FOR p : paragraphs SEPARATOR "<p>"»
172 def generateRestrictions(Type type, String paramName, Type returnType) '''
173 «val boolean isArray = returnType.name.contains("[")»
174 «processRestrictions(type, paramName, returnType, isArray)»
177 def generateRestrictions(GeneratedProperty field, String paramName) '''
178 «val Type type = field.returnType»
179 «IF type instanceof ConcreteType»
180 «processRestrictions(type, paramName, field.returnType, type.name.contains("["))»
181 «ELSEIF type instanceof GeneratedTransferObject»
182 «processRestrictions(type, paramName, field.returnType, isArrayType(type as GeneratedTransferObject))»
187 private def processRestrictions(Type type, String paramName, Type returnType, boolean isArray) '''
188 «val restrictions = type.getRestrictions»
189 «IF restrictions !== null»
190 «IF !restrictions.lengthConstraints.empty»
191 «generateLengthRestriction(type, restrictions, paramName, isArray,
192 !(returnType instanceof ConcreteType))»
194 «IF !restrictions.rangeConstraints.empty &&
195 ("java.lang".equals(returnType.packageName) || "java.math".equals(returnType.packageName))»
196 «generateRangeRestriction(type, returnType, restrictions, paramName,
197 !(returnType instanceof ConcreteType))»
202 def generateLengthRestriction(Type type, Restrictions restrictions, String paramName, boolean isArray,
203 boolean isNestedType) '''
204 if («paramName» != null) {
205 boolean isValidLength = false;
206 «List.importedName»<«Range.importedName»<«Integer.importedName»>> lengthConstraints = new «ArrayList.
208 «FOR r : restrictions.lengthConstraints»
209 lengthConstraints.add(«Range.importedName».closed(«r.min», «r.max»));
211 for («Range.importedName»<«Integer.importedName»> r : lengthConstraints) {
214 if (r.contains(«paramName».getValue().length)) {
216 if (r.contains(«paramName».length)) {
220 if (r.contains(«paramName».getValue().length())) {
222 if (r.contains(«paramName».length())) {
225 isValidLength = true;
228 if (!isValidLength) {
229 throw new IllegalArgumentException(String.format("Invalid length: %s, expected: %s.", «paramName», lengthConstraints));
234 def generateRangeRestriction(Type type, Type returnType, Restrictions restrictions, String paramName,
235 boolean isNestedType) '''
236 «val javaType = Class.forName(returnType.fullyQualifiedName)»
237 if («paramName» != null) {
238 boolean isValidRange = false;
239 «List.importedName»<«Range.importedName»<«javaType.importedName»>> rangeConstraints = new «ArrayList.
241 «FOR r : restrictions.rangeConstraints»
242 rangeConstraints.add(«Range.importedName».closed(new «javaType.importedName»(«r.min.toQuote»), new «javaType.
243 importedName»(«r.max.toQuote»)));
245 for («Range.importedName»<«javaType.importedName»> r : rangeConstraints) {
247 if (r.contains(«paramName».getValue())) {
249 if (r.contains(«paramName»)) {
255 throw new IllegalArgumentException(String.format("Invalid range: %s, expected: %s.", «paramName», rangeConstraints));
260 def protected generateToString(Collection<GeneratedProperty> properties) '''
261 «IF !properties.empty»
263 public «String.importedName» toString() {
264 «StringBuilder.importedName» builder = new «StringBuilder.importedName»("«type.name» [");
265 boolean first = true;
267 «FOR property : properties»
268 if («property.fieldName» != null) {
272 builder.append(", ");
274 builder.append("«property.fieldName»=");
275 «IF property.returnType.name.contains("[")»
276 builder.append(«Arrays.importedName».toString(«property.fieldName»));
278 builder.append(«property.fieldName»);
282 return builder.append(']').toString();
287 def GeneratedProperty getPropByName(GeneratedType gt, String name) {
288 for (GeneratedProperty prop : gt.properties) {
289 if (prop.name.equals(name)) {
296 def getRestrictions(Type type) {
297 var Restrictions restrictions = null
298 if (type instanceof ConcreteType) {
299 restrictions = (type as ConcreteType).restrictions
300 } else if (type instanceof GeneratedTransferObject) {
301 restrictions = (type as GeneratedTransferObject).restrictions
306 def boolean isArrayType(GeneratedTransferObject type) {
308 val GeneratedTransferObject superType = type.findSuperType
309 val GeneratedProperty value = superType.getPropByName("value")
310 if (value != null && value.returnType.name.contains("[")) {
316 def GeneratedTransferObject findSuperType(GeneratedTransferObject gto) {
317 var GeneratedTransferObject base = gto
318 var GeneratedTransferObject superType = base.superType
319 while (superType !== null) {
321 superType = base.superType
326 def String toQuote(Object obj) {
327 return "\"" + obj.toString + "\"";
331 * Template method which generates method parameters with their types from <code>parameters</code>.
334 * list of parameter instances which are transformed to the method parameters
335 * @return string with the list of the method parameters with their types in JAVA format
337 def protected generateParameters(List<MethodSignature.Parameter> parameters) '''«
338 IF !parameters.empty»«
339 FOR parameter : parameters SEPARATOR ", "»«
340 parameter.type.importedName» «parameter.name»«