*/
package org.opendaylight.mdsal.binding.java.api.generator
+import static extension org.apache.commons.text.StringEscapeUtils.escapeJava;
+
+import com.google.common.base.MoreObjects
import com.google.common.collect.ImmutableMap
import com.google.common.collect.ImmutableSortedSet
+import com.google.common.collect.ImmutableList
import java.util.ArrayList
import java.util.Arrays
import java.util.Collection
import java.util.Map
import java.util.Objects
import java.util.Set
+import java.util.regex.Pattern
import org.opendaylight.mdsal.binding.model.api.ConcreteType
import org.opendaylight.mdsal.binding.model.api.GeneratedProperty
import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject
import org.opendaylight.mdsal.binding.model.api.GeneratedType
+import org.opendaylight.mdsal.binding.model.api.JavaTypeName
import org.opendaylight.mdsal.binding.model.api.MethodSignature
import org.opendaylight.mdsal.binding.model.api.Type
+import org.opendaylight.mdsal.binding.model.api.ParameterizedType
+import org.opendaylight.mdsal.binding.model.api.Restrictions
import org.opendaylight.mdsal.binding.model.util.ReferencedTypeImpl
import org.opendaylight.mdsal.binding.model.util.Types
-import org.opendaylight.mdsal.binding.model.util.generated.type.builder.GeneratedTOBuilderImpl
+import org.opendaylight.mdsal.binding.model.util.generated.type.builder.CodegenGeneratedTOBuilder
+import org.opendaylight.mdsal.binding.model.util.TypeConstants
import org.opendaylight.yangtools.concepts.Builder
import org.opendaylight.yangtools.yang.binding.Augmentable
import org.opendaylight.yangtools.yang.binding.AugmentationHolder
+import org.opendaylight.yangtools.yang.binding.CodeHelpers
import org.opendaylight.yangtools.yang.binding.DataObject
import org.opendaylight.yangtools.yang.binding.Identifiable
* @throws IllegalArgumentException if <code>genType</code> equals <code>null</code>
*/
new(GeneratedType genType) {
- super(genType)
+ super(new TopLevelJavaGeneratedType(builderName(genType), genType), genType)
this.properties = propertiesFromMethods(createMethods)
- addImport(Builder.simpleName, Builder.package.name)
+ addImport(Builder)
+ }
+
+ def static builderName(GeneratedType genType) {
+ val name = genType.identifier
+ name.createSibling(name.simpleName + "Builder")
}
/**
} else if (implementedIfc.fullyQualifiedName == Augmentable.name) {
for (m : Augmentable.methods) {
if (m.name == GET_AUGMENTATION_METHOD_NAME) {
- val fullyQualifiedName = m.returnType.name
- val pkg = fullyQualifiedName.package
- val name = fullyQualifiedName.name
- val tmpGenTO = new GeneratedTOBuilderImpl(pkg, name)
- val refType = new ReferencedTypeImpl(pkg, name)
- val generic = new ReferencedTypeImpl(type.packageName, type.name)
+ val identifier = JavaTypeName.create(m.returnType)
+ val tmpGenTO = new CodegenGeneratedTOBuilder(identifier)
+ val refType = new ReferencedTypeImpl(identifier)
+ val generic = new ReferencedTypeImpl(type.identifier)
val parametrizedReturnType = Types.parameterizedTypeFor(refType, generic)
tmpGenTO.addMethod(m.name).setReturnType(parametrizedReturnType)
- augmentField = tmpGenTO.toInstance.methodDefinitions.first.propertyFromGetter
+ augmentField = tmpGenTO.build.methodDefinitions.first.propertyFromGetter
}
}
}
elements.get(0)
}
- /**
- * Returns the name of the package from <code>fullyQualifiedName</code>.
- *
- * @param fullyQualifiedName string with fully qualified type name (package + type)
- * @return string with the package name
- */
- def private String getPackage(String fullyQualifiedName) {
- val lastDotIndex = fullyQualifiedName.lastIndexOf(Constants.DOT)
- return if (lastDotIndex == -1) "" else fullyQualifiedName.substring(0, lastDotIndex)
- }
-
- /**
- * Returns the name of tye type from <code>fullyQualifiedName</code>
- *
- * @param fullyQualifiedName string with fully qualified type name (package + type)
- * @return string with the name of the type
- */
- def private String getName(String fullyQualifiedName) {
- val lastDotIndex = fullyQualifiedName.lastIndexOf(Constants.DOT)
- return if (lastDotIndex == -1) fullyQualifiedName else fullyQualifiedName.substring(lastDotIndex + 1)
- }
-
/**
* Creates set of generated property instances from getter <code>methods</code>.
*
}
if (method.name.startsWith(prefix)) {
val fieldName = method.getName().substring(prefix.length()).toFirstLower
- val tmpGenTO = new GeneratedTOBuilderImpl("foo", "foo")
+ val tmpGenTO = new CodegenGeneratedTOBuilder(JavaTypeName.create("foo", "foo"))
tmpGenTO.addProperty(fieldName).setReturnType(method.returnType)
- return tmpGenTO.toInstance.properties.first
+ return tmpGenTO.build.properties.first
}
}
- override isLocalInnerClass(String importedTypePackageName) {
+ override isLocalInnerClass(JavaTypeName name) {
// Builders do not have inner types
return false;
}
«generateFields(false)»
+ «constantsDeclarations()»
+
«generateAugmentField(false)»
«generateConstructorsFromIfcs(type)»
«FOR impl : ifc.getAllIfcs»
«generateIfCheck(impl, done)»
«ENDFOR»
- if (!isValidArg) {
- throw new IllegalArgumentException(
- "expected one of: «ifc.getAllIfcs.toListOfNames» \n" +
- "but was: " + arg
- );
- }
+ «CodeHelpers.importedName».validValue(isValidArg, arg, "«ifc.getAllIfcs.toListOfNames»");
}
«ENDIF»
«ENDIF»
def private generateMethodFieldsFromComment(GeneratedType type) '''
/**
- *Set fields from given grouping argument. Valid argument is instance of one of following types:
+ * Set fields from given grouping argument. Valid argument is instance of one of following types:
* <ul>
«FOR impl : type.getAllIfcs»
* <li>«impl.fullyQualifiedName»</li>
«ENDIF»
'''
+ def private constantsDeclarations() '''
+ «FOR c : type.getConstantDefinitions»
+ «IF c.getName.startsWith(TypeConstants.PATTERN_CONSTANT_NAME)»
+ «val cValue = c.value as Map<String, String>»
+ «val String fieldSuffix = c.getName.substring(TypeConstants.PATTERN_CONSTANT_NAME.length)»
+ «IF cValue.size == 1»
+ private static final «Pattern.importedName» «Constants.MEMBER_PATTERN_LIST»«fieldSuffix» = «Pattern.importedName».compile("«cValue.keySet.get(0).escapeJava»");
+ private static final String «Constants.MEMBER_REGEX_LIST»«fieldSuffix» = "«cValue.values.get(0).escapeJava»";
+ «ELSE»
+ private static final «Pattern.importedName»[] «Constants.MEMBER_PATTERN_LIST»«fieldSuffix» = «CodeHelpers.importedName».compilePatterns(«ImmutableList.importedName».of(
+ «FOR v : cValue.keySet SEPARATOR ", "»"«v.escapeJava»"«ENDFOR»));
+ private static final String[] «Constants.MEMBER_REGEX_LIST»«fieldSuffix» = { «
+ FOR v : cValue.values SEPARATOR ", "»"«v.escapeJava»"«ENDFOR» };
+ «ENDIF»
+ «ELSE»
+ «emitConstant(c)»
+ «ENDIF»
+ «ENDFOR»
+ '''
+
+ def private generateCheckers(GeneratedProperty field, Restrictions restrictions, Type actualType) '''
+ «IF restrictions.rangeConstraint.present»
+ «AbstractRangeGenerator.forType(actualType).generateRangeChecker(field.name.toFirstUpper,
+ restrictions.rangeConstraint.get, this)»
+ «ENDIF»
+ «IF restrictions.lengthConstraint.present»
+ «LengthGenerator.generateLengthChecker(field.fieldName.toString, actualType, restrictions.lengthConstraint.get, this)»
+ «ENDIF»
+ '''
+
+ def private checkArgument(GeneratedProperty property, Restrictions restrictions, Type actualType) '''
+ «IF restrictions.getRangeConstraint.isPresent»
+ «IF actualType instanceof ConcreteType»
+ «AbstractRangeGenerator.forType(actualType).generateRangeCheckerCall(property.getName.toFirstUpper, "value")»
+ «ELSE»
+ «AbstractRangeGenerator.forType(actualType).generateRangeCheckerCall(property.getName.toFirstUpper, "value.getValue()")»
+ «ENDIF»
+ «ENDIF»
+ «IF restrictions.getLengthConstraint.isPresent»
+ «IF actualType instanceof ConcreteType»
+ «LengthGenerator.generateLengthCheckerCall(property.fieldName.toString, "value")»
+ «ELSE»
+ «LengthGenerator.generateLengthCheckerCall(property.fieldName.toString, "value.getValue()")»
+ «ENDIF»
+ «ENDIF»
+
+ «val fieldUpperCase = property.fieldName.toString.toUpperCase()»
+ «FOR currentConstant : type.getConstantDefinitions»
+ «IF currentConstant.getName.startsWith(TypeConstants.PATTERN_CONSTANT_NAME)
+ && fieldUpperCase.equals(currentConstant.getName.substring(TypeConstants.PATTERN_CONSTANT_NAME.length))»
+ «CodeHelpers.importedName».checkPattern(value, «Constants.MEMBER_PATTERN_LIST»«property.fieldName», «Constants.MEMBER_REGEX_LIST»«property.fieldName»);
+ «ENDIF»
+ «ENDFOR»
+ '''
+
+ def private Restrictions restrictionsForSetter(Type actualType) {
+ if (actualType instanceof GeneratedType) {
+ return null;
+ }
+ return actualType.restrictions;
+ }
+
+ def private generateListSetter(GeneratedProperty field, Type actualType) '''
+ «val restrictions = restrictionsForSetter(actualType)»
+ «IF restrictions !== null»
+ «generateCheckers(field, restrictions, actualType)»
+ «ENDIF»
+ public «type.getName»Builder set«field.getName.toFirstUpper»(final «field.returnType.importedName» values) {
+ «IF restrictions !== null»
+ if (values != null) {
+ for («actualType.getFullyQualifiedName» value : values) {
+ «checkArgument(field, restrictions, actualType)»
+ }
+ }
+ «ENDIF»
+ this.«field.fieldName.toString» = values;
+ return this;
+ }
+
+ '''
+
+ def private generateSetter(GeneratedProperty field, Type actualType) '''
+ «val restrictions = restrictionsForSetter(actualType)»
+ «IF restrictions !== null»
+ «generateCheckers(field, restrictions, actualType)»
+ «ENDIF»
+
+ public «type.getName»Builder set«field.getName.toFirstUpper»(final «field.returnType.importedName» value) {
+ «IF restrictions !== null»
+ if (value != null) {
+ «checkArgument(field, restrictions, actualType)»
+ }
+ «ENDIF»
+ this.«field.fieldName.toString» = value;
+ return this;
+ }
+ '''
+
+ private def Type getActualType(ParameterizedType ptype) {
+ return ptype.getActualTypeArguments.get(0)
+ }
+
/**
* Template method which generates setter methods
*
* @return string with the setter methods
*/
def private generateSetters() '''
- «FOR field : properties SEPARATOR '\n'»
- «/* FIXME: generate checkers as simple blocks and embed them directly in setters */»
- «val restrictions = field.returnType.restrictions»
- «IF !(field.returnType instanceof GeneratedType) && restrictions !== null»
- «IF restrictions.rangeConstraint.present»
- «val rangeGenerator = AbstractRangeGenerator.forType(field.returnType)»
- «rangeGenerator.generateRangeChecker(field.name.toFirstUpper, restrictions.rangeConstraint.get)»
-
- «ENDIF»
- «IF restrictions.lengthConstraint.present»
- «LengthGenerator.generateLengthChecker(field.fieldName.toString, field.returnType, restrictions.lengthConstraint.get)»
-
- «ENDIF»
- «ENDIF»
- public «type.name»«BUILDER» set«field.name.toFirstUpper»(final «field.returnType.importedName» value) {
- «IF !(field.returnType instanceof GeneratedType) && restrictions !== null»
- «IF restrictions !== null && (restrictions.rangeConstraint.present || restrictions.lengthConstraint.present)»
- if (value != null) {
- «IF restrictions.rangeConstraint.present»
- «val rangeGenerator = AbstractRangeGenerator.forType(field.returnType)»
- «IF field.returnType instanceof ConcreteType»
- «rangeGenerator.generateRangeCheckerCall(field.name.toFirstUpper, "value")»
- «ELSE»
- «rangeGenerator.generateRangeCheckerCall(field.name.toFirstUpper, "value.getValue()")»
- «ENDIF»
- «ENDIF»
- «IF restrictions.lengthConstraint.present»
- «IF field.returnType instanceof ConcreteType»
- «LengthGenerator.generateLengthCheckerCall(field.fieldName.toString, "value")»
- «ELSE»
- «LengthGenerator.generateLengthCheckerCall(field.fieldName.toString, "value.getValue()")»
- «ENDIF»
- «ENDIF»
- }
- «ENDIF»
+ «FOR property : properties»
+ «IF property.returnType instanceof ParameterizedType
+ && (property.returnType as ParameterizedType).rawType.equals(Types.LIST_TYPE)»
+ «generateListSetter(property, getActualType(property.returnType as ParameterizedType))»
+ «ELSE»
+ «generateSetter(property, property.returnType)»
«ENDIF»
- this.«field.fieldName» = value;
- return this;
- }
«ENDFOR»
- «IF augmentField !== null»
+ «IF augmentField !== null»
public «type.name»«BUILDER» add«augmentField.name.toFirstUpper»(«Class.importedName»<? extends «augmentField.returnType.importedName»> augmentationType, «augmentField.returnType.importedName» augmentationValue) {
if (augmentationValue == null) {
return remove«augmentField.name.toFirstUpper»(augmentationType);
@SuppressWarnings("unchecked")
«IF addOverride»@Override«ENDIF»
public <E extends «augmentField.returnType.importedName»> E get«augmentField.name.toFirstUpper»(«Class.importedName»<E> augmentationType) {
- if (augmentationType == null) {
- throw new IllegalArgumentException("Augmentation Type reference cannot be NULL!");
- }
- return (E) «augmentField.name».get(augmentationType);
+ return (E) «augmentField.name».get(«CodeHelpers.importedName».nonNullValue(augmentationType, "augmentationType"));
}
«ENDIF»
'''
'''
def override generateToString(Collection<GeneratedProperty> properties) '''
- «IF !(properties === null)»
+ «IF properties !== null»
@Override
public «String.importedName» toString() {
- «String.importedName» name = "«type.name» [";
- «StringBuilder.importedName» builder = new «StringBuilder.importedName» (name);
- «FOR property : properties SEPARATOR "\n builder.append(\", \");\n}" AFTER " }\n"»
- if («property.fieldName» != null) {
- builder.append("«property.fieldName»=");
- «IF property.returnType.name.contains("[")»
- builder.append(«Arrays.importedName».toString(«property.fieldName»));
- «ELSE»
- builder.append(«property.fieldName»);
- «ENDIF»
+ final «MoreObjects.importedName».ToStringHelper helper = «MoreObjects.importedName».toStringHelper("«type.name»");
+ «FOR property : properties»
+ «CodeHelpers.importedName».appendValue(helper, "«property.fieldName»", «property.fieldName»);
«ENDFOR»
«IF augmentField !== null»
- «IF !properties.empty»
- «««Append comma separator only if it's not there already from previous operation»»»
-final int builderLength = builder.length();
- final int builderAdditionalLength = builder.substring(name.length(), builderLength).length();
- if (builderAdditionalLength > 2 && !builder.substring(builderLength - 2, builderLength).equals(", ")) {
- builder.append(", ");
- }
- «ENDIF»
- builder.append("«augmentField.name»=");
- builder.append(«augmentField.name».values());«"\n"»
- return builder.append(']').toString();
- «ELSE»
- «IF properties.empty»
- return builder.append(']').toString();
- «ELSE»
- return builder.append(']').toString();
- «ENDIF»
+ «CodeHelpers.importedName».appendValue(helper, "«augmentField.name»", «augmentField.name».values());
«ENDIF»
+ return helper.toString();
}
«ENDIF»
'''