genCtx.get(module).addChildNodeType(node, genType);
groupingsToGenTypes(module, ((DataNodeContainer) node).getGroupings());
processUsesAugments((DataNodeContainer) node, module);
+ if (node.isAddedByUses() || node.isAugmenting())
+ genType.setSuitableForBoxing(false);
}
return genType;
}
+ private boolean hasWhenOrMustConstraints(final SchemaNode node) {
+ boolean hasWhenCondition;
+ boolean hasMustConstraints;
+
+ if (node instanceof ContainerSchemaNode) {
+ ContainerSchemaNode contNode = (ContainerSchemaNode)node;
+ hasWhenCondition = contNode.getConstraints().getWhenCondition() != null;
+ hasMustConstraints = !isNullOrEmpty(contNode.getConstraints().getMustConstraints());
+
+ if (hasWhenCondition || hasMustConstraints)
+ return true;
+ }
+ return false;
+ }
+
private void containerToGenType(final Module module, final String basePackageName,
final GeneratedTypeBuilder parent, final GeneratedTypeBuilder childOf, final ContainerSchemaNode node) {
final GeneratedTypeBuilder genType = processDataSchemaNode(module, basePackageName, childOf, node);
+
if (genType != null) {
constructGetter(parent, node.getQName().getLocalName(), node.getDescription(), genType);
resolveDataSchemaNodes(module, basePackageName, genType, genType, node.getChildNodes());
+
+ final String parentName = parent.getName();
+ final String childOfName = childOf.getName();
+
+ if (parent != null && !parent.getName().contains("Data"))
+ genType.setParentType(parent);
+ genType.setSuitableForBoxing(hasOnlyOneChild(node) && !hasWhenOrMustConstraints(node));
+
+ if (parentName.equals(childOfName))
+ genType.setSuitableForBoxing(false);
}
}
+ private boolean hasOnlyOneChild(final ContainerSchemaNode contNode) {
+ if (!isNullOrEmpty(contNode.getChildNodes()) && contNode.getChildNodes().size() == 1)
+ return true;
+ return false;
+ }
+
private void listToGenType(final Module module, final String basePackageName, final GeneratedTypeBuilder parent,
final GeneratedTypeBuilder childOf, final ListSchemaNode node) {
final GeneratedTypeBuilder genType = processDataSchemaNode(module, basePackageName, childOf, node);
+
if (genType != null) {
+ if (!parent.getName().equals(childOf) && !parent.getName().contains("Data")) {
+ genType.setParentType(parent);
+ }
constructGetter(parent, node.getQName().getLocalName(), node.getDescription(), Types.listTypeFor(genType));
final List<String> listKeys = listKeys(node);
if (targetTypeBuilder == null) {
throw new NullPointerException("Target type not yet generated: " + targetSchemaNode);
}
+ targetTypeBuilder.setSuitableForBoxing(false);
if (!(targetSchemaNode instanceof ChoiceNode)) {
String packageName = augmentPackageName;
constructGetter(parent, choiceNode.getQName().getLocalName(), choiceNode.getDescription(),
choiceTypeBuilder);
choiceTypeBuilder.addImplementsType(typeForClass(DataContainer.class));
+ choiceTypeBuilder.setParentType(parent);
genCtx.get(module).addChildNodeType(choiceNode, choiceTypeBuilder);
generateTypesFromChoiceCases(module, basePackageName, choiceTypeBuilder.toInstance(), choiceNode);
}
return values;
}
+ @Override
+ public boolean isSuitableForBoxing() {
+ return false;
+ }
+
@Override
public List<AnnotationType> getAnnotations() {
return annotations;
public String getModuleName() {
return moduleName;
}
+
}
}
public String getModuleName() {
return moduleName;
}
+
+ @Override
+ public boolean isSuitableForBoxing() {
+ return false;
+ }
}
}
package org.opendaylight.yangtools.binding.generator.util.generated.type.builder;
import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder;
import org.opendaylight.yangtools.yang.common.QName;
private String reference;
private String moduleName;
private Iterable<QName> schemaPath;
+ private boolean isSuitableForBoxing;
+ private GeneratedTypeBuilder parentType;
public GeneratedTypeBuilderImpl(final String packageName, final String name) {
super(packageName, name);
this.reference = reference;
}
+ @Override
+ public void setSuitableForBoxing(boolean value) {
+ this.isSuitableForBoxing = value;
+ }
+
+ @Override
+ public void setParentType(GeneratedTypeBuilder parent) {
+ this.parentType = parent;
+ }
+
+ @Override
+ public Type getParent() {
+ return this.parentType;
+ }
+
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
private final String reference;
private final String moduleName;
private final Iterable<QName> schemaPath;
+ private final boolean isSuitableForBoxing;
+ private final GeneratedTypeBuilder parentType;
public GeneratedTypeImpl(GeneratedTypeBuilderImpl builder) {
super(builder);
this.reference = builder.reference;
this.moduleName = builder.moduleName;
this.schemaPath = builder.schemaPath;
+ this.isSuitableForBoxing = builder.isSuitableForBoxing;
+ this.parentType = builder.parentType;
}
@Override
public String getModuleName() {
return moduleName;
}
+
+ @Override
+ public boolean isSuitableForBoxing() {
+ return isSuitableForBoxing;
+ }
}
+
}
import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature
import org.opendaylight.yangtools.sal.binding.model.api.Type
import org.opendaylight.yangtools.yang.binding.Augmentable
+import org.opendaylight.yangtools.yang.binding.ChildOf
import org.opendaylight.yangtools.yang.binding.DataObject
import org.opendaylight.yangtools.yang.binding.Identifiable
«generateSetters»
- public «type.name» build() {
- return new «type.name»«IMPL»(this);
- }
+ «generateBuildMethod»
+
+ «generateBuildBoxedMethod»
private static final class «type.name»«IMPL» implements «type.name» {
}
'''
+ def private generateBuildMethod() '''
+ public «type.name» build() {
+ return new «type.name»«IMPL»(this);
+ }
+ '''
+
+ def private generateBuildBoxedMethod() {
+ if(type.suitableForBoxing && type.parentType != null && isContainerAndIsNotList(type)) {
+ val parentTypeBuilder = createParentTypeBuilder()
+ if (countMatches(parentTypeBuilder, "org") < 2) {
+ return '''
+ public «type.parentType.importedName» buildBoxed() {
+ return new «parentTypeBuilder»().set«type.name»(build()).build();
+ }
+ '''
+ }
+ }
+ return ''
+ }
+
+ def private int countMatches(String string, String subString) {
+ if (string.nullOrEmpty || subString.nullOrEmpty) {
+ return 0
+ }
+ var int count = 0;
+ var int idx = 0;
+ while ((idx = string.indexOf(subString, idx)) != -1) {
+ count = count + 1;
+ idx = idx + subString.length();
+ }
+ return count;
+ }
+
+ def private createParentTypeBuilder() {
+ return type.parentType.packageName + "." + type.parentType.importedName + "Builder"
+ }
+
+ def private boolean isContainerAndIsNotList(GeneratedType type) {
+ val isList = implementsIfc(type, Types.parameterizedTypeFor(Types.typeForClass(Identifiable), type))
+ val implementsChildOf = implementsIfc(type, Types.parameterizedTypeFor(Types.typeForClass(ChildOf), type))
+
+ if (implementsChildOf && !isList) {
+ return true
+ }
+ return false;
+ }
+
/**
* Generate default constructor and constructor for every implemented interface from uses statements.
*/
--- /dev/null
+
+module mod-box {
+ yang-version 1;
+ namespace "urn:opendaylight:mod:box";
+ prefix "box";
+
+ revision 2014-08-05 {
+ }
+
+ container cont1 {
+ choice choice1 {
+ case case1 {
+ container cont2 {
+ leaf leaf1 {
+ type string;
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * 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
+ */
+package org.opendaylight.yangtools.sal.binding.model.api;
+
+/**
+ * Implementing this interface allows an object to hold information about that if
+ * is generated type suitable for boxing.
+ *
+ * Example:
+ * choice foo-choice {
+ * case foo-case {
+ * container foo {
+ * ...
+ * }
+ * }
+ * }
+ *
+ * Suitable type have to implements ChildOf<T>, where !(T instanceof Identifiable) and
+ * T does not place any structural requirements (must/when) on existence/value Foo.
+ */
+public interface BoxableType {
+
+ /**
+ * Check if generated type is suitable for boxing.
+ *
+ * @return true if generated type is suitable for boxing, false otherwise.
+ */
+ boolean isSuitableForBoxing();
+}
* definitions MUST be public, so there is no need to specify the scope of
* visibility.
*/
-public interface GeneratedType extends Type, DocumentedType {
+public interface GeneratedType extends Type, DocumentedType, BoxableType {
/**
* Returns the parent type if Generated Type is defined as enclosing type,
/**
* Generated Type Builder interface is helper interface for building and
* defining the GeneratedType.
- *
+ *
* @see GeneratedType
*/
public interface GeneratedTypeBuilder extends GeneratedTypeBuilderBase<GeneratedTypeBuilder> {
/**
* Returns the <code>new</code> <i>immutable</i> instance of Generated Type.
- *
+ *
* @return the <code>new</code> <i>immutable</i> instance of Generated Type.
*/
GeneratedType toInstance();
+ /**
+ * Set true if generated type is suitable for boxing, false otherwise.
+ *
+ * @param value
+ */
+ public void setSuitableForBoxing(boolean value);
+
+ /**
+ * Set parent for current generated type.
+ *
+ * @param parent
+ */
+ public void setParentType(GeneratedTypeBuilder parent);
}
package org.opendaylight.yangtools.sal.binding.model.api.type.builder;
import java.util.List;
-
import org.opendaylight.yangtools.sal.binding.model.api.Constant;
import org.opendaylight.yangtools.sal.binding.model.api.Type;
import org.opendaylight.yangtools.yang.common.QName;