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 '';
149 val paragraphs = paragraphSplitter.split(comment)
153 «FOR p : paragraphs SEPARATOR "<p>"»
160 def generateRestrictions(Type type, String paramName, Type returnType) '''
161 «val boolean isArray = returnType.name.contains("[")»
162 «processRestrictions(type, paramName, returnType, isArray)»
165 def generateRestrictions(GeneratedProperty field, String paramName) '''
166 «val Type type = field.returnType»
167 «IF type instanceof ConcreteType»
168 «processRestrictions(type, paramName, field.returnType, type.name.contains("["))»
169 «ELSEIF type instanceof GeneratedTransferObject»
170 «processRestrictions(type, paramName, field.returnType, isArrayType(type as GeneratedTransferObject))»
175 private def processRestrictions(Type type, String paramName, Type returnType, boolean isArray) '''
176 «val restrictions = type.getRestrictions»
177 «IF restrictions !== null»
178 «IF !restrictions.lengthConstraints.empty»
179 «generateLengthRestriction(type, restrictions, paramName, isArray,
180 !(returnType instanceof ConcreteType))»
182 «IF !restrictions.rangeConstraints.empty &&
183 ("java.lang".equals(returnType.packageName) || "java.math".equals(returnType.packageName))»
184 «generateRangeRestriction(type, returnType, restrictions, paramName,
185 !(returnType instanceof ConcreteType))»
190 def generateLengthRestriction(Type type, Restrictions restrictions, String paramName, boolean isArray,
191 boolean isNestedType) '''
192 if («paramName» != null) {
193 boolean isValidLength = false;
194 «List.importedName»<«Range.importedName»<«Integer.importedName»>> lengthConstraints = new «ArrayList.
196 «FOR r : restrictions.lengthConstraints»
197 lengthConstraints.add(«Range.importedName».closed(«r.min», «r.max»));
199 for («Range.importedName»<«Integer.importedName»> r : lengthConstraints) {
202 if (r.contains(«paramName».getValue().length)) {
204 if (r.contains(«paramName».length)) {
208 if (r.contains(«paramName».getValue().length())) {
210 if (r.contains(«paramName».length())) {
213 isValidLength = true;
216 if (!isValidLength) {
217 throw new IllegalArgumentException(String.format("Invalid length: {}, expected: {}.", «paramName», lengthConstraints));
222 def generateRangeRestriction(Type type, Type returnType, Restrictions restrictions, String paramName,
223 boolean isNestedType) '''
224 «val javaType = Class.forName(returnType.fullyQualifiedName)»
225 if («paramName» != null) {
226 boolean isValidRange = false;
227 «List.importedName»<«Range.importedName»<«javaType.importedName»>> rangeConstraints = new «ArrayList.
229 «FOR r : restrictions.rangeConstraints»
230 rangeConstraints.add(«Range.importedName».closed(new «javaType.importedName»(«r.min.toQuote»), new «javaType.
231 importedName»(«r.max.toQuote»)));
233 for («Range.importedName»<«javaType.importedName»> r : rangeConstraints) {
235 if (r.contains(«paramName».getValue())) {
237 if (r.contains(«paramName»)) {
243 throw new IllegalArgumentException(String.format("Invalid range: %s, expected: %s.", «paramName», rangeConstraints));
248 def protected generateToString(Collection<GeneratedProperty> properties) '''
249 «IF !properties.empty»
251 public String toString() {
252 StringBuilder builder = new StringBuilder();
253 builder.append("«type.name» [«properties.get(0).fieldName»=");
254 «IF properties.get(0).returnType.name.contains("[")»
255 builder.append(«Arrays.importedName».toString(«properties.get(0).fieldName»));
257 builder.append(«properties.get(0).fieldName»);
259 «FOR i : 1..<properties.size»
260 builder.append(", «properties.get(i).fieldName»=");
261 «IF properties.get(i).returnType.name.contains("[")»
262 builder.append(«Arrays.importedName».toString(«properties.get(i).fieldName»));
264 builder.append(«properties.get(i).fieldName»);
268 return builder.toString();
273 def GeneratedProperty getPropByName(GeneratedType gt, String name) {
274 for (GeneratedProperty prop : gt.properties) {
275 if (prop.name.equals(name)) {
282 def GeneratedProperty getPropByName(Collection<GeneratedProperty> props, String name) {
283 for (GeneratedProperty prop : props) {
284 if (prop.name.equals(name)) {
291 def getRestrictions(Type type) {
292 var Restrictions restrictions = null
293 if (type instanceof ConcreteType) {
294 restrictions = (type as ConcreteType).restrictions
295 } else if (type instanceof GeneratedTransferObject) {
296 restrictions = (type as GeneratedTransferObject).restrictions
301 def boolean isArrayType(GeneratedTransferObject type) {
303 val GeneratedTransferObject superType = type.findSuperType
304 val GeneratedProperty value = superType.getPropByName("value")
305 if (value != null && value.returnType.name.contains("[")) {
311 def GeneratedTransferObject findSuperType(GeneratedTransferObject gto) {
312 var GeneratedTransferObject base = gto
313 var GeneratedTransferObject superType = base.superType
314 while (superType !== null) {
316 superType = base.superType
321 def String toQuote(Object obj) {
322 return "\"" + obj.toString + "\"";
326 * Template method which generates method parameters with their types from <code>parameters</code>.
329 * list of parameter instances which are transformed to the method parameters
330 * @return string with the list of the method parameters with their types in JAVA format
332 def protected generateParameters(List<MethodSignature.Parameter> parameters) '''«
333 IF !parameters.empty»«
334 FOR parameter : parameters SEPARATOR ", "»«
335 parameter.type.importedName» «parameter.name»«