import java.util.ArrayList
import java.util.HashSet
import java.util.Collection
+import org.opendaylight.yangtools.yang.binding.Identifiable
/**\r
* Template for generating JAVA builder classes. \r
*/\r
\r
class BuilderTemplate extends BaseTemplate {\r
- \r
+\r
/**\r
* Constant with the name of the concrete method.\r
*/\r
val static GET_AUGMENTATION_METHOD_NAME = "getAugmentation"\r
- \r
+\r
/**\r
* Constant with the suffix for builder classes.\r
*/\r
val static BUILDER = 'Builder'\r
- \r
+\r
/**\r
* Constant with suffix for the classes which are generated from the builder classes.\r
*/\r
val static IMPL = 'Impl'\r
- \r
+\r
/**\r
* Generated property is set if among methods is found one with the name GET_AUGMENTATION_METHOD_NAME\r
*/\r
var GeneratedProperty augmentField\r
- \r
+\r
/**\r
* Set of class attributes (fields) which are derived from the getter methods names\r
*/\r
val Set<GeneratedProperty> properties\r
- \r
+\r
/**\r
* Constructs new instance of this class.\r
* @throws IllegalArgumentException if <code>genType</code> equals <code>null</code>\r
super(genType)\r
this.properties = propertiesFromMethods(createMethods)\r
}\r
- \r
+\r
/**\r
* Returns set of method signature instances which contains all the methods of the <code>genType</code>\r
* and all the methods of the implemented interfaces.\r
collectImplementedMethods(methods, type.implements)\r
return methods\r
}\r
- \r
\r
/**\r
* Adds to the <code>methods</code> set all the methods of the <code>implementedIfcs</code> \r
} else if (implementedIfc.fullyQualifiedName == Augmentable.name) {\r
for (m : Augmentable.methods) {\r
if (m.name == GET_AUGMENTATION_METHOD_NAME) {\r
- //addToImports(JAVA_UTIL, HASH_MAP)\r
- //addToImports(JAVA_UTIL, MAP)\r
val fullyQualifiedName = m.returnType.name\r
val pkg = fullyQualifiedName.package\r
val name = fullyQualifiedName.name\r
- //addToImports(pkg, name)\r
val tmpGenTO = new GeneratedTOBuilderImpl(pkg, name)\r
val refType = new ReferencedTypeImpl(pkg, name)\r
val generic = new ReferencedTypeImpl(type.packageName, type.name)\r
}\r
}\r
}\r
- \r
- \r
+\r
/**\r
* Returns the first element of the list <code>elements</code>.\r
* \r
def private <E> first(List<E> elements) {\r
elements.get(0)\r
}\r
- \r
+\r
/**\r
* Returns the name of the package from <code>fullyQualifiedName</code>.\r
* \r
val lastDotIndex = fullyQualifiedName.lastIndexOf(Constants.DOT)\r
return if (lastDotIndex == -1) fullyQualifiedName else fullyQualifiedName.substring(lastDotIndex + 1)\r
}\r
- \r
\r
/**\r
* Creates set of generated property instances from getter <code>methods</code>.\r
* @return set of generated property instances which represents the getter <code>methods</code>\r
*/\r
def private propertiesFromMethods(Set<MethodSignature> methods) {\r
- \r
-\r
if (methods == null || methods.isEmpty()) {\r
return Collections.emptySet\r
}\r
}\r
return result\r
}\r
- \r
+\r
/**\r
* Creates generated property instance from the getter <code>method</code> name and return type.\r
* \r
* </ul>\r
*/\r
def private GeneratedProperty propertyFromGetter(MethodSignature method) {\r
-\r
if (method == null || method.name == null || method.name.empty || method.returnType == null) {\r
throw new IllegalArgumentException("Method, method name, method return type reference cannot be NULL or empty!")\r
}\r
\r
«generateConstructorsFromIfcs(type)»\r
\r
- «generateSetterFromIfcs(type)»\r
+ «generateMethodFieldsFrom(type)»\r
\r
«generateGetters(false)»\r
\r
}\r
'''\r
\r
+ /**\r
+ * Generate default constructor and constructor for every implemented interface from uses statements.\r
+ */\r
def private generateConstructorsFromIfcs(Type type) '''\r
public «type.name»«BUILDER»() {\r
} \r
«IF (type instanceof GeneratedType && !(type instanceof GeneratedTransferObject))»\r
- «val ifc = type as GeneratedType»\r
- «FOR impl : ifc.implements»\r
- «generateConstructorFromIfc(impl)»\r
- «ENDFOR»\r
+ «val ifc = type as GeneratedType»\r
+ «FOR impl : ifc.implements»\r
+ «generateConstructorFromIfc(impl)»\r
+ «ENDFOR»\r
«ENDIF»\r
'''\r
\r
+ /**\r
+ * Generate constructor with argument of given type.\r
+ */\r
def private generateConstructorFromIfc(Type impl) '''\r
«IF (impl instanceof GeneratedType) && !((impl as GeneratedType).methodDefinitions.empty)»\r
- «val implType = impl as GeneratedType»\r
+ «val implType = impl as GeneratedType»\r
\r
- public «type.name»«BUILDER»(«implType.fullyQualifiedName» arg) {\r
- «printConstructorProperties(implType)»\r
- }\r
- «FOR implTypeImplement : implType.implements»\r
- «generateConstructorFromIfc(implTypeImplement)»\r
- «ENDFOR»\r
+ public «type.name»«BUILDER»(«implType.fullyQualifiedName» arg) {\r
+ «printConstructorPropertySetter(implType)»\r
+ }\r
+ «FOR implTypeImplement : implType.implements»\r
+ «generateConstructorFromIfc(implTypeImplement)»\r
+ «ENDFOR»\r
«ENDIF»\r
'''\r
\r
- def private printConstructorProperties(Type implementedIfc) '''\r
+ def private printConstructorPropertySetter(Type implementedIfc) '''\r
«IF (implementedIfc instanceof GeneratedType && !(implementedIfc instanceof GeneratedTransferObject))»\r
- «val ifc = implementedIfc as GeneratedType»\r
- «FOR getter : ifc.methodDefinitions»\r
- this._«getter.propertyNameFromGetter» = arg.«getter.name»();\r
- «ENDFOR»\r
- «FOR impl : ifc.implements»\r
- «printConstructorProperties(impl)»\r
- «ENDFOR»\r
+ «val ifc = implementedIfc as GeneratedType»\r
+ «FOR getter : ifc.methodDefinitions»\r
+ this._«getter.propertyNameFromGetter» = arg.«getter.name»();\r
+ «ENDFOR»\r
+ «FOR impl : ifc.implements»\r
+ «printConstructorPropertySetter(impl)»\r
+ «ENDFOR»\r
«ENDIF»\r
'''\r
\r
- def private generateSetterFromIfcs(Type type) '''\r
+ /**\r
+ * Generate 'fieldsFrom' method to set builder properties based on type of given argument.\r
+ */\r
+ def private generateMethodFieldsFrom(Type type) '''\r
«IF (type instanceof GeneratedType && !(type instanceof GeneratedTransferObject))»\r
- «val ifc = type as GeneratedType»\r
- «val List<Type> done = ifc.getBaseIfcs»\r
- «generateCommentForSetter(ifc)»\r
- public void fieldsFrom(«DataObject.importedName» arg) {\r
- boolean isValidArg = false;\r
- «FOR impl : ifc.getAllIfcs»\r
- «generateSettersForIfc(impl, done)»\r
- «ENDFOR»\r
- if (!isValidArg) {\r
- throw new IllegalArgumentException(\r
- "expected one of: «ifc.getAllIfcs.toListOfNames» \n" +\r
- "but was: " + arg\r
- );\r
- }\r
- }\r
+ «val ifc = type as GeneratedType»\r
+ «IF ifc.hasImplementsFromUses»\r
+ «val List<Type> done = ifc.getBaseIfcs»\r
+ «generateMethodFieldsFromComment(ifc)»\r
+ public void fieldsFrom(«DataObject.importedName» arg) {\r
+ boolean isValidArg = false;\r
+ «FOR impl : ifc.getAllIfcs»\r
+ «generateIfCheck(impl, done)»\r
+ «ENDFOR»\r
+ if (!isValidArg) {\r
+ throw new IllegalArgumentException(\r
+ "expected one of: «ifc.getAllIfcs.toListOfNames» \n" +\r
+ "but was: " + arg\r
+ );\r
+ }\r
+ }\r
+ «ENDIF»\r
«ENDIF»\r
'''\r
\r
- def private generateSettersForIfc(Type impl, List<Type> done) '''\r
+ def private generateMethodFieldsFromComment(GeneratedType type) '''\r
+ /**\r
+ Set fields from given grouping argument. Valid argument is instance of one of following types:\r
+ * <ul>\r
+ «FOR impl : type.getAllIfcs»\r
+ * <li>«impl.fullyQualifiedName»</li>\r
+ «ENDFOR»\r
+ * </ul>\r
+ *\r
+ * @param arg grouping object\r
+ * @throws IllegalArgumentException if given argument is none of valid types\r
+ */\r
+ '''\r
+\r
+ /**\r
+ * Method is used to find out if given type implements any interface from uses.\r
+ */\r
+ def boolean hasImplementsFromUses(GeneratedType type) {\r
+ var i = 0\r
+ for (impl : type.getAllIfcs) {\r
+ if ((impl instanceof GeneratedType) && !((impl as GeneratedType).methodDefinitions.empty)) {\r
+ i = i + 1\r
+ }\r
+ }\r
+ return i > 0\r
+ }\r
+\r
+ def private generateIfCheck(Type impl, List<Type> done) '''\r
«IF (impl instanceof GeneratedType) && !((impl as GeneratedType).methodDefinitions.empty)»\r
«val implType = impl as GeneratedType»\r
if (arg instanceof «implType.fullyQualifiedName») {\r
- «printSetterProperties(implType)»\r
+ «printPropertySetter(implType)»\r
isValidArg = true;\r
}\r
«ENDIF»\r
'''\r
\r
- def private generateSettersForNestedIfc(Type impl, List<Type> done) '''\r
- «IF (impl instanceof GeneratedType) && !((impl as GeneratedType).methodDefinitions.empty)»\r
- «val implType = impl as GeneratedType»\r
- «val boolean added = done.contains(impl)»\r
- «IF !(added)»\r
- if (arg instanceof «implType.fullyQualifiedName») {\r
- «printSetterProperties(implType)»\r
- }\r
- «ENDIF»\r
- «FOR implTypeImplement : implType.implements»\r
- «generateSettersForNestedIfc(implTypeImplement, done)»\r
- «ENDFOR»\r
- «ENDIF»\r
- '''\r
-\r
- def private printSetterProperties(Type implementedIfc) '''\r
+ def private printPropertySetter(Type implementedIfc) '''\r
«IF (implementedIfc instanceof GeneratedType && !(implementedIfc instanceof GeneratedTransferObject))»\r
«val ifc = implementedIfc as GeneratedType»\r
«FOR getter : ifc.methodDefinitions»\r
«ENDIF»\r
'''\r
\r
- def private generateCommentForSetter(GeneratedType type) '''\r
- /**\r
- Set fields from given grouping argument. Valid argument is instance of one of following types:\r
- * <ul>\r
- «FOR impl : type.getAllIfcs»\r
- * <li>«impl.fullyQualifiedName»</li>\r
- «ENDFOR»\r
- * </ul>\r
- *\r
- * @param arg grouping object\r
- * @throws IllegalArgumentException if given argument is none of valid types\r
- */\r
- '''\r
-\r
private def List<Type> getBaseIfcs(GeneratedType type) {\r
val List<Type> baseIfcs = new ArrayList();\r
for (ifc : type.implements) {\r
def private generateFields(boolean _final) '''\r
«IF !properties.empty»\r
«FOR f : properties»\r
- private «IF _final»final«ENDIF» «f.returnType.importedName» «f.fieldName»;\r
+ private«IF _final» final«ENDIF» «f.returnType.importedName» «f.fieldName»;\r
«ENDFOR»\r
«ENDIF»\r
«IF augmentField != null»\r
def private generateSetters() '''\r
«FOR field : properties SEPARATOR '\n'»\r
public «type.name»«BUILDER» set«field.name.toFirstUpper»(«field.returnType.importedName» value) {\r
- «generateLengthRestrictions(field.returnType, "value")»\r
+ «generateRestrictions(field, "value")»\r
\r
this.«field.fieldName» = value;\r
return this;\r
}\r
«ENDFOR»\r
«IF augmentField != null»\r
- \r
+\r
public «type.name»«BUILDER» add«augmentField.name.toFirstUpper»(Class<? extends «augmentField.returnType.importedName»> augmentationType, «augmentField.returnType.importedName» augmentation) {\r
this.«augmentField.name».put(augmentationType, augmentation);\r
return this;\r
*/\r
def private generateConstructor() '''\r
private «type.name»«IMPL»(«type.name»«BUILDER» builder) {\r
- «IF !properties.empty»\r
- «FOR field : properties»\r
- this.«field.fieldName» = builder.«field.getterMethodName»();\r
+ «val allProps = new ArrayList(properties)»\r
+ «val isList = implementsIfc(type, Types.parameterizedTypeFor(Types.typeForClass(Identifiable), type))»\r
+ «val keyType = type.getKey»\r
+ «IF isList && keyType != null»\r
+ «val keyProps = new ArrayList((keyType as GeneratedTransferObject).properties)»\r
+ «Collections.sort(keyProps,\r
+ [ p1, p2 |\r
+ return p1.name.compareTo(p2.name)\r
+ ])\r
+ »\r
+ «FOR field : keyProps»\r
+ «removeProperty(allProps, field.name)»\r
«ENDFOR»\r
+ «removeProperty(allProps, "key")»\r
+ if (builder.getKey() == null) {\r
+ this._key = new «keyType.importedName»(\r
+ «FOR keyProp : keyProps SEPARATOR ", "»\r
+ builder.«keyProp.getterMethodName»()\r
+ «ENDFOR»\r
+ );\r
+ «FOR field : keyProps»\r
+ this.«field.fieldName» = builder.«field.getterMethodName»();\r
+ «ENDFOR»\r
+ } else {\r
+ this._key = builder.getKey();\r
+ «FOR field : keyProps»\r
+ this.«field.fieldName» = _key.«field.getterMethodName»();\r
+ «ENDFOR»\r
+ }\r
«ENDIF»\r
+ «FOR field : allProps»\r
+ this.«field.fieldName» = builder.«field.getterMethodName»();\r
+ «ENDFOR»\r
«IF augmentField != null»\r
this.«augmentField.name».putAll(builder.«augmentField.name»);\r
«ENDIF»\r
}\r
'''\r
- \r
+\r
+ private def boolean implementsIfc(GeneratedType type, Type impl) {\r
+ for (Type ifc : type.implements) {\r
+ if (ifc.equals(impl)) {\r
+ return true;\r
+ }\r
+ }\r
+ return false;\r
+ }\r
+\r
+ private def Type getKey(GeneratedType type) {\r
+ for (m : type.methodDefinitions) {\r
+ if ("getKey".equals(m.name)) {\r
+ return m.returnType;\r
+ }\r
+ }\r
+ return null;\r
+ }\r
+\r
+ private def void removeProperty(Collection<GeneratedProperty> props, String name) {\r
+ var GeneratedProperty toRemove = null\r
+ for (p : props) {\r
+ if (p.name.equals(name)) {\r
+ toRemove = p;\r
+ }\r
+ }\r
+ if (toRemove != null) {\r
+ props.remove(toRemove);\r
+ }\r
+ }\r
\r
/**\r
* Template method which generate getter methods for IMPL class.\r
return «type.importedName».class;\r
}\r
'''\r
- \r
+\r
}\r
\r