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
26 abstract class BaseTemplate {
28 protected val GeneratedType type;
29 protected val Map<String, String> importMap;
30 static val paragraphSplitter = Splitter.on("\n\n").omitEmptyStrings();
32 new(GeneratedType _type) {
34 throw new IllegalArgumentException("Generated type reference cannot be NULL!")
37 this.importMap = GeneratorUtil.createImports(type)
40 def packageDefinition() '''package «type.packageName»;'''
42 protected def getFullyQualifiedName() {
43 return type.fullyQualifiedName
46 final public def generate() {
56 protected def imports() '''
58 «FOR entry : importMap.entrySet»
59 «IF entry.value != fullyQualifiedName»
60 import «entry.value».«entry.key»;
67 protected abstract def CharSequence body();
70 final protected def fieldName(GeneratedProperty property) '''_«property.name»'''
72 final protected def propertyNameFromGetter(MethodSignature getter) {
74 if (getter.name.startsWith("is")) {
76 } else if (getter.name.startsWith("get")) {
79 throw new IllegalArgumentException("Not a getter")
81 return getter.name.substring(prefix).toFirstLower;
85 * Template method which generates the getter method for <code>field</code>
88 * generated property with data about field which is generated as the getter method
89 * @return string with the getter method source code in JAVA format
91 final protected def getterMethod(GeneratedProperty field) {
93 public «field.returnType.importedName» «field.getterMethodName»() {
94 return «field.fieldName»;
99 final protected def getterMethodName(GeneratedProperty field) {
100 val prefix = if(field.returnType.equals(Types.BOOLEAN)) "is" else "get"
101 return '''«prefix»«field.name.toFirstUpper»'''
105 * Template method which generates the setter method for <code>field</code>
108 * generated property with data about field which is generated as the setter method
109 * @return string with the setter method source code in JAVA format
111 final protected def setterMethod(GeneratedProperty field) '''
112 «val returnType = field.returnType.importedName»
113 public «type.name» set«field.name.toFirstUpper»(«returnType» value) {
114 this.«field.fieldName» = value;
119 final protected def importedName(Type intype) {
120 GeneratorUtil.putTypeIntoImports(type, intype, importMap);
121 GeneratorUtil.getExplicitType(type, intype, importMap)
124 final protected def importedName(Class<?> cls) {
125 importedName(Types.typeForClass(cls))
129 * Template method which generates method parameters with their types from <code>parameters</code>.
132 * group of generated property instances which are transformed to the method parameters
133 * @return string with the list of the method parameters with their types in JAVA format
135 def final protected asArgumentsDeclaration(Iterable<GeneratedProperty> parameters) '''«IF !parameters.empty»«FOR parameter : parameters SEPARATOR ", "»«parameter.
136 returnType.importedName» «parameter.fieldName»«ENDFOR»«ENDIF»'''
139 * Template method which generates sequence of the names of the class attributes from <code>parameters</code>.
142 * group of generated property instances which are transformed to the sequence of parameter names
143 * @return string with the list of the parameter names of the <code>parameters</code>
145 def final protected asArguments(Iterable<GeneratedProperty> parameters) '''«IF !parameters.empty»«FOR parameter : parameters SEPARATOR ", "»«parameter.
146 fieldName»«ENDFOR»«ENDIF»'''
149 * Template method which generates JAVA comments.
151 * @param comment string with the comment for whole JAVA class
152 * @return string with comment in JAVA format
154 def protected CharSequence asJavadoc(String comment) {
155 if(comment == null) return '';
157 if (txt.contains("*/")) {
158 txt = txt.replace("*/", "*/")
160 val paragraphs = paragraphSplitter.split(txt)
164 «FOR p : paragraphs SEPARATOR "<p>"»
171 def generateRestrictions(Type type, String paramName, Type returnType) '''
172 «val boolean isArray = returnType.name.contains("[")»
173 «processRestrictions(type, paramName, returnType, isArray)»
176 def generateRestrictions(GeneratedProperty field, String paramName) '''
177 «val Type type = field.returnType»
178 «IF type instanceof ConcreteType»
179 «processRestrictions(type, paramName, field.returnType, type.name.contains("["))»
180 «ELSEIF type instanceof GeneratedTransferObject»
181 «processRestrictions(type, paramName, field.returnType, isArrayType(type as GeneratedTransferObject))»
186 private def processRestrictions(Type type, String paramName, Type returnType, boolean isArray) '''
187 «val restrictions = type.getRestrictions»
188 «IF restrictions !== null»
189 «IF !restrictions.lengthConstraints.empty»
190 «generateLengthRestriction(type, restrictions, paramName, isArray,
191 !(returnType instanceof ConcreteType))»
193 «IF !restrictions.rangeConstraints.empty &&
194 ("java.lang".equals(returnType.packageName) || "java.math".equals(returnType.packageName))»
195 «generateRangeRestriction(type, returnType, restrictions, paramName,
196 !(returnType instanceof ConcreteType))»
201 def generateLengthRestriction(Type type, Restrictions restrictions, String paramName, boolean isArray,
202 boolean isNestedType) '''
203 if («paramName» != null) {
204 boolean isValidLength = false;
205 «List.importedName»<«Range.importedName»<«Integer.importedName»>> lengthConstraints = new «ArrayList.
207 «FOR r : restrictions.lengthConstraints»
208 lengthConstraints.add(«Range.importedName».closed(«r.min», «r.max»));
210 for («Range.importedName»<«Integer.importedName»> r : lengthConstraints) {
213 if (r.contains(«paramName».getValue().length)) {
215 if (r.contains(«paramName».length)) {
219 if (r.contains(«paramName».getValue().length())) {
221 if (r.contains(«paramName».length())) {
224 isValidLength = true;
227 if (!isValidLength) {
228 throw new IllegalArgumentException(String.format("Invalid length: %s, expected: %s.", «paramName», lengthConstraints));
233 def generateRangeRestriction(Type type, Type returnType, Restrictions restrictions, String paramName,
234 boolean isNestedType) '''
235 «val javaType = Class.forName(returnType.fullyQualifiedName)»
236 if («paramName» != null) {
237 boolean isValidRange = false;
238 «List.importedName»<«Range.importedName»<«javaType.importedName»>> rangeConstraints = new «ArrayList.
240 «FOR r : restrictions.rangeConstraints»
241 rangeConstraints.add(«Range.importedName».closed(new «javaType.importedName»(«r.min.toQuote»), new «javaType.
242 importedName»(«r.max.toQuote»)));
244 for («Range.importedName»<«javaType.importedName»> r : rangeConstraints) {
246 if (r.contains(«paramName».getValue())) {
248 if (r.contains(«paramName»)) {
254 throw new IllegalArgumentException(String.format("Invalid range: %s, expected: %s.", «paramName», rangeConstraints));
259 def protected generateToString(Collection<GeneratedProperty> properties) '''
260 «IF !properties.empty»
262 public String toString() {
263 StringBuilder builder = new StringBuilder("«type.name» [");
264 boolean first = true;
266 «FOR property : properties»
267 if («property.fieldName» != null) {
271 builder.append(", ");
273 builder.append("«property.fieldName»=");
274 «IF property.returnType.name.contains("[")»
275 builder.append(«Arrays.importedName».toString(«property.fieldName»));
277 builder.append(«property.fieldName»);
281 return builder.append(']').toString();
286 def GeneratedProperty getPropByName(GeneratedType gt, String name) {
287 for (GeneratedProperty prop : gt.properties) {
288 if (prop.name.equals(name)) {
295 def getRestrictions(Type type) {
296 var Restrictions restrictions = null
297 if (type instanceof ConcreteType) {
298 restrictions = (type as ConcreteType).restrictions
299 } else if (type instanceof GeneratedTransferObject) {
300 restrictions = (type as GeneratedTransferObject).restrictions
305 def boolean isArrayType(GeneratedTransferObject type) {
307 val GeneratedTransferObject superType = type.findSuperType
308 val GeneratedProperty value = superType.getPropByName("value")
309 if (value != null && value.returnType.name.contains("[")) {
315 def GeneratedTransferObject findSuperType(GeneratedTransferObject gto) {
316 var GeneratedTransferObject base = gto
317 var GeneratedTransferObject superType = base.superType
318 while (superType !== null) {
320 superType = base.superType
325 def String toQuote(Object obj) {
326 return "\"" + obj.toString + "\"";
330 * Template method which generates method parameters with their types from <code>parameters</code>.
333 * list of parameter instances which are transformed to the method parameters
334 * @return string with the list of the method parameters with their types in JAVA format
336 def protected generateParameters(List<MethodSignature.Parameter> parameters) '''«
337 IF !parameters.empty»«
338 FOR parameter : parameters SEPARATOR ", "»«
339 parameter.type.importedName» «parameter.name»«