X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=code-generator%2Fbinding-java-api-generator%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fyangtools%2Fsal%2Fjava%2Fapi%2Fgenerator%2FClassTemplate.xtend;h=25236bcfd1ebcba5b8b7ea8d92f6f5f3ad0172db;hb=6ead361308210a0926250900b644efa4e2ddb19b;hp=c58a781761b3a5bf595570b8afd841dd0f6eb4db;hpb=c173dce5639bef5016b14debdef051e79ebe91f1;p=yangtools.git diff --git a/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/ClassTemplate.xtend b/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/ClassTemplate.xtend index c58a781761..25236bcfd1 100644 --- a/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/ClassTemplate.xtend +++ b/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/ClassTemplate.xtend @@ -1,434 +1,457 @@ -package org.opendaylight.yangtools.sal.java.api.generator - -import java.util.List -import java.util.Map -import org.opendaylight.yangtools.binding.generator.util.TypeConstants -import org.opendaylight.yangtools.sal.binding.model.api.Constant -import org.opendaylight.yangtools.sal.binding.model.api.Enumeration -import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty -import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject -import org.opendaylight.yangtools.sal.binding.model.api.Type -import org.opendaylight.yangtools.binding.generator.util.Types - -/** - * Template for generating JAVA class. +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html */ -class ClassTemplate { - - /** - * Generated transfer object for which class JAVA file is generated - */ - val GeneratedTransferObject genTO - - /** - * Map of imports for this genTO. - */ - val Map imports - - /** - * List of generated property instances which represents class attributes. - */ - val List fields - - /** - * List of enumeration which are generated as JAVA enum type. - */ - val List enums - - /** - * List of constant instances which are generated as JAVA public static final attributes. - */ - val List consts - - /** - * Creates instance of this class with concrete genTO. - * - * @param genTO generated transfer object which will be transformed to JAVA class source code - */ - new(GeneratedTransferObject genTO) { - if (genTO == null) { - throw new IllegalArgumentException("Generated transfer object reference cannot be NULL!") - } - - this.genTO = genTO - this.imports = GeneratorUtil.createImports(genTO) - this.fields = genTO.properties - this.enums = genTO.enumerations - this.consts = genTO.constantDefinitions - } - - /** - * Generates JAVA class source code (package name + class body). - * - * @return string with JAVA class source code - */ - def String generate() { - val body = generateBody(false) - val pkgAndImports = generatePkgAndImports - return pkgAndImports.toString + body.toString - } - - /** - * Generates JAVA class source code (class body only). - * - * @return string with JAVA class body source code - */ - def generateAsInnerClass() { - return generateBody(true) - } - - /** - * Template method which generates class body. - * - * @param isInnerClass boolean value which specify if generated class is|isn't inner - * @return string with class source code in JAVA format - */ - def private generateBody(boolean isInnerClass) ''' - «genTO.comment.generateComment» - «generateClassDeclaration(isInnerClass)» { - - «generateEnums» - - «generateConstants» - - «generateFields» - - «generateConstructor» - - «FOR field : fields SEPARATOR "\n"» - «field.generateGetter» - «IF !field.readOnly» - - «field.generateSetter» - «ENDIF» - «ENDFOR» - - «generateHashCode» - - «generateEquals» - - «generateToString» - - } - ''' - - /** - * Template method which generates JAVA comments. - * - * @param string with the comment for whole JAVA class - * @return string with comment in JAVA format - */ - def private generateComment(String comment) ''' - «IF comment != null && !comment.empty» - /* - «comment» - */ - «ENDIF» - ''' - - /** - * Template method which generates JAVA class declaration. - * - * @param isInnerClass boolean value which specify if generated class is|isn't inner - * @return string with class declaration in JAVA format - */ - def private generateClassDeclaration(boolean isInnerClass) ''' - public« - IF (isInnerClass)»« - " static final "»« - ELSEIF (genTO.abstract)»« - " abstract "»« - ELSE»« - " "»« - ENDIF»class «genTO.name»« - IF (genTO.extends != null)»« - " extends "»«genTO.extends.resolveName»« - ENDIF»« - IF (!genTO.implements.empty)»« - " implements "»« - FOR type : genTO.implements SEPARATOR ", "»« - type.resolveName»« - ENDFOR»« - ENDIF - »''' - - /** - * Template method which generates JAVA enum type. - * - * @return string with inner enum source code in JAVA format - */ - def private generateEnums() ''' - «IF !enums.empty» - «FOR e : enums SEPARATOR "\n"» - «val enumTemplate = new EnumTemplate(e)» - «enumTemplate.generateAsInnerClass» - «ENDFOR» - «ENDIF» - ''' - - /** - * Template method wich generates JAVA constants. - * - * @return string with constants in JAVA format - */ - def private generateConstants() ''' - «IF !consts.empty» - «FOR c : consts» - «IF c.name == TypeConstants.PATTERN_CONSTANT_NAME» - «val cValue = c.value» - «IF cValue instanceof List» - «val cValues = cValue as List» - private static final List «Constants.MEMBER_PATTERN_LIST» = new ArrayList(); - public static final List «TypeConstants.PATTERN_CONSTANT_NAME» = Arrays.asList(« - FOR v : cValues SEPARATOR ", "»« - IF v instanceof String»"« - v as String»"« - ENDIF»« - ENDFOR»); - - «generateStaticInicializationBlock» - «ENDIF» - «ELSE» - public static final «c.type.resolveName» «c.name» = «c.value»; - «ENDIF» - «ENDFOR» - «ENDIF» - ''' - - /** - * Template method which generates JAVA static initialization block. - * - * @return string with static initialization block in JAVA format - */ - def private generateStaticInicializationBlock() ''' - static { - for (String regEx : «TypeConstants.PATTERN_CONSTANT_NAME») { - «Constants.MEMBER_PATTERN_LIST».add(Pattern.compile(regEx)); - } - } - ''' - - /** - * Template method which generates JAVA class attributes. - * - * @return string with the class attributes in JAVA format - */ - def private generateFields() ''' - «IF !fields.empty» - «FOR f : fields» - private «f.returnType.resolveName» «f.fieldName»; - «ENDFOR» - «ENDIF» - ''' - - /** - * Template method which generates JAVA constructor(s). - * - * @return string with the class constructor(s) in JAVA format - */ - def private generateConstructor() ''' - «val genTOTopParent = GeneratorUtil.getTopParrentTransportObject(genTO)» - «val properties = GeneratorUtil.resolveReadOnlyPropertiesFromTO(genTO.properties)» - «val propertiesAllParents = GeneratorUtil.getPropertiesOfAllParents(genTO)» - «IF !genTO.unionType» -««« create constructor for every parent property - «IF genTOTopParent != genTO && genTOTopParent.unionType» - «FOR parentProperty : propertiesAllParents SEPARATOR "\n"» - «val parentPropertyAndProperties = properties + #[parentProperty]» - «if (genTO.abstract) "protected" else "public"» «genTO.name»(«parentPropertyAndProperties.generateParameters») { - super(«#[parentProperty].generateParameterNames»); - «FOR property : properties» - this.«property.fieldName» = «property.name»; - «ENDFOR» - } - «ENDFOR» -««« create one constructor - «ELSE» - «val propertiesAll = propertiesAllParents + properties» - «if (genTO.abstract) "protected" else "public"» «genTO.name»(«propertiesAll.generateParameters») { - super(«propertiesAllParents.generateParameterNames()»); - «FOR property : properties» - this.«property.fieldName» = «property.fieldName»; - «ENDFOR» - } - «ENDIF» -««« create constructor for every property - «ELSE» - «FOR property : properties SEPARATOR "\n"» - «val propertyAndTopParentProperties = propertiesAllParents + #[property]» - «if (genTO.abstract) "protected" else "public"» «genTO.name»(«propertyAndTopParentProperties.generateParameters») { - super(«propertiesAllParents.generateParameterNames()»); - this.«property.fieldName» = «property.fieldName»; - } - «ENDFOR» - «ENDIF» - ''' - - /** - * Template method which generates the getter method for field - * - * @param field - * generated property with data about field which is generated as the getter method - * @return string with the getter method source code in JAVA format - */ - def private generateGetter(GeneratedProperty field) { - val prefix = if(field.returnType.equals(Types.typeForClass(Boolean))) "is" else "get" - ''' - public «field.returnType.resolveName» «prefix»«field.name.toFirstUpper»() { - return «field.fieldName»; - - } - ''' - } - /** - * Template method which generates the setter method for field - * - * @param field - * generated property with data about field which is generated as the setter method - * @return string with the setter method source code in JAVA format - */ - def private generateSetter(GeneratedProperty field) ''' - «val type = field.returnType.resolveName» - public void set«field.name.toFirstUpper»(«type» «field.fieldName») { - this.«field.fieldName» = «field.fieldName»; - } - ''' - - /** - * Template method which generates method parameters with their types from parameters. - * - * @param parameters - * group of generated property instances which are transformed to the method parameters - * @return string with the list of the method parameters with their types in JAVA format - */ - def private generateParameters(Iterable parameters) '''« - IF !parameters.empty»« - FOR parameter : parameters SEPARATOR ", "»« - parameter.returnType.resolveName» «parameter.fieldName»« - ENDFOR»« - ENDIF - »''' - - /** - * Template method which generates sequence of the names of the class attributes from parameters. - * - * @param parameters - * group of generated property instances which are transformed to the sequence of parameter names - * @return string with the list of the parameter names of the parameters - */ - def private generateParameterNames(Iterable parameters) '''« - IF !parameters.empty»« - FOR parameter : parameters SEPARATOR ", "»« - parameter.fieldName»« - ENDFOR»« - ENDIF - »''' - - /** - * Template method which generates the method hashCode(). - * - * @return string with the hashCode() method definition in JAVA format - */ - def private generateHashCode() ''' - «IF !genTO.hashCodeIdentifiers.empty» - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - «FOR property : genTO.hashCodeIdentifiers» - result = prime * result + ((«property.fieldName» == null) ? 0 : «property.fieldName».hashCode()); - «ENDFOR» - return result; - } - «ENDIF» - ''' - - /** - * Template method which generates the method equals(). - * - * @return string with the equals() method definition in JAVA format - */ - def private generateEquals() ''' - «IF !genTO.equalsIdentifiers.empty» - @Override - public boolean equals(java.lang.Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - «genTO.name» other = («genTO.name») obj; - «FOR property : genTO.equalsIdentifiers» - «val fieldName = property.fieldName» - if («fieldName» == null) { - if (other.«fieldName» != null) { - return false; - } - } else if(!«fieldName».equals(other.«fieldName»)) { - return false; - } - «ENDFOR» - return true; - } - «ENDIF» - ''' - - /** - * Template method which generates the method toString(). - * - * @return string with the toString() method definition in JAVA format - */ - def private generateToString() ''' - «IF !genTO.toStringIdentifiers.empty» - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - «val properties = genTO.toStringIdentifiers» - builder.append("«genTO.name» [«properties.get(0).fieldName»="); - builder.append(«properties.get(0).fieldName»); - «FOR i : 1..Type - * @return string with the type name (with or without package name) - */ - def private resolveName(Type type) { - GeneratorUtil.putTypeIntoImports(genTO, type, imports); - GeneratorUtil.getExplicitType(genTO, type, imports) - } - - def private fieldName(GeneratedProperty property) { - '''_«property.name»''' - } -} +/** + * Template for generating JAVA class. + */ +class ClassTemplate extends BaseTemplate { + + protected val List properties + protected val List finalProperties + protected val List parentProperties + protected val Iterable allProperties; + protected val Restrictions restrictions + + /** + * List of enumeration which are generated as JAVA enum type. + */ + protected val List enums + + /** + * List of constant instances which are generated as JAVA public static final attributes. + */ + protected val List consts + + /** + * List of generated types which are enclosed inside genType + */ + protected val List enclosedGeneratedTypes; + + + protected val GeneratedTransferObject genTO; + + /** + * Creates instance of this class with concrete genType. + * + * @param genType generated transfer object which will be transformed to JAVA class source code + */ + new(GeneratedTransferObject genType) { + super(genType) + this.genTO = genType + this.properties = genType.properties + this.finalProperties = GeneratorUtil.resolveReadOnlyPropertiesFromTO(genTO.properties) + this.parentProperties = GeneratorUtil.getPropertiesOfAllParents(genTO) + this.restrictions = genType.restrictions + + var List sorted = new ArrayList(); + sorted.addAll(properties); + sorted.addAll(parentProperties); + Collections.sort(sorted, new PropertyComparator()); + + this.allProperties = sorted + this.enums = genType.enumerations + this.consts = genType.constantDefinitions + this.enclosedGeneratedTypes = genType.enclosedTypes + } + + + /** + * Generates JAVA class source code (class body only). + * + * @return string with JAVA class body source code + */ + def CharSequence generateAsInnerClass() { + return generateBody(true) + } + + + override protected body() { + generateBody(false); + } + + /** + * Template method which generates class body. + * + * @param isInnerClass boolean value which specify if generated class is|isn't inner + * @return string with class source code in JAVA format + */ + def protected generateBody(boolean isInnerClass) ''' + «type.comment.asJavadoc» + «generateClassDeclaration(isInnerClass)» { + «suidDeclaration» + «innerClassesDeclarations» + «enumDeclarations» + «constantsDeclarations» + «generateFields» + + «constructors» + + «defaultInstance» + + «FOR field : properties SEPARATOR "\n"» + «field.getterMethod» + «IF !field.readOnly» + «field.setterMethod» + «ENDIF» + «ENDFOR» + + «generateHashCode» + + «generateEquals» + + «generateToString(genTO.toStringIdentifiers)» + + «generateGetLength» + + } + ''' + + + /** + * Template method which generates inner classes inside this interface. + * + * @return string with the source code for inner classes in JAVA format + */ + def protected innerClassesDeclarations() ''' + «IF !enclosedGeneratedTypes.empty» + «FOR innerClass : enclosedGeneratedTypes SEPARATOR "\n"» + «IF (innerClass instanceof GeneratedTransferObject)» + «val classTemplate = new ClassTemplate(innerClass as GeneratedTransferObject)» + «classTemplate.generateAsInnerClass» + + «ENDIF» + «ENDFOR» + «ENDIF» + ''' + + + def protected constructors() ''' + «IF genTO.unionType» + «genUnionConstructor» + «ELSE» + «allValuesConstructor» + «ENDIF» + «IF !allProperties.empty» + «copyConstructor» + «ENDIF» + «IF properties.empty && !parentProperties.empty » + «parentConstructor» + «ENDIF» + ''' + + def protected allValuesConstructor() ''' + «IF genTO.typedef && !allProperties.empty && allProperties.size == 1 && allProperties.get(0).name.equals("value")» + @«ConstructorProperties.importedName»("value") + «ENDIF» + public «type.name»(«allProperties.asArgumentsDeclaration») { + «IF false == parentProperties.empty» + super(«parentProperties.asArguments»); + «ENDIF» + «FOR p : allProperties» + «generateRestrictions(type, p.fieldName.toString, p.returnType)» + «ENDFOR» + «FOR p : properties» + this.«p.fieldName» = «p.fieldName»; + «ENDFOR» + } + ''' + + def protected genUnionConstructor() ''' + «FOR p : allProperties» + «val List other = new ArrayList(properties)» + «val added = other.remove(p)» + «genConstructor(p, other)» + «ENDFOR» + + ''' + + def protected genConstructor(GeneratedProperty property, GeneratedProperty... other) ''' + public «type.name»(«property.returnType.importedName + " " + property.name») { + «IF false == parentProperties.empty» + super(«parentProperties.asArguments»); + «ENDIF» + «generateRestrictions(type, property.fieldName.toString, property.returnType)» + this.«property.fieldName» = «property.name»; + «FOR p : other» + this.«p.fieldName» = null; + «ENDFOR» + } + ''' + + def protected copyConstructor() ''' + /** + * Creates a copy from Source Object. + * + * @param source Source object + */ + public «type.name»(«type.name» source) { + «IF false == parentProperties.empty» + super(source); + «ENDIF» + «FOR p : properties» + this.«p.fieldName» = source.«p.fieldName»; + «ENDFOR» + } + ''' + + def protected parentConstructor() ''' + /** + * Creates a new instance from «genTO.superType.importedName» + * + * @param source Source object + */ + public «type.name»(«genTO.superType.importedName» source) { + super(source); + } + ''' + + def protected defaultInstance() ''' + «IF genTO.typedef && !allProperties.empty && !genTO.unionType» + «val prop = allProperties.get(0)» + «IF !("org.opendaylight.yangtools.yang.binding.InstanceIdentifier".equals(prop.returnType.fullyQualifiedName))» + public static «genTO.name» getDefaultInstance(String defaultValue) { + «IF "byte[]".equals(prop.returnType.name)» + «BaseEncoding.importedName» baseEncoding = «BaseEncoding.importedName».base64(); + return new «genTO.name»(baseEncoding.decode(defaultValue)); + «ELSEIF "java.lang.String".equals(prop.returnType.fullyQualifiedName)» + return new «genTO.name»(defaultValue); + «ELSEIF allProperties.size > 1» + «bitsArgs» + «ELSE» + return new «genTO.name»(new «prop.returnType.importedName»(defaultValue)); + «ENDIF» + } + «ENDIF» + «ENDIF» + ''' + + def protected bitsArgs() ''' + «List.importedName»<«String.importedName»> properties = «Lists.importedName».newArrayList(«allProperties.propsAsArgs»); + if (!properties.contains(defaultValue)) { + throw new «IllegalArgumentException.importedName»("invalid default parameter"); + } + int i = 0; + return new «genTO.name»( + «FOR prop : allProperties SEPARATOR ","» + properties.get(i++).equals(defaultValue) ? new «Boolean.importedName»("true") : null + «ENDFOR» + ); + ''' + + def protected propsAsArgs(Iterable properties) ''' + «FOR prop : properties SEPARATOR ","» + "«prop.name»" + «ENDFOR» + ''' + + /** + * Template method which generates JAVA class declaration. + * + * @param isInnerClass boolean value which specify if generated class is|isn't inner + * @return string with class declaration in JAVA format + */ + def protected generateClassDeclaration(boolean isInnerClass) ''' + public« + IF (isInnerClass)»« + " static final "»« + ELSEIF (type.abstract)»« + " abstract "»« + ELSE»« + " "»« + ENDIF»class «type.name»« + IF (genTO.superType != null)»« + " extends "»«genTO.superType.importedName»« + ENDIF» + «IF (!type.implements.empty)»« + " implements "»« + FOR type : type.implements SEPARATOR ", "»« + type.importedName»« + ENDFOR»« + ENDIF + »''' + + /** + * Template method which generates JAVA enum type. + * + * @return string with inner enum source code in JAVA format + */ + def protected enumDeclarations() ''' + «IF !enums.empty» + «FOR e : enums SEPARATOR "\n"» + «val enumTemplate = new EnumTemplate(e)» + «enumTemplate.generateAsInnerClass» + «ENDFOR» + «ENDIF» + ''' + + def protected suidDeclaration() ''' + «IF genTO.SUID != null» + private static final long serialVersionUID = «genTO.SUID.value»L; + «ENDIF» + ''' + + /** + * Template method wich generates JAVA constants. + * + * @return string with constants in JAVA format + */ + def protected constantsDeclarations() ''' + «IF !consts.empty» + «FOR c : consts» + «IF c.name == TypeConstants.PATTERN_CONSTANT_NAME» + «val cValue = c.value» + «IF cValue instanceof List» + «val cValues = cValue as List» + private static final «List.importedName»<«Pattern.importedName»> «Constants.MEMBER_PATTERN_LIST» = new «ArrayList.importedName»<«Pattern.importedName»>(); + public static final «List.importedName» «TypeConstants.PATTERN_CONSTANT_NAME» = «Arrays.importedName».asList(« + FOR v : cValues SEPARATOR ", "»« + IF v instanceof String»"« + v as String»"« + ENDIF»« + ENDFOR»); + + «generateStaticInicializationBlock» + «ENDIF» + «ELSE» + public static final «c.type.importedName» «c.name» = «c.value»; + «ENDIF» + «ENDFOR» + «ENDIF» + ''' + + /** + * Template method which generates JAVA static initialization block. + * + * @return string with static initialization block in JAVA format + */ + def protected generateStaticInicializationBlock() ''' + static { + for (String regEx : «TypeConstants.PATTERN_CONSTANT_NAME») { + «Constants.MEMBER_PATTERN_LIST».add(Pattern.compile(regEx)); + } + } + ''' + + /** + * Template method which generates JAVA class attributes. + * + * @return string with the class attributes in JAVA format + */ + def protected generateFields() ''' + «IF !properties.empty» + «FOR f : properties» + «IF f.readOnly»final«ENDIF» private «f.returnType.importedName» «f.fieldName»; + «ENDFOR» + «ENDIF» + ''' + + + /** + * Template method which generates the method hashCode(). + * + * @return string with the hashCode() method definition in JAVA format + */ + def protected generateHashCode() ''' + «IF !genTO.hashCodeIdentifiers.empty» + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + «FOR property : genTO.hashCodeIdentifiers» + «IF property.returnType.name.contains("[")» + result = prime * result + ((«property.fieldName» == null) ? 0 : «Arrays.importedName».hashCode(«property.fieldName»)); + «ELSE» + result = prime * result + ((«property.fieldName» == null) ? 0 : «property.fieldName».hashCode()); + «ENDIF» + «ENDFOR» + return result; + } + «ENDIF» + ''' + + /** + * Template method which generates the method equals(). + * + * @return string with the equals() method definition in JAVA format + */ + def protected generateEquals() ''' + «IF !genTO.equalsIdentifiers.empty» + @Override + public boolean equals(java.lang.Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + «type.name» other = («type.name») obj; + «FOR property : genTO.equalsIdentifiers» + «val fieldName = property.fieldName» + if («fieldName» == null) { + if (other.«fieldName» != null) { + return false; + } + «IF property.returnType.name.contains("[")» + } else if(!«Arrays.importedName».equals(«fieldName», other.«fieldName»)) { + «ELSE» + } else if(!«fieldName».equals(other.«fieldName»)) { + «ENDIF» + return false; + } + «ENDFOR» + return true; + } + «ENDIF» + ''' + + def private generateGetLength() ''' + «IF restrictions != null && !(restrictions.lengthConstraints.empty)» + public static «List.importedName»<«Range.importedName»> getLength() { + final «List.importedName»<«Range.importedName»> result = new «ArrayList.importedName»<>(); + «FOR r : restrictions.lengthConstraints» + result.add(«Range.importedName».closed(«r.min», «r.max»)); + «ENDFOR» + return result; + } + «ENDIF» + ''' + + def private generateGetRange() ''' + «IF restrictions != null && !(restrictions.lengthConstraints.empty)» + public static «List.importedName»<«Range.importedName»> getLength() { + final «List.importedName»<«Range.importedName»> result = new «ArrayList.importedName»<>(); + «List.importedName»<«Range.importedName»<«Integer.importedName»>> lengthConstraints = new «ArrayList.importedName»<>(); + «FOR r : restrictions.lengthConstraints» + result.add(«Range.importedName».closed(«r.min», «r.max»)); + «ENDFOR» + return result; + } + «ENDIF» + ''' + +}