*.iml
.idea
bin
-**/src/main/xtend-gen
+xtend-gen
target
<plugin>
<groupId>org.eclipse.xtend</groupId>
<artifactId>xtend-maven-plugin</artifactId>
- <executions>
- <execution>
- <goals>
- <goal>compile</goal>
- </goals>
- <configuration>
- <outputDirectory>${basedir}/src/main/xtend-gen</outputDirectory>
- </configuration>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <artifactId>maven-clean-plugin</artifactId>
- <configuration>
- <filesets>
- <fileset>
- <directory>${basedir}/src/main/xtend-gen</directory>
- <includes>
- <include>**</include>
- </includes>
- </fileset>
- </filesets>
- </configuration>
</plugin>
</plugins>
</build>
import static org.opendaylight.yangtools.binding.generator.util.Types.typeForClass;
import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findDataSchemaNode;
import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findNodeInSchemaContext;
-import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findOriginal;
import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findParentModule;
+import com.google.common.base.Splitter;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Sets;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
-
import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil;
import org.opendaylight.yangtools.binding.generator.util.BindingTypes;
import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl;
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DerivableSchemaNode;
import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Splitter;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Sets;
-
public class BindingGeneratorImpl implements BindingGenerator {
private static final Logger LOG = LoggerFactory.getLogger(BindingGeneratorImpl.class);
return genType;
}
- private void containerToGenType(final Module module, final String basePackageName, final GeneratedTypeBuilder parent,
- final GeneratedTypeBuilder childOf, final ContainerSchemaNode node) {
+ 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);
* information about base of identity
*
*/
- private void identityToGenType(final Module module, final String basePackageName, final IdentitySchemaNode identity,
- final SchemaContext context) {
+ private void identityToGenType(final Module module, final String basePackageName,
+ final IdentitySchemaNode identity, final SchemaContext context) {
if (identity == null) {
return;
}
final String packageName = packageNameForGeneratedType(basePackageName, identity.getPath());
final String genTypeName = BindingMapping.getClassName(identity.getQName());
- final GeneratedTOBuilder newType = new GeneratedTOBuilderImpl(packageName, genTypeName);
+ final GeneratedTOBuilderImpl newType = new GeneratedTOBuilderImpl(packageName, genTypeName);
final IdentitySchemaNode baseIdentity = identity.getBaseIdentity();
if (baseIdentity == null) {
final GeneratedTOBuilderImpl gto = new GeneratedTOBuilderImpl(BaseIdentity.class.getPackage().getName(),
newType.setExtendsType(gto.toInstance());
} else {
final Module baseIdentityParentModule = SchemaContextUtil.findParentModule(context, baseIdentity);
- final String returnTypePkgName = BindingMapping.getRootPackageName(module.getQNameModule());
+ final String returnTypePkgName = BindingMapping.getRootPackageName(baseIdentityParentModule
+ .getQNameModule());
final String returnTypeName = BindingMapping.getClassName(baseIdentity.getQName());
final GeneratedTransferObject gto = new GeneratedTOBuilderImpl(returnTypePkgName, returnTypeName)
.toInstance();
}
newType.setAbstract(true);
newType.addComment(identity.getDescription());
+ newType.setDescription(identity.getDescription());
+ newType.setReference(identity.getReference());
+ newType.setModuleName(module.getName());
+ newType.setSchemaPath(identity.getPath().getPathFromRoot());
+
final QName qname = identity.getQName();
qnameConstant(newType, BindingMapping.QNAME_STATIC_FIELD_NAME, qname);
genCtx.get(module).addIdentityType(identity.getQName(), newType);
}
- private static Constant qnameConstant(final GeneratedTypeBuilderBase<?> toBuilder, final String constantName, final QName name) {
+ private static Constant qnameConstant(final GeneratedTypeBuilderBase<?> toBuilder, final String constantName,
+ final QName name) {
StringBuilder sb = new StringBuilder("org.opendaylight.yangtools.yang.common.QName");
sb.append(".create(");
sb.append('"');
&& (enumTypeDef.getQName().getLocalName() != null)) {
final String enumerationName = BindingMapping.getClassName(enumName);
final EnumBuilder enumBuilder = typeBuilder.addEnumeration(enumerationName);
+ enumBuilder.setDescription(enumTypeDef.getDescription());
enumBuilder.updateEnumPairsFromEnumTypeDef(enumTypeDef);
return enumBuilder;
}
checkArgument(module != null, "Module reference cannot be NULL.");
final String packageName = BindingMapping.getRootPackageName(module.getQNameModule());
final String moduleName = BindingMapping.getClassName(module.getName()) + postfix;
- return new GeneratedTypeBuilderImpl(packageName, moduleName);
+
+ final GeneratedTypeBuilderImpl moduleBuilder = new GeneratedTypeBuilderImpl(packageName, moduleName);
+ moduleBuilder.setDescription(module.getDescription());
+ moduleBuilder.setReference(module.getReference());
+ moduleBuilder.setModuleName(moduleName);
+
+ return moduleBuilder;
}
/**
* @throws IllegalStateException
* if augment target path is null
*/
- private void augmentationToGenTypes(final String augmentPackageName, final AugmentationSchema augSchema, final Module module) {
+ private void augmentationToGenTypes(final String augmentPackageName, final AugmentationSchema augSchema,
+ final Module module) {
checkArgument(augmentPackageName != null, "Package Name cannot be NULL.");
checkArgument(augSchema != null, "Augmentation Schema cannot be NULL.");
checkState(augSchema.getTargetPath() != null,
targetSchemaNode = findDataSchemaNode(schemaContext, targetPath);
if (targetSchemaNode instanceof DataSchemaNode && ((DataSchemaNode) targetSchemaNode).isAddedByUses()) {
- targetSchemaNode = findOriginal((DataSchemaNode) targetSchemaNode, schemaContext);
+ if (targetSchemaNode instanceof DerivableSchemaNode) {
+ targetSchemaNode = ((DerivableSchemaNode) targetSchemaNode).getOriginal().orNull();
+ }
if (targetSchemaNode == null) {
- throw new NullPointerException("Failed to find target node from grouping in augmentation " + augSchema
+ throw new IllegalStateException("Failed to find target node from grouping in augmentation " + augSchema
+ " in module " + module.getName());
}
}
}
}
- private void usesAugmentationToGenTypes(final String augmentPackageName, final AugmentationSchema augSchema, final Module module,
- final UsesNode usesNode, final DataNodeContainer usesNodeParent) {
+ private void usesAugmentationToGenTypes(final String augmentPackageName, final AugmentationSchema augSchema,
+ final Module module, final UsesNode usesNode, final DataNodeContainer usesNodeParent) {
checkArgument(augmentPackageName != null, "Package Name cannot be NULL.");
checkArgument(augSchema != null, "Augmentation Schema cannot be NULL.");
checkState(augSchema.getTargetPath() != null,
* added to it.
*/
private GeneratedTypeBuilder augSchemaNodeToMethods(final Module module, final String basePackageName,
- final GeneratedTypeBuilder typeBuilder, final GeneratedTypeBuilder childOf, final Set<DataSchemaNode> schemaNodes) {
+ final GeneratedTypeBuilder typeBuilder, final GeneratedTypeBuilder childOf,
+ final Set<DataSchemaNode> schemaNodes) {
if ((schemaNodes != null) && (typeBuilder != null)) {
for (DataSchemaNode schemaNode : schemaNodes) {
if (!schemaNode.isAugmenting()) {
* <li>if <code>choiceNode</code> is null</li>
* </ul>
*/
- private void choiceToGeneratedType(final Module module, final String basePackageName, final GeneratedTypeBuilder parent,
- final ChoiceNode choiceNode) {
+ private void choiceToGeneratedType(final Module module, final String basePackageName,
+ final GeneratedTypeBuilder parent, final ChoiceNode choiceNode) {
checkArgument(basePackageName != null, "Base Package Name cannot be NULL.");
checkArgument(choiceNode != null, "Choice Schema Node cannot be NULL.");
* <li>if <code>caseNodes</code> equals null</li>
* </ul>
*/
- private void generateTypesFromChoiceCases(final Module module, final String basePackageName, final Type refChoiceType,
- final ChoiceNode choiceNode) {
+ private void generateTypesFromChoiceCases(final Module module, final String basePackageName,
+ final Type refChoiceType, final ChoiceNode choiceNode) {
checkArgument(basePackageName != null, "Base Package Name cannot be NULL.");
checkArgument(refChoiceType != null, "Referenced Choice Type cannot be NULL.");
checkArgument(choiceNode != null, "ChoiceNode cannot be NULL.");
SchemaNode targetSchemaNode = findDataSchemaNode(schemaContext, targetPath);
if (targetSchemaNode instanceof DataSchemaNode
&& ((DataSchemaNode) targetSchemaNode).isAddedByUses()) {
- targetSchemaNode = findOriginal((DataSchemaNode) targetSchemaNode, schemaContext);
+ if (targetSchemaNode instanceof DerivableSchemaNode) {
+ targetSchemaNode = ((DerivableSchemaNode) targetSchemaNode).getOriginal().orNull();
+ }
if (targetSchemaNode == null) {
- throw new NullPointerException(
+ throw new IllegalStateException(
"Failed to find target node from grouping for augmentation " + augSchema
+ " in module " + module.getName());
}
parent = findDataSchemaNode(schemaContext, sp.getParent());
}
GeneratedTypeBuilder childOfType = findChildNodeByPath(parent.getPath());
+ if (childOfType == null) {
+ childOfType = findGroupingByPath(parent.getPath());
+ }
resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, childOfType, caseChildNodes);
}
}
* <li>if <code>augmentedNodes</code> is null</li>
* </ul>
*/
- private void generateTypesFromAugmentedChoiceCases(final Module module, final String basePackageName, final Type targetType,
- final ChoiceNode targetNode, final Set<DataSchemaNode> augmentedNodes) {
+ private void generateTypesFromAugmentedChoiceCases(final Module module, final String basePackageName,
+ final Type targetType, final ChoiceNode targetNode, final Set<DataSchemaNode> augmentedNodes) {
checkArgument(basePackageName != null, "Base Package Name cannot be NULL.");
checkArgument(targetType != null, "Referenced Choice Type cannot be NULL.");
checkArgument(augmentedNodes != null, "Set of Choice Case Nodes cannot be NULL.");
}
((TypeProviderImpl) typeProvider).putReferencedType(leaf.getPath(), returnType);
} else if (typeDef instanceof UnionType) {
- genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, leaf);
+ genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, leaf, parentModule);
if (genTOBuilder != null) {
returnType = createReturnTypeForUnion(genTOBuilder, typeDef, typeBuilder, parentModule);
}
} else if (typeDef instanceof BitsTypeDefinition) {
- genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, leaf);
+ genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, leaf, parentModule);
if (genTOBuilder != null) {
returnType = new ReferencedTypeImpl(genTOBuilder.getPackageName(), genTOBuilder.getName());
}
return returnType;
}
- private void processContextRefExtension(final LeafSchemaNode leaf, final MethodSignatureBuilder getter, final Module module) {
+ private void processContextRefExtension(final LeafSchemaNode leaf, final MethodSignatureBuilder getter,
+ final Module module) {
for (UnknownSchemaNode node : leaf.getUnknownSchemaNodes()) {
final QName nodeType = node.getNodeType();
if ("context-reference".equals(nodeType.getLocalName())) {
* <li>true - other cases</li>
* </ul>
*/
- private boolean resolveLeafSchemaNodeAsProperty(final GeneratedTOBuilder toBuilder, final LeafSchemaNode leaf, final Type returnType,
- final boolean isReadOnly) {
+ private boolean resolveLeafSchemaNodeAsProperty(final GeneratedTOBuilder toBuilder, final LeafSchemaNode leaf,
+ final Type returnType, final boolean isReadOnly) {
if (returnType == null) {
return false;
}
returnType = new ReferencedTypeImpl(enumBuilder.getPackageName(), enumBuilder.getName());
((TypeProviderImpl) typeProvider).putReferencedType(node.getPath(), returnType);
} else if (typeDef instanceof UnionType) {
- final GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, node);
+ final GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, node, parentModule);
if (genTOBuilder != null) {
returnType = createReturnTypeForUnion(genTOBuilder, typeDef, typeBuilder, parentModule);
}
} else if (typeDef instanceof BitsTypeDefinition) {
- final GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, node);
+ final GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, node, parentModule);
returnType = new ReferencedTypeImpl(genTOBuilder.getPackageName(), genTOBuilder.getName());
} else {
final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
final GeneratedTypeBuilder typeBuilder, final Module parentModule) {
final GeneratedTOBuilderImpl returnType = new GeneratedTOBuilderImpl(genTOBuilder.getPackageName(),
genTOBuilder.getName());
+
+ returnType.setDescription(typeDef.getDescription());
+ returnType.setReference(typeDef.getReference());
+ returnType.setSchemaPath(typeDef.getPath().getPathFromRoot());
+ returnType.setModuleName(parentModule.getName());
+
genTOBuilder.setTypedef(true);
genTOBuilder.setIsUnion(true);
((TypeProviderImpl) typeProvider).addUnitsToGenTO(genTOBuilder, typeDef.getUnits());
* parent type (can be null)
* @return generated type builder <code>schemaNode</code>
*/
- private GeneratedTypeBuilder addDefaultInterfaceDefinition(final String packageName, final SchemaNode schemaNode, final Type parent) {
+ private GeneratedTypeBuilder addDefaultInterfaceDefinition(final String packageName, final SchemaNode schemaNode,
+ final Type parent) {
final GeneratedTypeBuilder it = addRawInterfaceDefinition(packageName, schemaNode, "");
if (parent == null) {
it.addImplementsType(DATA_OBJECT);
* </ul>
*
*/
- private GeneratedTypeBuilder addRawInterfaceDefinition(final String packageName, final SchemaNode schemaNode, final String prefix) {
+ private GeneratedTypeBuilder addRawInterfaceDefinition(final String packageName, final SchemaNode schemaNode,
+ final String prefix) {
checkArgument(schemaNode != null, "Data Schema Node cannot be NULL.");
checkArgument(packageName != null, "Package Name for Generated Type cannot be NULL.");
checkArgument(schemaNode.getQName() != null, "QName for Data Schema Node cannot be NULL.");
final GeneratedTypeBuilderImpl newType = new GeneratedTypeBuilderImpl(packageName, genTypeName);
qnameConstant(newType, BindingMapping.QNAME_STATIC_FIELD_NAME, schemaNode.getQName());
newType.addComment(schemaNode.getDescription());
+ newType.setDescription(schemaNode.getDescription());
+ newType.setReference(schemaNode.getReference());
+ newType.setSchemaPath(schemaNode.getPath().getPathFromRoot());
+
+ final Module module = findParentModule(schemaContext, schemaNode);
+ newType.setModuleName(module.getName());
+
if (!genTypeBuilders.containsKey(packageName)) {
final Map<String, GeneratedTypeBuilder> builders = new HashMap<>();
builders.put(genTypeName, newType);
* @return method signature builder which represents the getter method of
* <code>interfaceBuilder</code>
*/
- private MethodSignatureBuilder constructGetter(final GeneratedTypeBuilder interfaceBuilder, final String schemaNodeName,
- final String comment, final Type returnType) {
+ private MethodSignatureBuilder constructGetter(final GeneratedTypeBuilder interfaceBuilder,
+ final String schemaNodeName, final String comment, final Type returnType) {
final MethodSignatureBuilder getMethod = interfaceBuilder
.addMethod(getterMethodName(schemaNodeName, returnType));
getMethod.setComment(comment);
* </ul>
*/
private void addSchemaNodeToListBuilders(final String basePackageName, final DataSchemaNode schemaNode,
- final GeneratedTypeBuilder typeBuilder, final GeneratedTOBuilder genTOBuilder, final List<String> listKeys, final Module module) {
+ final GeneratedTypeBuilder typeBuilder, final GeneratedTOBuilder genTOBuilder, final List<String> listKeys,
+ final Module module) {
checkArgument(schemaNode != null, "Data Schema Node cannot be NULL.");
checkArgument(typeBuilder != null, "Generated Type Builder cannot be NULL.");
}
}
- private void typeBuildersToGenTypes(final Module module, final GeneratedTypeBuilder typeBuilder, final GeneratedTOBuilder genTOBuilder) {
+ private void typeBuildersToGenTypes(final Module module, final GeneratedTypeBuilder typeBuilder,
+ final GeneratedTOBuilder genTOBuilder) {
checkArgument(typeBuilder != null, "Generated Type Builder cannot be NULL.");
if (genTOBuilder != null) {
* @param leaf
* @return generated TO builder for <code>typeDef</code>
*/
- private GeneratedTOBuilder addTOToTypeBuilder(final TypeDefinition<?> typeDef, final GeneratedTypeBuilder typeBuilder,
- final DataSchemaNode leaf) {
+ private GeneratedTOBuilder addTOToTypeBuilder(final TypeDefinition<?> typeDef,
+ final GeneratedTypeBuilder typeBuilder, final DataSchemaNode leaf, final Module parentModule) {
final String classNameFromLeaf = BindingMapping.getClassName(leaf.getQName());
final List<GeneratedTOBuilder> genTOBuilders = new ArrayList<>();
final String packageName = typeBuilder.getFullyQualifiedName();
} else if (typeDef instanceof BitsTypeDefinition) {
genTOBuilders.add((((TypeProviderImpl) typeProvider)).provideGeneratedTOBuilderForBitsTypeDefinition(
- packageName, typeDef, classNameFromLeaf));
+ packageName, typeDef, classNameFromLeaf, parentModule.getName()));
}
if (genTOBuilders != null && !genTOBuilders.isEmpty()) {
for (GeneratedTOBuilder genTOBuilder : genTOBuilders) {
import static extension org.opendaylight.yangtools.sal.binding.generator.util.YangSchemaUtils.*
import java.util.ArrayList
+import org.opendaylight.yangtools.sal.binding.generator.util.DefaultSourceCodeGenerator
+import org.opendaylight.yangtools.sal.binding.generator.util.SourceCodeGeneratorFactory
+import org.opendaylight.yangtools.sal.binding.generator.util.SourceCodeGenerator
class TransformerGenerator extends AbstractTransformerGenerator {
private static val LOG = LoggerFactory.getLogger(TransformerGenerator)
val CtClass BINDING_CODEC
val CtClass ctQName
+ val SourceCodeGeneratorFactory sourceCodeGeneratorFactory = new SourceCodeGeneratorFactory();
+
public new(TypeResolver typeResolver, ClassPool pool) {
super(typeResolver, pool)
private def generateKeyTransformerFor(Class<? extends Object> inputType, GeneratedType typeSpec, ListSchemaNode node) {
try {
+ val SourceCodeGenerator sourceGenerator = sourceCodeGeneratorFactory.getInstance( null );
+
//log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
val properties = typeSpec.allProperties;
val ctCls = createClass(inputType.codecClassName) [
//staticField(Map,"AUGMENTATION_SERIALIZERS");
- staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
- staticField(it, IDENTITYREF_CODEC, BindingCodec)
- staticQNameField(node.QName);
+ staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec, sourceGenerator)
+ staticField(it, IDENTITYREF_CODEC, BindingCodec, sourceGenerator)
+ staticQNameField(node.QName, sourceGenerator);
implementsType(BINDING_CODEC)
method(Object, "toDomStatic", #[QName, Object]) [
modifiers = PUBLIC + FINAL + STATIC
- bodyChecked = '''
+ val body = '''
{
«QName.name» _resultName;
if($1 != null) {
return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
}
'''
+ setBodyChecked(body, sourceGenerator)
]
method(Object, "fromDomStatic", #[QName, Object]) [
modifiers = PUBLIC + FINAL + STATIC
- bodyChecked = '''
+ val body = '''
{
if($2 == null){
return null;
return _value;
}
'''
+ setBodyChecked(body, sourceGenerator)
]
method(Object, "serialize", Object) [
- bodyChecked = '''
+ val body = '''
{
java.util.Map.Entry _input = (java.util.Map.Entry) $1;
«QName.name» _localQName = («QName.name») _input.getKey();
return toDomStatic(_localQName,_keyValue);
}
'''
+ setBodyChecked(body, sourceGenerator)
]
method(Object, "deserialize", Object) [
- bodyChecked = '''
+ val body = '''
{
«QName.name» _qname = QNAME;
if($1 instanceof java.util.Map.Entry) {
return fromDomStatic(_qname,$1);
}
'''
+ setBodyChecked(body, sourceGenerator)
]
]
val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
+ sourceGenerator.outputGeneratedSource( ctCls )
LOG.debug("DOM Codec for {} was generated {}", inputType, ret)
return ret as Class<? extends BindingCodec<Map<QName,Object>, ?>>;
} catch (Exception e) {
private def Class<? extends BindingCodec<Object, Object>> generateCaseCodec(Class<?> inputType, GeneratedType type,
ChoiceCaseNode node) {
try {
+ val SourceCodeGenerator sourceGenerator = sourceCodeGeneratorFactory.getInstance( null );
+
//log.info("Generating DOM Codec for {} with {}, TCCL is: {}", inputType, inputType.classLoader,Thread.currentThread.contextClassLoader)
val ctCls = createClass(type.codecClassName) [
//staticField(Map,"AUGMENTATION_SERIALIZERS");
implementsType(BINDING_CODEC)
- staticQNameField(node.QName);
- staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
- staticField(it, AUGMENTATION_CODEC, BindingCodec)
- staticField(it, IDENTITYREF_CODEC, BindingCodec)
+ staticQNameField(node.QName, sourceGenerator);
+ staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec, sourceGenerator)
+ staticField(it, AUGMENTATION_CODEC, BindingCodec, sourceGenerator)
+ staticField(it, IDENTITYREF_CODEC, BindingCodec, sourceGenerator)
method(Object, "toDomStatic", #[QName, Object]) [
modifiers = PUBLIC + FINAL + STATIC
- bodyChecked = '''
+ val body = '''
{
«QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
java.util.List _childNodes = new java.util.ArrayList();
return ($r) _childNodes;
}
'''
+ setBodyChecked( body, sourceGenerator)
]
method(Object, "serialize", Object) [
- bodyChecked = '''
+ val body = '''
{
java.util.Map.Entry _input = (java.util.Map.Entry) $1;
«QName.name» _localName = QNAME;
return toDomStatic(_localName,_input.getValue());
}
'''
+ setBodyChecked( body, sourceGenerator)
]
method(Object, "fromDomStatic", #[QName, Object, InstanceIdentifier]) [
modifiers = PUBLIC + FINAL + STATIC
- bodyChecked = deserializeBody(type, node, getBindingIdentifierByPath(node.path))
+ setBodyChecked( deserializeBody(type, node, getBindingIdentifierByPath(node.path)),
+ sourceGenerator )
]
method(Object, "deserialize", #[Object, InstanceIdentifier]) [
- bodyChecked = '''
+ val body = '''
{
//System.out.println("«type.name»#deserialize: " +$1);
java.util.Map.Entry _input = (java.util.Map.Entry) $1;
return fromDomStatic((«QName.name»)_input.getKey(),_input.getValue(),$2);
}
'''
+ setBodyChecked( body, sourceGenerator)
]
]
val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) as Class<? extends BindingCodec<Object, Object>>
+ sourceGenerator.outputGeneratedSource( ctCls )
listener?.onDataContainerCodecCreated(inputType, ret);
LOG.debug("DOM Codec for {} was generated {}", inputType, ret)
return ret;
Class<?> inputType, GeneratedType typeSpec, SchemaNode node) {
try {
+ val SourceCodeGenerator sourceGenerator = sourceCodeGeneratorFactory.getInstance( null );
+
//log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
val ctCls = createClass(typeSpec.codecClassName) [
+
//staticField(Map,"AUGMENTATION_SERIALIZERS");
- staticQNameField(node.QName);
- staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
- staticField(it, IDENTITYREF_CODEC, BindingCodec)
- staticField(it, AUGMENTATION_CODEC, BindingCodec)
+ staticQNameField(node.QName, sourceGenerator);
+ staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec, sourceGenerator)
+ staticField(it, IDENTITYREF_CODEC, BindingCodec, sourceGenerator)
+ staticField(it, AUGMENTATION_CODEC, BindingCodec, sourceGenerator)
implementsType(BINDING_CODEC)
method(Object, "toDomStatic", #[QName, Object]) [
modifiers = PUBLIC + FINAL + STATIC
- bodyChecked = serializeBodyFacade(typeSpec, node)
+ setBodyChecked( serializeBodyFacade(typeSpec, node), sourceGenerator )
]
method(Object, "serialize", Object) [
- bodyChecked = '''
+ val body = '''
{
java.util.Map.Entry _input = (java.util.Map.Entry) $1;
«QName.name» _localName = QNAME;
return toDomStatic(_localName,_input.getValue());
}
'''
+ setBodyChecked( body, sourceGenerator )
]
method(Object, "fromDomStatic", #[QName, Object, InstanceIdentifier]) [
modifiers = PUBLIC + FINAL + STATIC
- bodyChecked = deserializeBody(typeSpec, node, getBindingIdentifierByPath(node.path))
+ setBodyChecked( deserializeBody(typeSpec, node, getBindingIdentifierByPath(node.path)),
+ sourceGenerator )
]
method(Object, "deserialize", #[Object, InstanceIdentifier]) [
- bodyChecked = '''
+ val body = '''
{
«QName.name» _qname = QNAME;
if($1 instanceof java.util.Map.Entry) {
return fromDomStatic(_qname,$1,$2);
}
'''
+ setBodyChecked( body, sourceGenerator )
]
]
val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) as Class<? extends BindingCodec<Map<QName,Object>, Object>>
+
+ sourceGenerator.outputGeneratedSource( ctCls )
+
listener?.onDataContainerCodecCreated(inputType, ret);
LOG.debug("DOM Codec for {} was generated {}", inputType, ret)
return ret;
Class<?> inputType, GeneratedType type, AugmentationSchema node) {
try {
+ val SourceCodeGenerator sourceGenerator = sourceCodeGeneratorFactory.getInstance( null );
+
//log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
val properties = type.allProperties
val ctCls = createClass(type.codecClassName) [
//staticField(Map,"AUGMENTATION_SERIALIZERS");
- staticQNameField(node.augmentationQName);
- staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
- staticField(it, AUGMENTATION_CODEC, BindingCodec)
- staticField(it, IDENTITYREF_CODEC, BindingCodec)
+ staticQNameField(node.augmentationQName, sourceGenerator);
+ staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec, sourceGenerator)
+ staticField(it, AUGMENTATION_CODEC, BindingCodec, sourceGenerator)
+ staticField(it, IDENTITYREF_CODEC, BindingCodec, sourceGenerator)
implementsType(BINDING_CODEC)
method(Object, "toDomStatic", #[QName, Object]) [
modifiers = PUBLIC + FINAL + STATIC
- bodyChecked = '''
+ val body = '''
{
////System.out.println("Qname " + $1);
////System.out.println("Value " + $2);
return ($r) _childNodes;
}
'''
+ setBodyChecked( body, sourceGenerator )
]
method(Object, "serialize", Object) [
- bodyChecked = '''
+ val body = '''
{
- java.util.Map.Entry _input = (java.util.Map.Entry) $1;
- «QName.name» _localName = QNAME;
- if(_input.getKey() != null) {
- _localName = («QName.name») _input.getKey();
- }
- return toDomStatic(_localName,_input.getValue());
+ java.util.Map.Entry _input = (java.util.Map.Entry) $1;
+ «QName.name» _localName = QNAME;
+ if(_input.getKey() != null) {
+ _localName = («QName.name») _input.getKey();
+ }
+ return toDomStatic(_localName,_input.getValue());
}
'''
+ setBodyChecked( body, sourceGenerator )
]
method(Object, "fromDomStatic", #[QName, Object, InstanceIdentifier]) [
modifiers = PUBLIC + FINAL + STATIC
- bodyChecked = '''
+ val body = '''
{
«QName.name» _localQName = QNAME;
return _builder.build();
}
'''
+ setBodyChecked( body, sourceGenerator )
]
method(Object, "deserialize", #[Object, InstanceIdentifier]) [
- bodyChecked = '''
- return fromDomStatic(QNAME,$1,$2);
+ val body = '''
+ {
+ return fromDomStatic(QNAME,$1,$2);
+ }
'''
+ setBodyChecked( body, sourceGenerator )
]
]
val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) as Class<? extends BindingCodec<Map<QName,Object>, Object>>
+ sourceGenerator.outputGeneratedSource( ctCls )
listener?.onDataContainerCodecCreated(inputType, ret);
return ret;
} catch (Exception e) {
Class<?> inputType, GeneratedType typeSpec, ChoiceNode node) {
try {
+ val SourceCodeGenerator sourceGenerator = sourceCodeGeneratorFactory.getInstance( null );
+
//log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
val ctCls = createClass(typeSpec.codecClassName) [
//staticField(Map,"AUGMENTATION_SERIALIZERS");
//staticQNameField(inputType);
- staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
- staticField(it, IDENTITYREF_CODEC, BindingCodec)
- staticField(it, DISPATCH_CODEC, BindingCodec)
+ staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec, sourceGenerator)
+ staticField(it, IDENTITYREF_CODEC, BindingCodec, sourceGenerator)
+ staticField(it, DISPATCH_CODEC, BindingCodec, sourceGenerator)
//staticField(it,QNAME_TO_CASE_MAP,BindingCodec)
implementsType(BINDING_CODEC)
method(List, "toDomStatic", #[QName, Object]) [
modifiers = PUBLIC + FINAL + STATIC
- bodyChecked = '''
+ val body = '''
{
if($2 == null) {
return null;
return («List.name») _ret;
}
'''
+ setBodyChecked( body, sourceGenerator )
]
method(Object, "serialize", Object) [
- bodyChecked = '''
- throw new «UnsupportedOperationException.name»("Direct invocation not supported.");
+ val body = '''
+ {
+ throw new «UnsupportedOperationException.name»("Direct invocation not supported.");
+ }
'''
+ setBodyChecked( body, sourceGenerator )
]
method(Object, "fromDomStatic", #[QName, Map, InstanceIdentifier]) [
modifiers = PUBLIC + FINAL + STATIC
- bodyChecked = '''
+ val body = '''
{
if («DISPATCH_CODEC» == null) {
throw new «IllegalStateException.name»("Implementation of codec was not initialized.");
return «DISPATCH_CODEC».deserialize($2,$3);
}
'''
+ setBodyChecked( body, sourceGenerator )
]
method(Object, "deserialize", #[Object, InstanceIdentifier]) [
- bodyChecked = '''
- throw new «UnsupportedOperationException.name»("Direct invocation not supported.");
+ val body = '''
+ {
+ throw new «UnsupportedOperationException.name»("Direct invocation not supported.");
+ }
'''
+ setBodyChecked( body, sourceGenerator )
]
]
val rawRet = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
+ sourceGenerator.outputGeneratedSource( ctCls )
val ret = rawRet as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
listener?.onChoiceCodecCreated(inputType, ret, node);
LOG.debug("DOM Codec for {} was generated {}", inputType, ret)
Class<?> inputType, GeneratedTransferObject typeSpec, TypeDefinition<?> typeDef) {
try {
+ val SourceCodeGenerator sourceGenerator = sourceCodeGeneratorFactory.getInstance( null );
+
val returnType = typeSpec.valueReturnType;
if (returnType == null) {
- val ctCls = createDummyImplementation(inputType, typeSpec);
+ val ctCls = createDummyImplementation(inputType, typeSpec, sourceGenerator);
val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
+ sourceGenerator.outputGeneratedSource( ctCls )
return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
}
//staticField(Map,"AUGMENTATION_SERIALIZERS");
if (inputType.isYangBindingAvailable) {
implementsType(BINDING_CODEC)
- staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
- staticField(it, IDENTITYREF_CODEC, BindingCodec)
+ staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec, sourceGenerator)
+ staticField(it, IDENTITYREF_CODEC, BindingCodec, sourceGenerator)
implementsType(BindingDeserializer.asCtClass)
}
method(Object, "toDomValue", Object) [
modifiers = PUBLIC + FINAL + STATIC
val ctSpec = typeSpec.asCtClass;
- bodyChecked = '''
+ val body = '''
{
////System.out.println("«inputType.simpleName»#toDomValue: "+$1);
return _domValue;
}
'''
+ setBodyChecked( body, sourceGenerator )
]
method(Object, "serialize", Object) [
- bodyChecked = '''
+ val body = '''
{
return toDomValue($1);
}
'''
+ setBodyChecked( body, sourceGenerator )
]
method(Object, "fromDomValue", Object) [
modifiers = PUBLIC + FINAL + STATIC
- bodyChecked = '''
+ val body = '''
{
////System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
return _value;
}
'''
+ setBodyChecked( body, sourceGenerator )
]
method(Object, "deserialize", Object) [
- bodyChecked = '''{
+ val body = '''
+ {
return fromDomValue($1);
- }
+ }
'''
+ setBodyChecked( body, sourceGenerator )
]
]
val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
+ sourceGenerator.outputGeneratedSource( ctCls )
LOG.debug("DOM Codec for {} was generated {}", inputType, ret)
return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
} catch (Exception e) {
private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateValueTransformer(
Class<?> inputType, GeneratedTransferObject typeSpec, UnionTypeDefinition typeDef) {
try {
+ val SourceCodeGenerator sourceGenerator = sourceCodeGeneratorFactory.getInstance( null );
+
val ctCls = createClass(typeSpec.codecClassName) [
val properties = typeSpec.allProperties;
val getterToTypeDefinition = XtendHelper.getTypes(typeDef).toMap[type|type.QName.getterName];
//staticField(Map,"AUGMENTATION_SERIALIZERS");
if (inputType.isYangBindingAvailable) {
implementsType(BINDING_CODEC)
- staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
- staticField(it, IDENTITYREF_CODEC, BindingCodec)
+ staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec, sourceGenerator)
+ staticField(it, IDENTITYREF_CODEC, BindingCodec, sourceGenerator)
implementsType(BindingDeserializer.asCtClass)
}
method(Object, "toDomValue", Object) [
modifiers = PUBLIC + FINAL + STATIC
val ctSpec = inputType.asCtClass;
- bodyChecked = '''
+ val body = '''
{
////System.out.println("«inputType.simpleName»#toDomValue: "+$1);
return null;
}
'''
+ setBodyChecked( body, sourceGenerator )
]
method(Object, "serialize", Object) [
- bodyChecked = '''
+ val body = '''
{
return toDomValue($1);
}
'''
+ setBodyChecked( body, sourceGenerator )
]
method(Object, "fromDomValue", Object) [
modifiers = PUBLIC + FINAL + STATIC
- bodyChecked = '''
+ val body = '''
{
////System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
return null;
}
'''
+ setBodyChecked( body, sourceGenerator )
]
method(Object, "deserialize", Object) [
- bodyChecked = '''{
+ val body = '''
+ {
return fromDomValue($1);
- }
+ }
'''
+ setBodyChecked( body, sourceGenerator )
]
]
val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
+ sourceGenerator.outputGeneratedSource( ctCls )
LOG.debug("DOM Codec for {} was generated {}", inputType, ret)
return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
} catch (Exception e) {
private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateValueTransformer(
Class<?> inputType, GeneratedTransferObject typeSpec, BitsTypeDefinition typeDef) {
try {
+ val SourceCodeGenerator sourceGenerator = sourceCodeGeneratorFactory.getInstance( null );
+
val ctCls = createClass(typeSpec.codecClassName) [
//staticField(Map,"AUGMENTATION_SERIALIZERS");
if (inputType.isYangBindingAvailable) {
implementsType(BINDING_CODEC)
- staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
- staticField(it, IDENTITYREF_CODEC, BindingCodec)
+ staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec, sourceGenerator)
+ staticField(it, IDENTITYREF_CODEC, BindingCodec, sourceGenerator)
implementsType(BindingDeserializer.asCtClass)
}
method(Object, "toDomValue", Object) [
modifiers = PUBLIC + FINAL + STATIC
val ctSpec = typeSpec.asCtClass;
- bodyChecked = '''
+ val body = '''
{
////System.out.println("«inputType.simpleName»#toDomValue: "+$1);
return _domValue;
}
'''
+ setBodyChecked( body, sourceGenerator )
]
method(Object, "serialize", Object) [
- bodyChecked = '''
+ val body = '''
{
return toDomValue($1);
}
'''
+ setBodyChecked( body, sourceGenerator )
]
method(Object, "fromDomValue", Object) [
modifiers = PUBLIC + FINAL + STATIC
- val sortedBits = new ArrayList(typeDef.bits)
- Collections.sort(sortedBits, [o1, o2|
- o1.propertyName.compareTo(o2.propertyName)
- ])
- bodyChecked = '''
+ val sortedBits = typeDef.bits.sort[o1, o2|o1.propertyName.compareTo(o2.propertyName)]
+ val body = '''
{
//System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
return new «inputType.resolvedName»(«FOR bit : sortedBits SEPARATOR ","»«bit.propertyName»«ENDFOR»);
}
'''
+ setBodyChecked( body, sourceGenerator )
]
method(Object, "deserialize", Object) [
- bodyChecked = '''{
+ val body = '''
+ {
return fromDomValue($1);
- }
+ }
'''
+ setBodyChecked( body, sourceGenerator )
]
]
val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
+ sourceGenerator.outputGeneratedSource( ctCls )
LOG.debug("DOM Codec for {} was generated {}", inputType, ret)
return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
} catch (Exception e) {
}
}
- private def createDummyImplementation(Class<?> object, GeneratedTransferObject typeSpec) {
+ private def createDummyImplementation(Class<?> object, GeneratedTransferObject typeSpec,
+ SourceCodeGenerator sourceGenerator ) {
LOG.trace("Generating Dummy DOM Codec for {} with {}", object, object.classLoader)
return createClass(typeSpec.codecClassName) [
if (object.isYangBindingAvailable) {
implementsType(BINDING_CODEC)
- staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
- staticField(it, IDENTITYREF_CODEC, BindingCodec)
+ staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec, sourceGenerator)
+ staticField(it, IDENTITYREF_CODEC, BindingCodec, sourceGenerator)
implementsType(BindingDeserializer.asCtClass)
}
//implementsType(BindingDeserializer.asCtClass)
method(Object, "toDomValue", Object) [
modifiers = PUBLIC + FINAL + STATIC
- bodyChecked = '''{
- if($1 == null) {
- return null;
- }
- return $1.toString();
-
+ val body = '''
+ {
+ if($1 == null) {
+ return null;
+ }
+ return $1.toString();
}'''
+ setBodyChecked( body, sourceGenerator )
]
method(Object, "serialize", Object) [
- bodyChecked = '''
+ val body = '''
{
return toDomValue($1);
}
'''
+ setBodyChecked( body, sourceGenerator )
]
method(Object, "fromDomValue", Object) [
modifiers = PUBLIC + FINAL + STATIC
- bodyChecked = '''return null;'''
+ val body = '''return null;'''
+ setBodyChecked( body, sourceGenerator )
]
method(Object, "deserialize", Object) [
- bodyChecked = '''{
+ val body = '''
+ {
return fromDomValue($1);
}
'''
+ setBodyChecked( body, sourceGenerator )
]
]
}
}
val enumSchema = enumSchemaType;
try {
+ val SourceCodeGenerator sourceGenerator = sourceCodeGeneratorFactory.getInstance( null );
+
//log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
val ctCls = createClass(typeSpec.codecClassName) [
//staticField(Map,"AUGMENTATION_SERIALIZERS");
//implementsType(BINDING_CODEC)
method(Object, "toDomValue", Object) [
modifiers = PUBLIC + FINAL + STATIC
- bodyChecked = '''{
+ val body = '''
+ {
if($1 == null) {
return null;
}
return null;
}
'''
+ setBodyChecked( body, sourceGenerator )
]
method(Object, "serialize", Object) [
- bodyChecked = '''
- return toDomValue($1);
+ val body = '''
+ {
+ return toDomValue($1);
+ }
'''
+ setBodyChecked( body, sourceGenerator )
]
method(Object, "fromDomValue", Object) [
modifiers = PUBLIC + FINAL + STATIC
- bodyChecked = '''
+ val body = '''
{
if($1 == null) {
return null;
return null;
}
'''
+ setBodyChecked( body, sourceGenerator )
]
method(Object, "deserialize", Object) [
- bodyChecked = '''
- return fromDomValue($1);
+ val body = '''
+ {
+ return fromDomValue($1);
+ }
'''
+ setBodyChecked( body, sourceGenerator )
]
]
val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
+ sourceGenerator.outputGeneratedSource( ctCls )
LOG.debug("DOM Codec for {} was generated {}", inputType, ret)
return ret;
} catch (CodeGenerationException e) {
*/
private def getBuilderName(GeneratedType type) '''«type.resolvedName»Builder'''
- private def staticQNameField(CtClass it, QName node) {
+ private def staticQNameField(CtClass it, QName node, SourceCodeGenerator sourceGenerator) {
val field = new CtField(ctQName, "QNAME", it);
field.modifiers = PUBLIC + FINAL + STATIC;
- addField(field,
- '''«QName.asCtClass.name».create("«node.namespace»","«node.formattedRevision»","«node.localName»")''')
+ val code = '''«QName.asCtClass.name».create("«node.namespace»","«node.formattedRevision»","«node.localName»")'''
+ addField(field, code )
+
+ sourceGenerator.appendField( field, code );
}
private def String serializeBodyImpl(GeneratedType type, DataNodeContainer nodeContainer) '''
throw exception;
}
- private def setBodyChecked(CtMethod method, String body) {
+ private def setBodyChecked(CtMethod method, String body, SourceCodeGenerator sourceGenerator ) {
try {
method.setBody(body);
+
+ sourceGenerator.appendMethod( method, body );
} catch (CannotCompileException e) {
LOG.error("Cannot compile method: {}#{} {}, Reason: {} Body: {}", method.declaringClass, method.name,
method.signature, e.message, body)
--- /dev/null
+/*
+ * Copyright (c) 2014 Brocade Communications 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.generator.util;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javassist.CtClass;
+import javassist.CtField;
+import javassist.CtMethod;
+import javassist.Modifier;
+import javassist.NotFoundException;
+
+/**
+ * The default implementation of the SourceCodeGenerator interface that generates readable source code
+ * for a runtime generated class. The appendField/appendMethod methods output source code to a temporary
+ * StringBuilder. When outputGeneratedSource is called, the entire class source code is generated and
+ * written to a file under a specified directory.
+ *
+ * @author Thomas Pantelis
+ */
+public class DefaultSourceCodeGenerator implements SourceCodeGenerator {
+ private static final Logger LOG = LoggerFactory.getLogger(DefaultSourceCodeGenerator.class);
+
+ private static final String GENERATED_SOURCE_DIR_PROP = "org.opendaylight.yangtools.sal.generatedCodecSourceDir";
+
+ private final StringBuilder builder = new StringBuilder();
+ private final String generatedSourceDir;
+
+ /**
+ * Constructor.
+ *
+ * @param generatedSourceDir the directory in which to put generated source files. If null, the directory
+ * is obtained from a system property (<i>org.opendaylight.yangtools.sal.generatedCodecSourceDir</i>) or
+ * defaults to "generated-codecs".
+ */
+ public DefaultSourceCodeGenerator( String generatedSourceDir ) {
+ if( generatedSourceDir != null ) {
+ this.generatedSourceDir = generatedSourceDir;
+ }
+ else {
+ this.generatedSourceDir = System.getProperty( GENERATED_SOURCE_DIR_PROP, "generated-codecs" );
+ }
+ }
+
+ @Override
+ public void appendField(CtField field, String value) {
+ try {
+ builder.append('\n')
+ .append(Modifier.toString(field.getModifiers()))
+ .append(' ').append(field.getType().getName()).append(' ')
+ .append(field.getName());
+ if (value != null) {
+ builder.append(" = ").append(value);
+ }
+
+ builder.append(";\n");
+ } catch (NotFoundException e) {
+ LOG.error("Error building field source for " + field.getName(), e);
+ }
+ }
+
+ @Override
+ public void appendMethod(CtMethod method, String code) {
+ try {
+ builder.append('\n')
+ .append(Modifier.toString(method.getModifiers()))
+ .append(' ').append(method.getReturnType().getName())
+ .append(' ').append(method.getName()).append("( ");
+
+ CtClass[] paramTypes = method.getParameterTypes();
+ if (paramTypes != null) {
+ for (int i = 0; i < paramTypes.length; i++) {
+ if (i > 0)
+ builder.append(", ");
+ builder.append(paramTypes[i].getName()).append(" $")
+ .append(i + 1);
+ }
+ }
+
+ builder.append(" )\n").append(code).append("\n\n");
+ } catch (NotFoundException e) {
+ LOG.error("Error building method source for " + method.getName(), e);
+ }
+ }
+
+ @Override
+ public void outputGeneratedSource(CtClass ctClass) {
+ String name = ctClass.getName();
+
+ StringBuilder classBuilder = new StringBuilder();
+ classBuilder.append(Modifier.toString(ctClass.getModifiers()))
+ .append(" class ").append(ctClass.getSimpleName());
+
+ try {
+ CtClass superClass = ctClass.getSuperclass();
+ if (superClass != null) {
+ classBuilder.append(" extends ").append(superClass.getName());
+ }
+
+ CtClass[] interfaces = ctClass.getInterfaces();
+ if (interfaces.length > 0) {
+ classBuilder.append(" implements ");
+ for (int i = 0; i < interfaces.length; i++) {
+ if (i > 0) {
+ classBuilder.append(", ");
+ }
+
+ classBuilder.append(interfaces[i].getName());
+ }
+ }
+
+ classBuilder.append(" {\n").append(builder.toString())
+ .append("\n}");
+ } catch (NotFoundException e) {
+ LOG.error("Error building class source for " + name, e);
+ return;
+ }
+
+ File dir = new File(generatedSourceDir);
+ dir.mkdir();
+ try (FileWriter writer = new FileWriter(new File(dir, name + ".java"))) {
+ writer.append(classBuilder.toString());
+ writer.flush();
+ } catch (IOException e) {
+ LOG.error("Error writing class source for " + name, e);
+ }
+ }
+}
import javassist.LoaderClassPath;
import javassist.Modifier;
import javassist.NotFoundException;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
}
public CtField staticField(final CtClass it, final String name, final Class<? extends Object> returnValue) throws CannotCompileException {
+ return staticField(it, name, returnValue, null);
+ }
+
+ public CtField staticField(final CtClass it, final String name,
+ final Class<? extends Object> returnValue,
+ SourceCodeGenerator sourceGenerator) throws CannotCompileException {
final CtField field = new CtField(asCtClass(returnValue), name, it);
field.setModifiers(Modifier.PUBLIC + Modifier.STATIC);
it.addField(field);
+
+ if (sourceGenerator != null) {
+ sourceGenerator.appendField(field, null);
+ }
+
return field;
}
--- /dev/null
+/*
+ * Copyright (c) 2014 Brocade Communications 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.generator.util;
+
+import javassist.CtClass;
+import javassist.CtField;
+import javassist.CtMethod;
+
+/**
+ * Implementation of the SourceCodeGenerator interface that does nothing.
+ *
+ * @author Thomas Pantelis
+ */
+public class NullSourceCodeGenerator implements SourceCodeGenerator {
+
+ @Override
+ public void appendField( CtField field, String value ) {
+ }
+
+ @Override
+ public void appendMethod( CtMethod method, String code ) {
+ }
+
+ @Override
+ public void outputGeneratedSource( CtClass ctClass ) {
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Brocade Communications 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.generator.util;
+
+import javassist.CtClass;
+import javassist.CtField;
+import javassist.CtMethod;
+
+/**
+ * Interface for a class that that generates readable source code for a runtime generated class.
+ * The appendField/appendMethod methods append source code to a temporary output. When outputGeneratedSource
+ * is called, the entire class source code is generated and outputted.
+ *
+ * @author Thomas Pantelis
+ */
+public interface SourceCodeGenerator {
+
+ /**
+ * Appends the given class field and value to the temporary output.
+ */
+ void appendField( CtField field, String value );
+
+ /**
+ * Appends the given method and source code body to the temporary output.
+ */
+ void appendMethod( CtMethod method, String code );
+
+ /**
+ * Generates the full source code for the given class and outputs it.
+ */
+ void outputGeneratedSource( CtClass ctClass );
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2014 Brocade Communications 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.generator.util;
+
+/**
+ * Factory class for creating SourceCodeGenerator instances.
+ *
+ * @author Thomas Pantelis
+ */
+public class SourceCodeGeneratorFactory {
+
+ private static final String GENERATE_CODEC_SOURCE_PROP = "org.opendaylight.yangtools.sal.generateCodecSource";
+
+ private static final SourceCodeGenerator NULL_GENERATOR = new NullSourceCodeGenerator();
+
+ /**
+ * Gets a SourceCodeGenerator instance.
+ * <p>
+ * Generation of source code is controlled by the <i>org.opendaylight.yangtools.sal.generateCodecSource</i>
+ * system property. If set to true, a DefaultSourceCodeGenerator instance is returned, otherwise a
+ * NullSourceCodeGenerator is returned.
+ *
+ * @param generatedSourceDir the directory in which to put generated source files. If null,
+ * a default is used (see DefaultSourceCodeGenerator).
+ */
+ public SourceCodeGenerator getInstance( String generatedSourceDir ) {
+
+ boolean generateSource = Boolean.valueOf( System.getProperty( GENERATE_CODEC_SOURCE_PROP, "false") );
+ if( generateSource ) {
+ return new DefaultSourceCodeGenerator( generatedSourceDir );
+ }
+
+ return NULL_GENERATOR;
+ }
+}
*/
package org.opendaylight.yangtools.binding.generator.util;
+import com.google.common.base.CharMatcher;
+import com.google.common.collect.Iterables;
+
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition;
import org.opendaylight.yangtools.yang.model.util.ExtendedType;
-import com.google.common.base.CharMatcher;
-import com.google.common.collect.Iterables;
-
/**
* Contains the methods for converting strings to valid JAVA language strings
* (package names, class names, attribute names).
private static final CharMatcher DOT_MATCHER = CharMatcher.is('.');
private static final CharMatcher DASH_COLON_MATCHER = CharMatcher.anyOf("-:");
+ private static final Restrictions EMPTY_RESTRICTIONS = new Restrictions() {
+ @Override
+ public List<LengthConstraint> getLengthConstraints() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public List<PatternConstraint> getPatternConstraints() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public List<RangeConstraint> getRangeConstraints() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return true;
+ }
+ };
+
+ private static final Comparator<TypeMemberBuilder<?>> SUID_MEMBER_COMPARATOR = new Comparator<TypeMemberBuilder<?>>() {
+ @Override
+ public int compare(final TypeMemberBuilder<?> o1, final TypeMemberBuilder<?> o2) {
+ return o1.getName().compareTo(o2.getName());
+ }
+ };
+
+ private static final Comparator<Type> SUID_NAME_COMPARATOR = new Comparator<Type>() {
+ @Override
+ public int compare(final Type o1, final Type o2) {
+ return o1.getFullyQualifiedName().compareTo(o2.getFullyQualifiedName());
+ }
+ };
+
/**
* Converts <code>parameterName</code> to valid JAVA parameter name.
*
return sb.toString();
}
+ private static <T> Iterable<T> sortedCollection(final Comparator<? super T> comparator, final Collection<T> input) {
+ if (input.size() > 1) {
+ final List<T> ret = new ArrayList<>(input);
+ Collections.sort(ret, comparator);
+ return ret;
+ } else {
+ return input;
+ }
+ }
+
public static long computeDefaultSUID(final GeneratedTypeBuilderBase<?> to) {
try {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
dout.writeUTF(to.getName());
dout.writeInt(to.isAbstract() ? 3 : 7);
- List<Type> impl = to.getImplementsTypes();
- Collections.sort(impl, new Comparator<Type>() {
- @Override
- public int compare(final Type o1, final Type o2) {
- return o1.getFullyQualifiedName().compareTo(o2.getFullyQualifiedName());
- }
- });
- for (Type ifc : impl) {
+ for (Type ifc : sortedCollection(SUID_NAME_COMPARATOR, to.getImplementsTypes())) {
dout.writeUTF(ifc.getFullyQualifiedName());
}
- Comparator<TypeMemberBuilder<?>> comparator = new Comparator<TypeMemberBuilder<?>>() {
- @Override
- public int compare(final TypeMemberBuilder<?> o1, final TypeMemberBuilder<?> o2) {
- return o1.getName().compareTo(o2.getName());
- }
- };
-
- List<GeneratedPropertyBuilder> props = to.getProperties();
- Collections.sort(props, comparator);
- for (GeneratedPropertyBuilder gp : props) {
+ for (GeneratedPropertyBuilder gp : sortedCollection(SUID_MEMBER_COMPARATOR, to.getProperties())) {
dout.writeUTF(gp.getName());
}
- List<MethodSignatureBuilder> methods = to.getMethodDefinitions();
- Collections.sort(methods, comparator);
- for (MethodSignatureBuilder m : methods) {
+ for (MethodSignatureBuilder m : sortedCollection(SUID_MEMBER_COMPARATOR, to.getMethodDefinitions())) {
if (!(m.getAccessModifier().equals(AccessModifier.PRIVATE))) {
dout.writeUTF(m.getName());
dout.write(m.getAccessModifier().ordinal());
dout.flush();
- MessageDigest md = MessageDigest.getInstance("SHA");
- byte[] hashBytes = md.digest(bout.toByteArray());
- long hash = 0;
- for (int i = Math.min(hashBytes.length, 8) - 1; i >= 0; i--) {
- hash = (hash << 8) | (hashBytes[i] & 0xFF);
+ try {
+ MessageDigest md = MessageDigest.getInstance("SHA");
+ byte[] hashBytes = md.digest(bout.toByteArray());
+ long hash = 0;
+ for (int i = Math.min(hashBytes.length, 8) - 1; i >= 0; i--) {
+ hash = (hash << 8) | (hashBytes[i] & 0xFF);
+ }
+ return hash;
+ } catch (NoSuchAlgorithmException ex) {
+ throw new SecurityException(ex.getMessage());
}
- return hash;
} catch (IOException ex) {
throw new InternalError();
- } catch (NoSuchAlgorithmException ex) {
- throw new SecurityException(ex.getMessage());
}
}
public static Restrictions getRestrictions(final TypeDefinition<?> type) {
- final List<LengthConstraint> length = new ArrayList<>();
- final List<PatternConstraint> pattern = new ArrayList<>();
- final List<RangeConstraint> range = new ArrayList<>();
-
- if (type instanceof ExtendedType) {
- ExtendedType ext = (ExtendedType)type;
- TypeDefinition<?> base = ext.getBaseType();
- length.addAll(ext.getLengthConstraints());
- pattern.addAll(ext.getPatternConstraints());
- range.addAll(ext.getRangeConstraints());
-
- if (base instanceof IntegerTypeDefinition && range.isEmpty()) {
- range.addAll(((IntegerTypeDefinition)base).getRangeConstraints());
- } else if (base instanceof UnsignedIntegerTypeDefinition && range.isEmpty()) {
- range.addAll(((UnsignedIntegerTypeDefinition)base).getRangeConstraints());
- } else if (base instanceof DecimalTypeDefinition && range.isEmpty()) {
- range.addAll(((DecimalTypeDefinition)base).getRangeConstraints());
+ // Base types have no constraints, so get over it quickly
+ if (!(type instanceof ExtendedType)) {
+ return EMPTY_RESTRICTIONS;
+ }
+
+ // Take care of the extended types ...
+ final ExtendedType ext = (ExtendedType)type;
+ final List<LengthConstraint> length = ext.getLengthConstraints();
+ final List<PatternConstraint> pattern = ext.getPatternConstraints();
+
+ List<RangeConstraint> tmp = ext.getRangeConstraints();
+ if (tmp.isEmpty()) {
+ final TypeDefinition<?> base = ext.getBaseType();
+ if (base instanceof IntegerTypeDefinition) {
+ tmp = ((IntegerTypeDefinition)base).getRangeConstraints();
+ } else if (base instanceof UnsignedIntegerTypeDefinition) {
+ tmp = ((UnsignedIntegerTypeDefinition)base).getRangeConstraints();
+ } else if (base instanceof DecimalTypeDefinition) {
+ tmp = ((DecimalTypeDefinition)base).getRangeConstraints();
}
+ }
+ // Now, this may have ended up being empty, too...
+ if (length.isEmpty() && pattern.isEmpty() && tmp.isEmpty()) {
+ return EMPTY_RESTRICTIONS;
}
+ // Nope, not empty allocate a holder
+ final List<RangeConstraint> range = tmp;
return new Restrictions() {
@Override
public List<RangeConstraint> getRangeConstraints() {
}
@Override
public boolean isEmpty() {
- return range.isEmpty() && pattern.isEmpty() && length.isEmpty();
+ return false;
}
};
}
import org.opendaylight.yangtools.sal.binding.model.api.type.builder.AnnotationTypeBuilder;
import org.opendaylight.yangtools.sal.binding.model.api.type.builder.EnumBuilder;
import org.opendaylight.yangtools.yang.binding.BindingMapping;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.Status;
import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition.EnumPair;
private final String name;
private final List<Enumeration.Pair> values;
private final List<AnnotationTypeBuilder> annotationBuilders = new ArrayList<>();
+ private String description;
+ private String reference;
+ private String moduleName;
+ private Iterable<QName> schemaPath;
public EnumerationBuilderImpl(final String packageName, final String name) {
super(packageName, name);
values = new ArrayList<>();
}
+ public void setReference(final String reference) {
+ this.reference = reference;
+ }
+
+ public void setModuleName(final String moduleName) {
+ this.moduleName = moduleName;
+ }
+
+ public void setSchemaPath(final Iterable<QName> schemaPath) {
+ this.schemaPath = schemaPath;
+ }
+
+ @Override
+ public void setDescription(String description) {
+ this.description = description;
+
+ }
+
@Override
public AnnotationTypeBuilder addAnnotation(final String packageName, final String name) {
if (packageName != null && name != null) {
}
@Override
- public void addValue(final String name, final Integer value) {
- values.add(new EnumPairImpl(name, value));
+ public void addValue(final String name, final Integer value, final String description) {
+ values.add(new EnumPairImpl(name, value, description));
}
@Override
public Enumeration toInstance(final Type definingType) {
- return new EnumerationImpl(definingType, annotationBuilders, packageName, name, values);
+ return new EnumerationImpl(definingType, annotationBuilders, packageName, name, values,
+ description, reference, moduleName, schemaPath);
+ }
+
+ @Override
+ public void updateEnumPairsFromEnumTypeDef(final EnumTypeDefinition enumTypeDef) {
+ final List<EnumPair> enums = enumTypeDef.getValues();
+ if (enums != null) {
+ int listIndex = 0;
+ for (final EnumPair enumPair : enums) {
+ if (enumPair != null) {
+ final String enumPairName = BindingMapping.getClassName(enumPair.getName());
+ Integer enumPairValue = enumPair.getValue();
+
+ if (enumPairValue == null) {
+ enumPairValue = listIndex;
+ }
+ else {
+ listIndex = enumPairValue;
+ }
+
+ this.addValue(enumPairName, enumPairValue, enumPair.getDescription());
+ listIndex++;
+ }
+ }
+ }
}
/*
return builder.toString();
}
- @Override
- public void updateEnumPairsFromEnumTypeDef(final EnumTypeDefinition enumTypeDef) {
- final List<EnumPair> enums = enumTypeDef.getValues();
- if (enums != null) {
- int listIndex = 0;
- for (final EnumPair enumPair : enums) {
- if (enumPair != null) {
- final String enumPairName = BindingMapping.getClassName(enumPair.getName());
- Integer enumPairValue = enumPair.getValue();
-
- if (enumPairValue == null) {
- enumPairValue = listIndex;
- }
- this.addValue(enumPairName, enumPairValue);
- listIndex++;
- }
- }
- }
-
- }
-
private static final class EnumPairImpl implements Enumeration.Pair {
private final String name;
private final Integer value;
+ private final String description;
- public EnumPairImpl(String name, Integer value) {
+ public EnumPairImpl(String name, Integer value, String description) {
super();
this.name = name;
this.value = value;
+ this.description = description;
}
@Override
builder.append("]");
return builder.toString();
}
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ @Override
+ public String getReference() {
+ return null;
+ }
+
+ @Override
+ public Status getStatus() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
}
private static final class EnumerationImpl implements Enumeration {
private final Type definingType;
private final String packageName;
private final String name;
+ private final String description;
+ private final String reference;
+ private final String moduleName;
+ private final Iterable<QName> schemaPath;
private final List<Pair> values;
private List<AnnotationType> annotations = new ArrayList<>();
public EnumerationImpl(final Type definingType, final List<AnnotationTypeBuilder> annotationBuilders,
- final String packageName, final String name, final List<Pair> values) {
+ final String packageName, final String name, final List<Pair> values, final String description,
+ final String reference, final String moduleName, final Iterable<QName> schemaPath) {
super();
this.definingType = definingType;
for (final AnnotationTypeBuilder builder : annotationBuilders) {
this.packageName = packageName;
this.name = name;
this.values = Collections.unmodifiableList(values);
+ this.description = description;
+ this.reference = reference;
+ this.moduleName = moduleName;
+ this.schemaPath = schemaPath;
}
@Override
public List<GeneratedProperty> getProperties() {
return Collections.emptyList();
}
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ @Override
+ public String getReference() {
+ return reference;
+ }
+
+ @Override
+ public Iterable<QName> getSchemaPath() {
+ return schemaPath;
+ }
+
+ @Override
+ public String getModuleName() {
+ return moduleName;
+ }
}
}
import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedPropertyBuilder;
import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTOBuilder;
import org.opendaylight.yangtools.sal.binding.model.api.type.builder.MethodSignatureBuilder;
+import org.opendaylight.yangtools.yang.common.QName;
public final class GeneratedTOBuilderImpl extends AbstractGeneratedTypeBuilder<GeneratedTOBuilder> implements
GeneratedTOBuilder {
private boolean isUnionTypeBuilder = false;
private Restrictions restrictions;
private GeneratedPropertyBuilder SUID;
+ private String reference;
+ private String description;
+ private String moduleName;
+ private Iterable<QName> schemaPath;
public GeneratedTOBuilderImpl(final String packageName, final String name) {
super(packageName, name);
@Override
public GeneratedTransferObject toInstance() {
- // FIXME: can we compact the arrays now? It needs to be thread-safe, though
+ // FIXME: can we compact the arrays now? It needs to be thread-safe,
+ // though
return new GeneratedTransferObjectImpl(this);
}
this.isUnionTypeBuilder = isUnionTypeBuilder;
}
+ @Override
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ @Override
+ public void setModuleName(String moduleName) {
+ this.moduleName = moduleName;
+ }
+
+ @Override
+ public void setSchemaPath(Iterable<QName> schemaPath) {
+ this.schemaPath = schemaPath;
+ }
+
+ @Override
+ public void setReference(String reference) {
+ this.reference = reference;
+ }
+
private static final class GeneratedTransferObjectImpl extends AbstractGeneratedType implements
GeneratedTransferObject {
private final boolean isUnionTypeBuilder;
private final Restrictions restrictions;
private final GeneratedProperty SUID;
+ private final String reference;
+ private final String description;
+ private final String moduleName;
+ private final Iterable<QName> schemaPath;
public GeneratedTransferObjectImpl(final GeneratedTOBuilderImpl builder) {
super(builder);
this.isUnionType = builder.isUnionType;
this.isUnionTypeBuilder = builder.isUnionTypeBuilder;
this.restrictions = builder.restrictions;
+ this.reference = builder.reference;
+ this.description = builder.description;
+ this.moduleName = builder.moduleName;
+ this.schemaPath = builder.schemaPath;
+
if (builder.SUID == null) {
this.SUID = null;
} else {
@Override
public String toString() {
- if(isTypedef) {
+ if (isTypedef) {
return serializeTypedef(this);
}
StringBuilder builder = new StringBuilder();
}
}
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ @Override
+ public String getReference() {
+ return reference;
+ }
+
+ @Override
+ public Iterable<QName> getSchemaPath() {
+ return schemaPath;
+ }
+
+ @Override
+ public String getModuleName() {
+ return moduleName;
+ }
}
}
*/
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.builder.GeneratedTypeBuilder;
+import org.opendaylight.yangtools.yang.common.QName;
+
+public final class GeneratedTypeBuilderImpl extends AbstractGeneratedTypeBuilder<GeneratedTypeBuilder> implements
+ GeneratedTypeBuilder {
-public final class GeneratedTypeBuilderImpl extends AbstractGeneratedTypeBuilder<GeneratedTypeBuilder> implements GeneratedTypeBuilder {
+ private String description;
+ private String reference;
+ private String moduleName;
+ private Iterable<QName> schemaPath;
- public GeneratedTypeBuilderImpl(String packageName, String name) {
+ public GeneratedTypeBuilderImpl(final String packageName, final String name) {
super(packageName, name);
setAbstract(true);
}
return new GeneratedTypeImpl(this);
}
+ @Override
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ @Override
+ public void setModuleName(String moduleName) {
+ this.moduleName = moduleName;
+ }
+
+ @Override
+ public void setSchemaPath(Iterable<QName> schemaPath) {
+ this.schemaPath = schemaPath;
+ }
+
+ @Override
+ public void setReference(String reference) {
+ this.reference = reference;
+ }
+
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("]");
return builder.toString();
}
-
+
@Override
protected GeneratedTypeBuilderImpl thisInstance() {
return this;
private static final class GeneratedTypeImpl extends AbstractGeneratedType {
+ private final String description;
+ private final String reference;
+ private final String moduleName;
+ private final Iterable<QName> schemaPath;
+
public GeneratedTypeImpl(GeneratedTypeBuilderImpl builder) {
super(builder);
+
+ this.description = builder.description;
+ this.reference = builder.reference;
+ this.moduleName = builder.moduleName;
+ this.schemaPath = builder.schemaPath;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ @Override
+ public String getReference() {
+ return reference;
+ }
+
+ @Override
+ public Iterable<QName> getSchemaPath() {
+ return schemaPath;
+ }
+
+ @Override
+ public String getModuleName() {
+ return moduleName;
}
}
}
<groupId>org.eclipse.xtend</groupId>
<artifactId>xtend-maven-plugin</artifactId>
</plugin>
- <plugin>
- <artifactId>maven-clean-plugin</artifactId>
- </plugin>
<!-- <plugin>
<artifactId>maven-enforcer-plugin</artifactId>
<executions>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-slf4j-logging</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ </dependency>
</dependencies>
</project>
*/
package org.opendaylight.yangtools.sal.java.api.generator
-import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty
-import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType
-import java.util.Map
-import org.opendaylight.yangtools.sal.binding.model.api.Type
-import org.opendaylight.yangtools.binding.generator.util.Types
-import com.google.common.base.Splitter
-import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature
+import com.google.common.collect.ImmutableList
import com.google.common.collect.Range
+import java.math.BigDecimal
+import java.math.BigInteger
+import java.util.Arrays
+import java.util.Collection
+import java.util.HashMap
import java.util.List
+import java.util.Map
+import java.util.StringTokenizer
+import org.opendaylight.yangtools.binding.generator.util.Types
import org.opendaylight.yangtools.sal.binding.model.api.ConcreteType
-import org.opendaylight.yangtools.sal.binding.model.api.Restrictions
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty
import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject
-import java.util.Collection
-import java.util.Arrays
-import java.util.HashMap
-import com.google.common.collect.ImmutableList
-import java.math.BigInteger
-import java.math.BigDecimal
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType
+import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature
+import org.opendaylight.yangtools.sal.binding.model.api.Restrictions
+import org.opendaylight.yangtools.sal.binding.model.api.Type
+import org.opendaylight.yangtools.yang.common.QName
abstract class BaseTemplate {
protected val GeneratedType type;
protected val Map<String, String> importMap;
- static val paragraphSplitter = Splitter.on("\n\n").omitEmptyStrings();
+
+ private static final String NEW_LINE = '\n'
new(GeneratedType _type) {
if (_type == null) {
'''
«packageDefinition»
«imports»
-
+
«_body»
'''.toString
}
«ENDIF»
«ENDFOR»
«ENDIF»
-
+
'''
protected abstract def CharSequence body();
* @return string with comment in JAVA format
*/
def protected CharSequence asJavadoc(String comment) {
- if(comment == null) return '';
+ if(comment == null) return ''
var txt = comment
if (txt.contains("*/")) {
txt = txt.replace("*/", "*/")
}
- val paragraphs = paragraphSplitter.split(txt)
+ txt = comment.trim
+ txt = formatToParagraph(txt)
return '''
- /**
- «FOR p : paragraphs SEPARATOR "<p>"»
- «p»
- «ENDFOR»
- **/
+ «wrapToDocumentation(txt)»
'''
}
+ def String wrapToDocumentation(String text) {
+ val StringTokenizer tokenizer = new StringTokenizer(text, "\n", false)
+ val StringBuilder sb = new StringBuilder()
+
+ if(text.empty)
+ return ""
+
+ sb.append("/**")
+ sb.append(NEW_LINE)
+
+ while(tokenizer.hasMoreTokens) {
+ sb.append(" * ")
+ sb.append(tokenizer.nextToken)
+ sb.append(NEW_LINE)
+ }
+ sb.append(" */")
+
+ return sb.toString
+ }
+
+ def protected String formatDataForJavaDoc(GeneratedType type) {
+ val typeDescription = type.description
+ val typeReference = type.reference
+ val typeModuleName = type.moduleName
+ val typeSchemaPath = type.schemaPath
+
+ return '''
+ «IF !type.isDocumentationParametersNullOrEmtpy»
+ «IF typeDescription != null && !typeDescription.empty»
+ «formatToParagraph(typeDescription)»
+ «ENDIF»
+ «IF typeReference != null && !typeReference.empty»
+ Reference:
+ «formatReference(typeReference)»
+ «ENDIF»
+ «IF typeModuleName != null && !typeModuleName.empty»
+ Module name:
+ «typeModuleName»
+ «ENDIF»
+ «IF typeSchemaPath != null && !typeSchemaPath.empty»
+ Schema path:
+ «formatPath(typeSchemaPath)»
+ «ENDIF»
+ «ENDIF»
+ '''.toString
+ }
+
+ def formatPath(Iterable<QName> schemaPath) {
+ var currentElement = schemaPath.head
+ val StringBuilder sb = new StringBuilder()
+ sb.append('[')
+ sb.append(currentElement)
+
+ for(pathElement : schemaPath) {
+ if(!currentElement.namespace.equals(pathElement.namespace)) {
+ currentElement = pathElement
+ sb.append('/')
+ sb.append(pathElement)
+ }
+ else {
+ sb.append('/')
+ sb.append(pathElement.localName)
+ }
+ }
+ sb.append(']')
+ return sb.toString
+ }
+
+ def formatReference(String reference) {
+ if(reference == null || reference.isEmpty)
+ return reference
+
+ val StringTokenizer tokenizer = new StringTokenizer(reference, " ", true)
+ val StringBuilder sb = new StringBuilder();
+
+ while(tokenizer.hasMoreTokens) {
+ var String oneElement = tokenizer.nextToken
+ if (oneElement.contains("http://")) {
+ oneElement = asLink(oneElement)
+ }
+ sb.append(oneElement)
+ }
+ return sb.toString
+ }
+
+ def asLink(String text) {
+ val StringBuilder sb = new StringBuilder()
+ var tempText = text
+ var char lastChar = ' '
+ var boolean badEnding = false
+
+ if(text.endsWith(".") || text.endsWith(":") || text.endsWith(",")) {
+ tempText = text.substring(0, text.length - 1)
+ lastChar = text.charAt(text.length - 1)
+ badEnding = true
+ }
+ sb.append("<a href = \"")
+ sb.append(tempText)
+ sb.append("\">")
+ sb.append(tempText)
+ sb.append("</a>")
+
+ if(badEnding)
+ sb.append(lastChar)
+
+ return sb.toString
+ }
+
+ protected def formatToParagraph(String text) {
+ if(text == null || text.isEmpty)
+ return text
+
+ var formattedText = text
+ val StringBuilder sb = new StringBuilder();
+ var StringBuilder lineBuilder = new StringBuilder();
+ var boolean isFirstElementOnNewLineEmptyChar = false;
+
+ formattedText = formattedText.replace("*/", "*/")
+ formattedText = formattedText.replace(NEW_LINE, "")
+ formattedText = formattedText.replace("\t", "")
+ formattedText = formattedText.replaceAll(" +", " ");
+
+ val StringTokenizer tokenizer = new StringTokenizer(formattedText, " ", true);
+
+ while(tokenizer.hasMoreElements) {
+ val nextElement = tokenizer.nextElement.toString
+
+ if(lineBuilder.length + nextElement.length > 80) {
+ if (lineBuilder.charAt(lineBuilder.length - 1) == ' ') {
+ lineBuilder.setLength(0)
+ lineBuilder.append(lineBuilder.substring(0, lineBuilder.length - 1))
+ }
+ if (lineBuilder.charAt(0) == ' ') {
+ lineBuilder.setLength(0)
+ lineBuilder.append(lineBuilder.substring(1))
+ }
+
+ sb.append(lineBuilder);
+ lineBuilder.setLength(0)
+ sb.append(NEW_LINE)
+
+ if(nextElement.toString == ' ')
+ isFirstElementOnNewLineEmptyChar = !isFirstElementOnNewLineEmptyChar;
+ }
+
+ if(isFirstElementOnNewLineEmptyChar) {
+ isFirstElementOnNewLineEmptyChar = !isFirstElementOnNewLineEmptyChar
+ }
+
+ else {
+ lineBuilder.append(nextElement)
+ }
+ }
+ sb.append(lineBuilder)
+ sb.append(NEW_LINE)
+
+ return sb.toString
+ }
+
+ def isDocumentationParametersNullOrEmtpy(GeneratedType type) {
+ var boolean isNullOrEmpty = true
+ val String typeDescription = type.description
+ val String typeReference = type.reference
+ val String typeModuleName = type.moduleName
+ val Iterable<QName> typeSchemaPath = type.schemaPath
+
+ if(typeDescription != null && !typeDescription.empty) {
+ isNullOrEmpty = false
+ return isNullOrEmpty
+ }
+ if(typeReference != null && !typeReference.empty) {
+ isNullOrEmpty = false
+ return isNullOrEmpty
+ }
+ if(typeModuleName != null && !typeModuleName.empty) {
+ isNullOrEmpty = false
+ return isNullOrEmpty
+ }
+ if(typeSchemaPath != null && !typeSchemaPath.empty) {
+ isNullOrEmpty = false
+ return isNullOrEmpty
+ }
+ return isNullOrEmpty
+ }
+
def generateRestrictions(Type type, String paramName, Type returnType) '''
«val restrictions = type.getRestrictions»
«IF restrictions !== null»
import org.opendaylight.yangtools.yang.binding.Identifiable
import com.google.common.collect.Range
import org.opendaylight.yangtools.sal.binding.model.api.ConcreteType
+import com.google.common.collect.ImmutableList
/**
* Template for generating JAVA builder classes.
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
- */
+ /**
+ * 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)
* @param method method signature from which is the method name and return type obtained
* @return generated property instance for the getter <code>method</code>
* @throws IllegalArgumentException<ul>
- * <li>if the <code>method</code> equals <code>null</code></li>
- * <li>if the name of the <code>method</code> equals <code>null</code></li>
- * <li>if the name of the <code>method</code> is empty</li>
- * <li>if the return type of the <code>method</code> equals <code>null</code></li>
+ * <li>if the <code>method</code> equals <code>null</code></li>
+ * <li>if the name of the <code>method</code> equals <code>null</code></li>
+ * <li>if the name of the <code>method</code> is empty</li>
+ * <li>if the return type of the <code>method</code> equals <code>null</code></li>
* </ul>
*/
def private GeneratedProperty propertyFromGetter(MethodSignature method) {
* @return string with JAVA source code
*/
override body() '''
-
+ «wrapToDocumentation(formatDataForJavaDoc(type))»
public class «type.name»«BUILDER» {
«generateFields(false)»
«generateConstructorsFromIfcs(type)»
+ «generateCopyConstructor(false)»
+
«generateMethodFieldsFrom(type)»
«generateGetters(false)»
«generateAugmentField(false)»
- «generateConstructor»
+ «generateCopyConstructor(true)»
«generateGetters(true)»
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>
}
'''
- /**
- * Template method which generate constructor for IMPL class.
- *
- * @return string with IMPL class constructor
- */
- def private generateConstructor() '''
- private «type.name»«IMPL»(«type.name»«BUILDER» builder) {
+ def private CharSequence generateCopyConstructor(boolean impl) '''
+ «IF impl»private«ELSE»public«ENDIF» «type.name»«IF impl»«IMPL»«ELSE»«BUILDER»«ENDIF»(«type.name»«IF impl»«BUILDER»«ENDIF» base) {
«val allProps = new ArrayList(properties)»
«val isList = implementsIfc(type, Types.parameterizedTypeFor(Types.typeForClass(Identifiable), type))»
«val keyType = type.getKey»
«removeProperty(allProps, field.name)»
«ENDFOR»
«removeProperty(allProps, "key")»
- if (builder.getKey() == null) {
+ if (base.getKey() == null) {
this._key = new «keyType.importedName»(
«FOR keyProp : keyProps SEPARATOR ", "»
- builder.«keyProp.getterMethodName»()
+ base.«keyProp.getterMethodName»()
«ENDFOR»
);
«FOR field : keyProps»
- this.«field.fieldName» = builder.«field.getterMethodName»();
+ this.«field.fieldName» = base.«field.getterMethodName»();
«ENDFOR»
} else {
- this._key = builder.getKey();
+ this._key = base.getKey();
«FOR field : keyProps»
this.«field.fieldName» = _key.«field.getterMethodName»();
«ENDFOR»
}
«ENDIF»
«FOR field : allProps»
- this.«field.fieldName» = builder.«field.getterMethodName»();
+ «IF List.canonicalName.equals(field.returnType.fullyQualifiedName)»
+ if (base.«field.getterMethodName»() == null || base.«field.getterMethodName»().isEmpty()) {
+ this.«field.fieldName» = «Collections.importedName».emptyList();
+ } else {
+ this.«field.fieldName» = «ImmutableList.importedName».copyOf(base.«field.getterMethodName»());
+ }
+ «ELSE»
+ this.«field.fieldName» = base.«field.getterMethodName»();
+ «ENDIF»
«ENDFOR»
«IF augmentField != null»
- switch (builder.«augmentField.name».size()) {
- case 0:
- this.«augmentField.name» = «Collections.importedName».emptyMap();
- break;
- case 1:
- final «Map.importedName».Entry<«Class.importedName»<? extends «augmentField.returnType.importedName»>, «augmentField.returnType.importedName»> e = builder.«augmentField.name».entrySet().iterator().next();
- this.«augmentField.name» = «Collections.importedName».<«Class.importedName»<? extends «augmentField.returnType.importedName»>, «augmentField.returnType.importedName»>singletonMap(e.getKey(), e.getValue());
- break;
- default :
- this.«augmentField.name» = new «HashMap.importedName»<>(builder.«augmentField.name»);
- }
+ «IF !impl»if (base instanceof «type.name»«IMPL») {«ENDIF»
+ «IF !impl»«type.name»«IMPL» _impl = («type.name»«IMPL») base;«ENDIF»
+ «val prop = if (impl) "base" else "_impl"»
+ switch («prop».«augmentField.name».size()) {
+ case 0:
+ this.«augmentField.name» = «Collections.importedName».emptyMap();
+ break;
+ case 1:
+ final «Map.importedName».Entry<«Class.importedName»<? extends «augmentField.returnType.importedName»>, «augmentField.returnType.importedName»> e = «prop».«augmentField.name».entrySet().iterator().next();
+ this.«augmentField.name» = «Collections.importedName».<«Class.importedName»<? extends «augmentField.returnType.importedName»>, «augmentField.returnType.importedName»>singletonMap(e.getKey(), e.getValue());
+ break;
+ default :
+ this.«augmentField.name» = new «HashMap.importedName»<>(«prop».«augmentField.name»);
+ }
+ «IF !impl»}«ENDIF»
«ENDIF»
}
'''
'''
}
-
* @return string with class source code in JAVA format
*/
def protected generateBody(boolean isInnerClass) '''
- «type.comment.asJavadoc»
+ «wrapToDocumentation(formatDataForJavaDoc(type))»
«generateClassDeclaration(isInnerClass)» {
«suidDeclaration»
«innerClassesDeclarations»
«IF restrictions != null»
«val prop = getPropByName("value")»
«IF prop != null»
- «val numberClass = prop.returnType.importedNumber»
«IF !(restrictions.lengthConstraints.empty)»
- private static «List.importedName»<«Range.importedName»<«numberClass»>> _length;
+ private static «List.importedName»<«Range.importedName»<«prop.returnType.importedNumber»>> _length;
«ENDIF»
«IF !(restrictions.rangeConstraints.empty)»
- private static «List.importedName»<«Range.importedName»<«numberClass»>> _range;
+ private static «List.importedName»<«Range.importedName»<«prop.returnType.importedNumber»>> _range;
«ENDIF»
«ENDIF»
«ENDIF»
«ENDIF»
'''
-
/**
* Template method which generates the method <code>hashCode()</code>.
*
return body
}
+ def writeEnumItem(String name, int value, String description) '''
+ «asJavadoc(formatToParagraph(description))»
+ «name»(«value»)
+ '''
+
/**
* Template method which generates enumeration body (declaration + enumeration items).
*
* @return string with the enumeration body
*/
override body() '''
+ «wrapToDocumentation(formatDataForJavaDoc(enums))»
public enum «enums.name» {
- «FOR v : enums.values SEPARATOR ",\n"»
- «" "»«v.name»(«v.value»)«
- ENDFOR»;
-
+ «writeEnumeration(enums)»
+
+
int value;
static java.util.Map<java.lang.Integer, «enums.name»> valueMap;
}
}
'''
+
+ def writeEnumeration(Enumeration enumeration)
+ '''
+ «FOR v : enumeration.values SEPARATOR ",\n" AFTER ";"»
+ «writeEnumItem(v.name, v.value, v.description)»«
+ ENDFOR»
+ '''
}
enclosedGeneratedTypes = genType.enclosedTypes
}
-
-
/**
* Template method which generate the whole body of the interface.
*
* @return string with code for interface body in JAVA format
*/
override body() '''
- «type.comment.asJavadoc»
+ «wrapToDocumentation(formatDataForJavaDoc(type))»
public interface «type.name»
«superInterfaces»
{
}
def override body() '''
- «type.comment.asJavadoc»
+ «wrapToDocumentation(formatDataForJavaDoc(type))»
public class «type.name» {
«generateMethods»
import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject
import java.beans.ConstructorProperties
+import org.opendaylight.yangtools.sal.binding.model.api.Enumeration
/**
* Template for generating JAVA class.
private def unionConstructors() '''
«FOR property : finalProperties SEPARATOR "\n"»
- «val isCharArray = "char[]".equals(property.returnType.name)»
+ «val propRet = property.returnType»
+ «val isCharArray = "char[]".equals(propRet.name)»
«IF isCharArray»
/**
* Constructor provided only for using in JMX. Don't use it for
* construction new object of this union type.
*/
@«ConstructorProperties.importedName»("«property.name»")
- public «type.name»(«property.returnType.importedName» «property.fieldName») {
+ public «type.name»(«propRet.importedName» «property.fieldName») {
«String.importedName» defVal = new «String.importedName»(«property.fieldName»);
«type.name» defInst = «type.name»Builder.getDefaultInstance(defVal);
«FOR other : finalProperties»
super(«parentProperties.asArguments»);
this.«property.fieldName» = «property.fieldName»;
«FOR other : finalProperties»
- «IF property != other»this.«other.fieldName» = null;«ENDIF»
+ «IF property != other»
+ «IF "value".equals(other.name)»
+ «IF "java.lang.String".equals(propRet.fullyQualifiedName)»
+ ««« type string
+ this.«other.fieldName» = «property.fieldName».toCharArray();
+ «ELSEIF "byte[]".equals(propRet.name)»
+ ««« type binary
+ this.«other.fieldName» = new «String.importedName»(«property.fieldName»).toCharArray();
+ «ELSEIF propRet.fullyQualifiedName.startsWith("java.lang") || propRet instanceof Enumeration»
+ ««« type int*, uint or enumeration*
+ this.«other.fieldName» = «property.fieldName».toString().toCharArray();
+ «ELSEIF propRet instanceof GeneratedTransferObject && (propRet as GeneratedTransferObject).unionType»
+ ««« union type
+ this.«other.fieldName» = «property.fieldName».getValue();
+ «ELSE»
+ ««« generated type
+ this.«other.fieldName» = «property.fieldName».getValue().toString().toCharArray();
+ «ENDIF»
+ «ELSE»
+ this.«other.fieldName» = null;
+ «ENDIF»
+ «ENDIF»
«ENDFOR»
}
«ENDIF»
--- /dev/null
+/*
+ * Copyright (c) 2013 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.java.api.generator.test;
+
+import static org.junit.Assert.assertTrue;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.BASE_PKG;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.COMPILER_OUTPUT_PATH;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.FS;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.GENERATOR_OUTPUT_PATH;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.assertContainsConstructor;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.cleanUp;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.getSourceFiles;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.testCompilation;
+
+import java.io.File;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import org.junit.Test;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.java.api.generator.GeneratorJavaFile;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * Previous construction of union constructor
+ *
+ * <code>
+ * public IpAddress(Arg1 _arg1) {
+ * super();
+ * this._arg1 = _arg1;
+ * this._arg2 = null;
+ * this._value = null;
+ * }
+ * </code>
+ *
+ * was incorrect and setting
+ *
+ * <code>this._value == null</code>
+ *
+ * was replaced with setting _value to correct value, for example:
+ *
+ * <code>this._value = arg1.getValue()</code> or
+ * <code>this._value = _arg1.getValue().toString().toCharArray()</code>
+ *
+ */
+public class Bug1276Test extends BaseCompilationTest {
+
+ @Test
+ public void test() throws Exception {
+ final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "bug1276");
+ assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
+ final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "bug1276");
+ assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
+
+ generateTestSources("/compilation/bug1276", sourcesOutputDir);
+
+ // Test if sources are compilable
+ testCompilation(sourcesOutputDir, compiledOutputDir);
+
+ ClassLoader loader = new URLClassLoader(new URL[] { compiledOutputDir.toURI().toURL() });
+ Class<?> ipAddressClass = Class.forName(BASE_PKG + ".test.yang.union.rev140715.IpAddress", true, loader);
+ Class<?> ipv4AddressClass = Class.forName(BASE_PKG + ".test.yang.union.rev140715.Ipv4Address", true, loader);
+ Class<?> hostClass = Class.forName(BASE_PKG + ".test.yang.union.rev140715.Host", true, loader);
+
+ Constructor<?> ipAddressConstructor = assertContainsConstructor(ipAddressClass, ipv4AddressClass);
+ Constructor<?> ipv4addressConstructor = assertContainsConstructor(ipv4AddressClass, String.class);
+ Constructor<?> hostConstructor = assertContainsConstructor(hostClass, ipAddressClass);
+
+ // test IpAddress with Ipv4Address argument
+ Object ipv4address = ipv4addressConstructor.newInstance("192.168.0.1");
+ Object ipAddress = ipAddressConstructor.newInstance(ipv4address);
+ Method getValue = ipAddressClass.getDeclaredMethod("getValue");
+ char[] expected = "192.168.0.1".toCharArray();
+ Object actual = getValue.invoke(ipAddress);
+ assertTrue(actual instanceof char[]);
+ assertTrue(Arrays.equals(expected, (char[]) actual));
+
+ // test Host with IpAddress argument
+ Object host = hostConstructor.newInstance(ipAddress);
+ getValue = hostClass.getDeclaredMethod("getValue");
+ actual = getValue.invoke(host);
+ assertTrue(actual instanceof char[]);
+ assertTrue(Arrays.equals(expected, (char[]) actual));
+
+ cleanUp(sourcesOutputDir, compiledOutputDir);
+ }
+
+ private void generateTestSources(String resourceDirPath, File sourcesOutputDir) throws Exception {
+ final List<File> sourceFiles = getSourceFiles(resourceDirPath);
+ final SchemaContext context = parser.parseFiles(sourceFiles);
+ final List<Type> types = bindingGenerator.generateTypes(context);
+ final GeneratorJavaFile generator = new GeneratorJavaFile(new HashSet<>(types));
+ generator.generateToFile(sourcesOutputDir);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.java.api.generator.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.BASE_PKG;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.COMPILER_OUTPUT_PATH;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.FS;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.GENERATOR_OUTPUT_PATH;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.cleanUp;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.getSourceFiles;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.testCompilation;
+
+import com.google.common.collect.Lists;
+import java.io.File;
+import java.lang.reflect.Constructor;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.HashSet;
+import java.util.List;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.java.api.generator.GeneratorJavaFile;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * Test correct functionality of copy constructor of generated builder classes.
+ */
+public class Bug532Test extends BaseCompilationTest {
+
+ @Test
+ public void test() throws Exception {
+ final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "bug532");
+ assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
+ final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "bug532");
+ assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
+
+ generateTestSources("/compilation/list-gen", sourcesOutputDir);
+
+ // Test if sources are compilable
+ testCompilation(sourcesOutputDir, compiledOutputDir);
+
+ ClassLoader loader = new URLClassLoader(new URL[] { compiledOutputDir.toURI().toURL() });
+ Class<?> linksKeyClass = Class.forName(BASE_PKG + ".urn.opendaylight.test.rev131008.LinksKey", true, loader);
+ Class<?> linksClass = Class.forName(BASE_PKG + ".urn.opendaylight.test.rev131008.Links", true, loader);
+ Class<?> linksBuilderClass = Class.forName(BASE_PKG + ".urn.opendaylight.test.rev131008.LinksBuilder", true,
+ loader);
+ Class<?> levelClass = Class.forName(BASE_PKG + ".urn.opendaylight.test.rev131008.links.Level", true, loader);
+ Class<?> nodeClass = Class.forName(BASE_PKG + ".urn.opendaylight.test.rev131008.links.Node", true, loader);
+ Class<?> nodeListClass = Class.forName(BASE_PKG + ".urn.opendaylight.test.rev131008.links.NodeList", true,
+ loader);
+
+ // init default values
+ Byte expectedId = Byte.valueOf("5");
+ String expectedName = "test-link";
+ Integer expectedSize = Integer.valueOf(10);
+ Object expectedLevel = Mockito.mock(levelClass);
+ Integer expectedLinksId = Integer.valueOf(11);
+ Object expectedNode = Mockito.mock(nodeClass);
+ List<?> expectedNodeList = Lists.newArrayList(Mockito.mock(nodeListClass), Mockito.mock(nodeListClass));
+ Constructor<?> keyConstructor = linksKeyClass.getDeclaredConstructor(Byte.class, String.class, Integer.class);
+ Object expectedKey = keyConstructor.newInstance(expectedId, expectedName, expectedSize);
+
+ // create Links object
+ Object linksBuilder = linksBuilderClass.newInstance();
+ linksBuilderClass.getDeclaredMethod("setKey", linksKeyClass).invoke(linksBuilder, expectedKey);
+ linksBuilderClass.getDeclaredMethod("setLevel", levelClass).invoke(linksBuilder, expectedLevel);
+ linksBuilderClass.getDeclaredMethod("setLinksId", Integer.class).invoke(linksBuilder, expectedLinksId);
+ linksBuilderClass.getDeclaredMethod("setNode", nodeClass).invoke(linksBuilder, expectedNode);
+ linksBuilderClass.getDeclaredMethod("setNodeList", List.class).invoke(linksBuilder, expectedNodeList);
+ Object links = linksBuilderClass.getDeclaredMethod("build").invoke(linksBuilder);
+
+ // create LinksBuilder object with constructor with Links object
+ // argument
+ Constructor<?> linksBuilderConstructor = linksBuilderClass.getDeclaredConstructor(linksClass);
+ assertNotNull(linksBuilderConstructor);
+ Object linksBuilderTested = linksBuilderConstructor.newInstance(links);
+
+ // get values from LinksBuilder
+ Object actualKey = linksBuilderClass.getDeclaredMethod("getKey").invoke(linksBuilderTested);
+ Object actualId = linksBuilderClass.getDeclaredMethod("getId").invoke(linksBuilderTested);
+ Object actualName = linksBuilderClass.getDeclaredMethod("getName").invoke(linksBuilderTested);
+ Object actualSize = linksBuilderClass.getDeclaredMethod("getSize").invoke(linksBuilderTested);
+ Object actualLevel = linksBuilderClass.getDeclaredMethod("getLevel").invoke(linksBuilderTested);
+ Object actualLinksId = linksBuilderClass.getDeclaredMethod("getLinksId").invoke(linksBuilderTested);
+ Object actualNode = linksBuilderClass.getDeclaredMethod("getNode").invoke(linksBuilderTested);
+ Object actualNodeList = linksBuilderClass.getDeclaredMethod("getNodeList").invoke(linksBuilderTested);
+
+ // test
+ assertEquals(expectedKey, actualKey);
+ assertEquals(expectedId, actualId);
+ assertEquals(expectedName, actualName);
+ assertEquals(expectedSize, actualSize);
+ assertEquals(expectedLevel, actualLevel);
+ assertEquals(expectedLinksId, actualLinksId);
+ assertEquals(expectedNode, actualNode);
+ assertEquals(expectedNodeList, actualNodeList);
+
+ cleanUp(sourcesOutputDir, compiledOutputDir);
+ }
+
+ private void generateTestSources(String resourceDirPath, File sourcesOutputDir) throws Exception {
+ final List<File> sourceFiles = getSourceFiles(resourceDirPath);
+ final SchemaContext context = parser.parseFiles(sourceFiles);
+ final List<Type> types = bindingGenerator.generateTypes(context);
+ final GeneratorJavaFile generator = new GeneratorJavaFile(new HashSet<>(types));
+ generator.generateToFile(sourcesOutputDir);
+ }
+
+}
// test generated builder for 'container nodes'
assertFalse(nodesBuilderClass.isInterface());
Constructor<?>[] nodesBuilderConstructors = nodesBuilderClass.getConstructors();
- assertEquals(5, nodesBuilderConstructors.length);
+ assertEquals(6, nodesBuilderConstructors.length);
// test generation of builder constructors from uses in 'container nodes'
Constructor<?> defaultConstructor = null;
import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.assertContainsRestrictionCheck;
import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.assertFilesCount;
import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.assertImplementsIfc;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.assertImplementsParameterizedIfc;
import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.cleanUp;
import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.getSourceFiles;
import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.testCompilation;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
import com.google.common.collect.Range;
import java.io.File;
import java.lang.annotation.Annotation;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import org.junit.Test;
+import org.mockito.Mockito;
import org.opendaylight.yangtools.sal.binding.model.api.Type;
import org.opendaylight.yangtools.sal.java.api.generator.GeneratorJavaFile;
+import org.opendaylight.yangtools.yang.binding.ChildOf;
import org.opendaylight.yangtools.yang.binding.annotations.RoutingContext;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
cleanUp(sourcesOutputDir, compiledOutputDir);
}
+ /**
+ * Test if class generated for node from grouping implements ChildOf.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testBug1377() throws Exception {
+ final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "bug1377");
+ assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
+ final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "bug1377");
+ assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
+
+ generateTestSources("/compilation/bug1377", sourcesOutputDir);
+
+ // Test if sources are compilable
+ testCompilation(sourcesOutputDir, compiledOutputDir);
+
+ ClassLoader loader = new URLClassLoader(new URL[] { compiledOutputDir.toURI().toURL() });
+ Class<?> outputActionClass = Class.forName(BASE_PKG
+ + ".urn.test.foo.rev140717.action.action.output.action._case.OutputAction", true, loader);
+ Class<?> actionClass = Class.forName(BASE_PKG + ".urn.test.foo.rev140717.Action", true, loader);
+
+ // Test generated 'container output-action'
+ assertTrue(outputActionClass.isInterface());
+ assertImplementsParameterizedIfc(outputActionClass, ChildOf.class.toString(), actionClass.getCanonicalName());
+
+ cleanUp(sourcesOutputDir, compiledOutputDir);
+ }
+
+ @Test
+ public void testBug1097() throws Exception {
+ final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "bug1097");
+ assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
+ final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "bug1097");
+ assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
+
+ generateTestSources("/compilation/bug1097", sourcesOutputDir);
+
+ // Test if sources are compilable
+ testCompilation(sourcesOutputDir, compiledOutputDir);
+
+ ClassLoader loader = new URLClassLoader(new URL[] { compiledOutputDir.toURI().toURL() });
+ Class<?> linkClass = Class.forName(BASE_PKG + ".urn.test.foo.rev140717.Link", true, loader);
+ Class<?> linkBuilderClass = Class.forName(BASE_PKG + ".urn.test.foo.rev140717.LinkBuilder", true, loader);
+ Class<?> nodeClass = Class.forName(BASE_PKG + ".urn.test.foo.rev140717.link.Node", true, loader);
+
+ // Test LinkBuilder without setting any value
+ Object linkBuilder = linkBuilderClass.newInstance();
+ Method build = linkBuilderClass.getDeclaredMethod("build");
+ Object link = build.invoke(linkBuilder);
+ Method getNodes = linkClass.getDeclaredMethod("getNode");
+ Object node = getNodes.invoke(link);
+ assertEquals(Collections.emptyList(), node);
+
+ // Test LinkBuilder with setting an empty list
+ linkBuilder = linkBuilderClass.newInstance();
+ Method setNode = linkBuilderClass.getDeclaredMethod("setNode", List.class);
+ setNode.invoke(linkBuilder, Collections.emptyList());
+ link = build.invoke(linkBuilder);
+ node = getNodes.invoke(link);
+ assertEquals(Collections.emptyList(), node);
+
+ // Test LinkBuilder with setting list with values
+ linkBuilder = linkBuilderClass.newInstance();
+ List<?> testList = Lists.newArrayList(Mockito.mock(nodeClass), Mockito.mock(nodeClass));
+ setNode.invoke(linkBuilder, testList);
+ link = build.invoke(linkBuilder);
+ node = getNodes.invoke(link);
+ assertEquals(testList, node);
+ assertTrue(node instanceof ImmutableList);
+
+ cleanUp(sourcesOutputDir, compiledOutputDir);
+ }
+
@Test
public void classNamesColisionTest() throws Exception {
final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "class-name-collision");
static final String COMPILER_OUTPUT_PATH = TEST_PATH + FS + "bin";
static final File COMPILER_OUTPUT_DIR = new File(COMPILER_OUTPUT_PATH);
+ static final String AUGMENTATION = "interface org.opendaylight.yangtools.yang.binding.Augmentation";
+
static final String BASE_PATH = "org" + FS + "opendaylight" + FS + "yang" + FS + "gen" + FS + "v1";
static final String NS_TEST = BASE_PATH + FS + "urn" + FS + "opendaylight" + FS + "test" + FS + "rev131008";
static final String NS_FOO = BASE_PATH + FS + "urn" + FS + "opendaylight" + FS + "foo" + FS + "rev131008";
* fully qualified name of expected parameter type
*/
static void testAugmentation(Class<?> clazz, String genericTypeName) {
- final String ifcName = "interface org.opendaylight.yangtools.yang.binding.Augmentation";
- assertImplementsParameterizedIfc(clazz, ifcName, genericTypeName);
+ assertImplementsParameterizedIfc(clazz, AUGMENTATION, genericTypeName);
}
/**
// typedef string-ext3
assertFalse(stringExt3Class.isInterface());
- assertContainsFieldWithValue(stringExt3Class, "serialVersionUID", Long.TYPE, -2751063130555484180L, String.class);
+ assertContainsFieldWithValue(stringExt3Class, "serialVersionUID", Long.TYPE, -2751063130555484180L,
+ String.class);
assertEquals(1, stringExt3Class.getDeclaredFields().length);
expectedConstructor = assertContainsConstructor(stringExt3Class, String.class);
assertContainsConstructor(stringExt3Class, stringExt3Class);
assertFalse(myDecimalTypeClass.isInterface());
assertContainsField(myDecimalTypeClass, VAL, BigDecimal.class);
assertContainsField(myDecimalTypeClass, RANGE, List.class);
- assertContainsFieldWithValue(myDecimalTypeClass, "serialVersionUID", Long.TYPE, 3143735729419861095L, BigDecimal.class);
+ assertContainsFieldWithValue(myDecimalTypeClass, "serialVersionUID", Long.TYPE, 3143735729419861095L,
+ BigDecimal.class);
assertEquals(3, myDecimalTypeClass.getDeclaredFields().length);
assertContainsMethod(myDecimalTypeClass, BigDecimal.class, "getValue");
expectedConstructor = assertContainsConstructor(myDecimalTypeClass, BigDecimal.class);
assertFalse(unionExt1Class.isInterface());
assertContainsField(unionExt1Class, "_int16", Short.class);
assertContainsField(unionExt1Class, "_int32", Integer.class);
- assertContainsFieldWithValue(unionExt1Class, "serialVersionUID", Long.TYPE, -5610530488718168882L, Short.class);
+ assertContainsFieldWithValue(unionExt1Class, "serialVersionUID", Long.TYPE, -5610530488718168882L,
+ new Class<?>[] { Short.class }, Short.valueOf("1"));
assertEquals(4, unionExt1Class.getDeclaredFields().length);
assertContainsMethod(unionExt1Class, Short.class, "getInt16");
assertContainsMethod(unionExt1Class, Integer.class, "getInt32");
// typedef union-ext2
assertFalse(unionExt2Class.isInterface());
- assertContainsFieldWithValue(unionExt2Class, "serialVersionUID", Long.TYPE, -8833407459073585206L, Short.class);
+ assertContainsFieldWithValue(unionExt2Class, "serialVersionUID", Long.TYPE, -8833407459073585206L,
+ new Class<?>[] { Short.class }, Short.valueOf("1"));
assertEquals(1, unionExt2Class.getDeclaredFields().length);
assertEquals(0, unionExt2Class.getDeclaredMethods().length);
assertContainsConstructor(unionExt2Class, Short.class);
assertFalse(unionExt3Class.isInterface());
assertContainsField(unionExt3Class, "_string", String.class);
assertContainsField(unionExt3Class, "_unionExt2", unionExt2Class);
- assertContainsFieldWithValue(unionExt3Class, UNITS, String.class, "object id", String.class);
- assertContainsFieldWithValue(unionExt3Class, "serialVersionUID", Long.TYPE, 4347887914884631036L, String.class);
+ assertContainsFieldWithValue(unionExt3Class, UNITS, String.class, "object id", new Class<?>[] { String.class },
+ "");
+ assertContainsFieldWithValue(unionExt3Class, "serialVersionUID", Long.TYPE, 4347887914884631036L,
+ new Class<?>[] { String.class }, "");
assertEquals(5, unionExt3Class.getDeclaredFields().length);
assertContainsMethod(unionExt3Class, String.class, "getString");
assertContainsMethod(unionExt3Class, unionExt2Class, "getUnionExt2");
assertContainsField(unionExt4Class, "_int32Ext2", int32Ext2Class);
assertContainsField(unionExt4Class, "_empty", Boolean.class);
assertContainsField(unionExt4Class, "_myDecimalType", myDecimalTypeClass);
- assertContainsFieldWithValue(unionExt4Class, "serialVersionUID", Long.TYPE, 4299836385615211130L, Boolean.class);
+ assertContainsFieldWithValue(unionExt4Class, "serialVersionUID", Long.TYPE, 4299836385615211130L,
+ new Class<?>[] { Boolean.class }, false);
assertEquals(6, unionExt4Class.getDeclaredFields().length);
assertContainsMethod(unionExt4Class, unionExt3Class, "getUnionExt3");
assertContainsMethod(unionExt4Class, int32Ext2Class, "getInt32Ext2");
yang-version 1;
namespace "urn:opendaylight.bar";
prefix "bar";
+
+ description "bar - Network topology is the arrangement of the various elements (links, nodes, etc.) of a computer network.[1][2] Essentially, it is the topological[3] structure of a network, and may be depicted physically or logically. Physical topology is the placement of the various components of a network, including device location and cable installation, while logical topology illustrates how data flows within a network, regardless of its physical design. Distances between nodes, physical interconnections, transmission rates, or signal types may differ between two networks, yet their topologies may be identical.";
+ reference "RFC 6020 - http://tools.ietf.org/html/rfc6020";
revision "2013-10-08" {
}
container network-topology {
+ description "network-topology - Network topology is the arrangement of the various elements (links, nodes, etc.) of a computer network.[1][2] Essentially, it is the topological[3] structure of a network, and may be depicted physically or logically. Physical topology is the placement of the various components of a network, including device location and cable installation, while logical topology illustrates how data flows within a network, regardless of its physical design. Distances between nodes, physical interconnections, transmission rates, or signal types may differ between two networks, yet their topologies may be identical.";
+ reference "RFC 6020 - http://tools.ietf.org/html/rfc6020";
+
list topology {
+ description "topology - Network topology is the arrangement of the various elements (links, nodes, etc.) of a computer network.[1][2] Essentially, it is the topological[3] structure of a network, and may be depicted physically or logically. Physical topology is the placement of the various components of a network, including device location and cable installation, while logical topology illustrates how data flows within a network, regardless of its physical design. Distances between nodes, physical interconnections, transmission rates, or signal types may differ between two networks, yet their topologies may be identical.";
+ reference "RFC 6020 - http://tools.ietf.org/html/rfc6020";
+
key "topology-id";
leaf topology-id {
+ description "topology-id - Network topology is the arrangement of the various elements (links, nodes, etc.) of a computer network.[1][2] Essentially, it is the topological[3] structure of a network, and may be depicted physically or logically. Physical topology is the placement of the various components of a network, including device location and cable installation, while logical topology illustrates how data flows within a network, regardless of its physical design. Distances between nodes, physical interconnections, transmission rates, or signal types may differ between two networks, yet their topologies may be identical.";
+ reference "RFC 6020 - http://tools.ietf.org/html/rfc6020";
type int32;
}
uses link;
grouping link {
list link {
+ description "Link - Network topology is the arrangement of the various elements (links, nodes, etc.) of a computer network.[1][2] Essentially, it is the topological[3] structure of a network, and may be depicted physically or logically. Physical topology is the placement of the various components of a network, including device location and cable installation, while logical topology illustrates how data flows within a network, regardless of its physical design. Distances between nodes, physical interconnections, transmission rates, or signal types may differ between two networks, yet their topologies may be identical.";
+ reference "RFC 6020 - http://tools.ietf.org/html/rfc6020";
key "link-id";
uses link-attributes;
}
grouping link-attributes {
leaf link-id {
+ description "Link-attributes - Network topology is the arrangement of the various elements (links, nodes, etc.) of a computer network.[1][2] Essentially, it is the topological[3] structure of a network, and may be depicted physically or logically. Physical topology is the placement of the various components of a network, including device location and cable installation, while logical topology illustrates how data flows within a network, regardless of its physical design. Distances between nodes, physical interconnections, transmission rates, or signal types may differ between two networks, yet their topologies may be identical.";
+ reference "RFC 6020 - http://tools.ietf.org/html/rfc6020";
type int8;
}
}
+
+ leaf inclusion-rulez {
+ description "Specified rulez description.";
+ reference "RFC 6020 http://technet.com";
+
+ type string;
+ }
+ leaf inclusion-rule {
+ description "Specify how inheritance will work for this label";
+ default include;
+
+ type enumeration {
+ enum include {
+ description
+ "This label will be included normally in the
+ matching. This seems to be a little bit longer comment. I hear you very weel my darling.
+ Network topology is the arrangement of the various elements (links, nodes, etc.) of any other builder nodes types.";
+ }
+ enum exclude {
+ description
+ "This label will be excluded from the
+ matching. This allows removing labels that
+ would have otherwise been included because of
+ inheritence rules.";
+ }
+ }
+ }
}
prefix "br";
revision-date 2013-10-08;
}
+
+ description "Baz - Network topology is the arrangement of the various elements (links, nodes, etc.) of a computer network.[1][2] Essentially, it is the topological[3] structure of a network, and may be depicted physically or logically. Physical topology is the placement of the various components of a network, including device location and cable installation, while logical topology illustrates how data flows within a network, regardless of its physical design. Distances between nodes, physical interconnections, transmission rates, or signal types may differ between two networks, yet their topologies may be identical.";
+ reference "RFC 6020 - http://tools.ietf.org/html/rfc6020";
revision "2013-10-08" {
}
grouping link-attributes {
container ospf-link-attributes {
+ description "Ospf-link-attributes - Network topology is the arrangement of the various elements (links, nodes, etc.) of a computer network.[1][2] Essentially, it is the topological[3] structure of a network, and may be depicted physically or logically. Physical topology is the placement of the various components of a network, including device location and cable installation, while logical topology illustrates how data flows within a network, regardless of its physical design. Distances between nodes, physical interconnections, transmission rates, or signal types may differ between two networks, yet their topologies may be identical.";
+ reference "RFC 6020 - http://tools.ietf.org/html/rfc6020";
leaf multi-topology-id {
+ description "Multi-topology-id - Network topology is the arrangement of the various elements (links, nodes, etc.) of a computer network.[1][2] Essentially, it is the topological[3] structure of a network, and may be depicted physically or logically. Physical topology is the placement of the various components of a network, including device location and cable installation, while logical topology illustrates how data flows within a network, regardless of its physical design. Distances between nodes, physical interconnections, transmission rates, or signal types may differ between two networks, yet their topologies may be identical.";
+ reference "RFC 6020 - http://tools.ietf.org/html/rfc6020";
+
type uint8 {
range "0..127";
}
prefix "br";
revision-date 2013-10-08;
}
+
+ description "Foo - Network topology is the arrangement of the various elements (links, nodes, etc.) of a computer network.[1][2] Essentially, it is the topological[3] structure of a network, and may be depicted physically or logically. Physical topology is the placement of the various components of a network, including device location and cable installation, while logical topology illustrates how data flows within a network, regardless of its physical design. Distances between nodes, physical interconnections, transmission rates, or signal types may differ between two networks, yet their topologies may be identical.";
+ reference "RFC 6020 - http://tools.ietf.org/html/rfc6020";
revision "2013-10-08" {
}
grouping igp-link-attributes {
container igp-link-attributes {
+ description "Igp-link-attributes - Network topology is the arrangement of the various elements (links, nodes, etc.) of a computer network.[1][2] Essentially, it is the topological[3] structure of a network, and may be depicted physically or logically. Physical topology is the placement of the various components of a network, including device location and cable installation, while logical topology illustrates how data flows within a network, regardless of its physical design. Distances between nodes, physical interconnections, transmission rates, or signal types may differ between two networks, yet their topologies may be identical.";
+ reference "RFC 6020 - http://tools.ietf.org/html/rfc6020";
+
leaf name {
+ description "Name - Network topology is the arrangement of the various elements (links, nodes, etc.) of a computer network.[1][2] Essentially, it is the topological[3] structure of a network, and may be depicted physically or logically. Physical topology is the placement of the various components of a network, including device location and cable installation, while logical topology illustrates how data flows within a network, regardless of its physical design. Distances between nodes, physical interconnections, transmission rates, or signal types may differ between two networks, yet their topologies may be identical.";
+ reference "RFC 6020 - http://tools.ietf.org/html/rfc6020";
type string;
}
leaf-list flag {
+ description "Flag - Network topology is the arrangement of the various elements (links, nodes, etc.) of a computer network.[1][2] Essentially, it is the topological[3] structure of a network, and may be depicted physically or logically. Physical topology is the placement of the various components of a network, including device location and cable installation, while logical topology illustrates how data flows within a network, regardless of its physical design. Distances between nodes, physical interconnections, transmission rates, or signal types may differ between two networks, yet their topologies may be identical.";
+ reference "RFC 6020 - http://tools.ietf.org/html/rfc6020";
type string;
}
leaf metric {
+ description "Metric - Network topology is the arrangement of the various elements (links, nodes, etc.) of a computer network.[1][2] Essentially, it is the topological[3] structure of a network, and may be depicted physically or logically. Physical topology is the placement of the various components of a network, including device location and cable installation, while logical topology illustrates how data flows within a network, regardless of its physical design. Distances between nodes, physical interconnections, transmission rates, or signal types may differ between two networks, yet their topologies may be identical.";
+ reference "RFC 6020 - http://tools.ietf.org/html/rfc6020";
type uint32 {
range "0..16777215" {
}
--- /dev/null
+module foo {
+ namespace "urn:test:foo";
+ prefix foo;
+
+ revision 2014-07-17 {
+ }
+
+
+ container link {
+ list node {
+ leaf id {
+ type string;
+ }
+ }
+ }
+
+}
--- /dev/null
+ module foo {
+
+ namespace "test:yang:union";
+ prefix "foo";
+
+ revision 2014-07-15 {
+ }
+
+
+ typedef ip-address {
+ type union {
+ type ipv4-address;
+ type ipv6-address;
+ }
+ }
+
+ typedef ipv4-address {
+ type string {
+ pattern
+ '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
+ + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
+ + '(%[\p{N}\p{L}]+)?';
+ }
+ }
+
+ typedef ipv6-address {
+ type string {
+ pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
+ + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
+ + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
+ + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
+ + '(%[\p{N}\p{L}]+)?';
+ pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
+ + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
+ + '(%.+)?';
+ }
+ }
+
+ typedef domain-name {
+ type string {
+ pattern '((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*'
+ + '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)'
+ + '|\.';
+ length "1..253";
+ }
+ }
+
+ typedef host {
+ type union {
+ type ip-address;
+ type domain-name;
+ }
+ }
+
+ typedef int-type {
+ type union {
+ type binary;
+ type int8;
+ }
+ }
+
+ }
--- /dev/null
+module foo {
+ namespace "urn:test:foo";
+ prefix foo;
+
+ revision 2014-07-17 {
+ }
+
+
+ grouping action {
+ choice action {
+ case output-action-case {
+ container output-action {
+ leaf id {
+ type string;
+ }
+ }
+ }
+ }
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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;
+
+import org.opendaylight.yangtools.yang.common.QName;
+
+/**
+ * Implementing this interface allows an object to hold information which are
+ * essential for generating java doc from type definition.
+ */
+public interface DocumentedType {
+
+ /**
+ * Returns a string that contains a human-readable textual description of
+ * type definition.
+ *
+ * @return a human-readable textual description of type definition.
+ */
+ String getDescription();
+
+ /**
+ * Returns a string that is used to specify a textual cross-reference to an
+ * external document, either another module that defines related management
+ * information, or a document that provides additional information relevant
+ * to this definition.
+ *
+ * @return a textual cross-reference to an external document.
+ */
+ String getReference();
+
+ /**
+ * Returns a list of QNames which represent schema path in schema tree from
+ * actual concrete type to the root.
+ *
+ * @return a schema path in schema tree from actual concrete schema node
+ * identifier to the root.
+ */
+ Iterable<QName> getSchemaPath();
+
+ /**
+ * Returns the name of the module, in which generated type was specified.
+ *
+ * @return the name of the module, in which generated type was specified.
+ */
+ String getModuleName();
+}
import java.util.List;
+import org.opendaylight.yangtools.yang.model.api.DocumentedNode;
+
/**
* Interface provide methods for reading data of enumeration class.
*/
public interface Enumeration extends GeneratedType {
/**
- *
+ *
* Returns list of annotation definitions associated with enumeration type.
- *
+ *
* @return list of annotation definitions associated with enumeration type.
- *
+ *
*/
+ @Override
List<AnnotationType> getAnnotations();
+ @Override
Type getParentType();
/**
* Returns list of the couples - name and value.
- *
+ *
* @return list of the enumeration pairs.
*/
List<Pair> getValues();
/**
* Formats enumeration according to rules of the programming language.
- *
+ *
* @return string with source code in some programming language
*/
String toFormattedString();
* Interface is used for reading enumeration item. It means item's name and
* its value.
*/
- interface Pair {
+ interface Pair extends DocumentedNode {
/**
* Returns the name of the enumeration item.
- *
+ *
* @return the name of the enumeration item.
*/
String getName();
/**
* Returns value of the enumeration item.
- *
+ *
* @return the value of the enumeration item.
*/
Integer getValue();
* <li><code>method definitions</code> with specified input parameters (with
* types) and return values</li>
* </ul>
- *
+ *
* By the definition of the interface constant, enum, enclosed types and method
* definitions MUST be public, so there is no need to specify the scope of
* visibility.
*/
-public interface GeneratedType extends Type {
+public interface GeneratedType extends Type, DocumentedType {
/**
* Returns the parent type if Generated Type is defined as enclosing type,
* otherwise returns <code>null</code>
- *
+ *
* @return the parent type if Generated Type is defined as enclosing type,
* otherwise returns <code>null</code>
*/
/**
* Returns comment string associated with Generated Type.
- *
+ *
* @return comment string associated with Generated Type.
*/
String getComment();
/**
* Returns List of annotation definitions associated with generated type.
- *
+ *
* @return List of annotation definitions associated with generated type.
*/
List<AnnotationType> getAnnotations();
/**
* Returns <code>true</code> if The Generated Type is defined as abstract.
- *
+ *
* @return <code>true</code> if The Generated Type is defined as abstract.
*/
boolean isAbstract();
/**
* Returns List of Types that Generated Type will implement.
- *
+ *
* @return List of Types that Generated Type will implement.
*/
List<Type> getImplements();
/**
* Returns List of enclosing Generated Types.
- *
+ *
* @return List of enclosing Generated Types.
*/
List<GeneratedType> getEnclosedTypes();
/**
* Returns List of all Enumerator definitions associated with Generated
* Type.
- *
+ *
* @return List of all Enumerator definitions associated with Generated
* Type.
*/
/**
* Returns List of Constant definitions associated with Generated Type.
- *
+ *
* @return List of Constant definitions associated with Generated Type.
*/
List<Constant> getConstantDefinitions();
/**
* Returns List of Method Definitions associated with Generated Type.
- *
+ *
* List does not contains getters and setters for properties.
- *
+ *
* @return List of Method Definitions associated with Generated Type.
*/
List<MethodSignature> getMethodDefinitions();
/**
* Returns List of Properties that are declared for Generated Transfer
* Object.
- *
+ *
* @return List of Properties that are declared for Generated Transfer
* Object.
*/
/**
* Enum Builder is interface that contains methods to build and instantiate
* Enumeration definition.
- *
+ *
* @see Enumeration
*/
public interface EnumBuilder extends Type {
* Neither the package name or annotation name can contain <code>null</code>
* references. In case that any of parameters contains <code>null</code> the
* method SHOULD thrown {@link IllegalArgumentException}
- *
+ *
* @param packageName
* Package Name of Annotation Type
* @param name
AnnotationTypeBuilder addAnnotation(final String packageName, final String name);
/**
- *
+ *
* @param name
* @param value
*/
- void addValue(final String name, final Integer value);
+ void addValue(final String name, final Integer value, final String description);
/**
- *
+ *
* @param definingType
* @return
*/
/**
* Updates this builder with data from <code>enumTypeDef</code>.
* Specifically this data represents list of value-name pairs.
- *
+ *
* @param enumTypeDef
* enum type definition as source of enum data for
* <code>enumBuilder</code>
*/
void updateEnumPairsFromEnumTypeDef(final EnumTypeDefinition enumTypeDef);
+ /**
+ * @param description
+ */
+ void setDescription(final String description);
+
}
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;
public interface GeneratedTypeBuilderBase<T extends GeneratedTypeBuilderBase<T>> extends Type {
*/
boolean containsProperty(final String name);
+ /**
+ * Set a string that contains a human-readable textual description of type
+ * definition.
+ *
+ * @param description
+ * a string that contains a human-readable textual description of
+ * type definition.
+ */
+ public void setDescription(String description);
+
+ /**
+ * Set the name of the module, in which generated type was specified.
+ *
+ * @param moduleName
+ * the name of the module
+ */
+ public void setModuleName(String moduleName);
+
+ /**
+ * Set a list of QNames which represent schema path in schema tree from
+ * actual concrete type to the root.
+ *
+ * @param schemaPath
+ * a list of QNames which represent schema path in schema tree
+ */
+ public void setSchemaPath(Iterable<QName> schemaPath);
+
+ /**
+ * Set a string that is used to specify a textual cross-reference to an
+ * external document, either another module that defines related management
+ * information, or a document that provides additional information relevant
+ * to this definition.
+ *
+ * @param reference
+ * a textual cross-reference to an external document.
+ */
+ public void setReference(String reference);
+
}
import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findDataSchemaNodeForRelativeXPath;
import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findParentModule;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Sets;
-import com.google.common.io.BaseEncoding;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+
import org.apache.commons.lang3.StringEscapeUtils;
import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil;
import org.opendaylight.yangtools.binding.generator.util.TypeConstants;
import org.opendaylight.yangtools.yang.model.util.Uint8;
import org.opendaylight.yangtools.yang.model.util.UnionType;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Sets;
+import com.google.common.io.BaseEncoding;
+
public final class TypeProviderImpl implements TypeProvider {
private static final Pattern NUMBERS_PATTERN = Pattern.compile("[0-9]+\\z");
Preconditions.checkArgument(typeDefinition.getQName() != null,
"Type Definition cannot have non specified QName (QName cannot be NULL!)");
String typedefName = typeDefinition.getQName().getLocalName();
- Preconditions.checkArgument(typedefName != null,
- "Type Definitions Local Name cannot be NULL!");
+ Preconditions.checkArgument(typedefName != null, "Type Definitions Local Name cannot be NULL!");
if (typeDefinition instanceof ExtendedType) {
returnType = javaTypeForExtendedType(typeDefinition);
Module module = findParentModule(schemaContext, parentNode);
final String basePackageName = moduleNamespaceToPackageName(module);
- final EnumBuilder enumBuilder = new EnumerationBuilderImpl(basePackageName, enumerationName);
+ final EnumerationBuilderImpl enumBuilder = new EnumerationBuilderImpl(basePackageName, enumerationName);
+ enumBuilder.setDescription(enumTypeDef.getDescription());
+ enumBuilder.setReference(enumTypeDef.getReference());
+ enumBuilder.setModuleName(module.getName());
+ enumBuilder.setSchemaPath(enumTypeDef.getPath().getPathFromRoot());
enumBuilder.updateEnumPairsFromEnumTypeDef(enumTypeDef);
return enumBuilder.toInstance(null);
}
final String enumerationName = BindingMapping.getClassName(enumName);
final EnumBuilder enumBuilder = typeBuilder.addEnumeration(enumerationName);
+ enumBuilder.setDescription(enumTypeDef.getDescription());
enumBuilder.updateEnumPairsFromEnumTypeDef(enumTypeDef);
return enumBuilder.toInstance(enumBuilder);
}
for (Module modul : modules) {
modulesArray[i++] = modul;
}
- final List<Module> modulesSortedByDependency = org.opendaylight.yangtools.yang.parser.util.ModuleDependencySort.sort(modulesArray);
+ final List<Module> modulesSortedByDependency = org.opendaylight.yangtools.yang.parser.util.ModuleDependencySort
+ .sort(modulesArray);
for (final Module module : modulesSortedByDependency) {
Map<Date, Map<String, Type>> dateTypeMap = genTypeDefsContextMap.get(module.getName());
Type returnType = null;
if (innerTypeDefinition instanceof ExtendedType) {
ExtendedType innerExtendedType = (ExtendedType) innerTypeDefinition;
- returnType = provideGeneratedTOFromExtendedType(typedef, innerExtendedType, basePackageName);
+ returnType = provideGeneratedTOFromExtendedType(typedef, innerExtendedType, basePackageName,
+ module.getName());
} else if (innerTypeDefinition instanceof UnionTypeDefinition) {
final GeneratedTOBuilder genTOBuilder = provideGeneratedTOBuilderForUnionTypeDef(basePackageName,
(UnionTypeDefinition) innerTypeDefinition, typedefName, typedef);
} else if (innerTypeDefinition instanceof BitsTypeDefinition) {
final BitsTypeDefinition bitsTypeDefinition = (BitsTypeDefinition) innerTypeDefinition;
final GeneratedTOBuilder genTOBuilder = provideGeneratedTOBuilderForBitsTypeDefinition(
- basePackageName, bitsTypeDefinition, typedefName);
+ basePackageName, bitsTypeDefinition, typedefName, module.getName());
genTOBuilder.setTypedef(true);
addUnitsToGenTO(genTOBuilder, typedef.getUnits());
makeSerializable((GeneratedTOBuilderImpl) genTOBuilder);
} else {
final Type javaType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(
innerTypeDefinition, typedef);
- returnType = wrapJavaTypeIntoTO(basePackageName, typedef, javaType);
+ returnType = wrapJavaTypeIntoTO(basePackageName, typedef, javaType, module.getName());
}
if (returnType != null) {
final Map<Date, Map<String, Type>> modulesByDate = genTypeDefsContextMap.get(moduleName);
* @return generated transfer object which represent<code>javaType</code>
*/
private GeneratedTransferObject wrapJavaTypeIntoTO(final String basePackageName, final TypeDefinition<?> typedef,
- final Type javaType) {
+ final Type javaType, final String moduleName) {
Preconditions.checkNotNull(javaType, "javaType cannot be null");
final String propertyName = "value";
- final GeneratedTOBuilder genTOBuilder = typedefToTransferObject(basePackageName, typedef);
+ final GeneratedTOBuilder genTOBuilder = typedefToTransferObject(basePackageName, typedef, moduleName);
genTOBuilder.setRestrictions(BindingGeneratorUtil.getRestrictions(typedef));
final GeneratedPropertyBuilder genPropBuilder = genTOBuilder.addProperty(propertyName);
genPropBuilder.setReturnType(javaType);
final List<GeneratedTOBuilder> generatedTOBuilders = new ArrayList<>();
final List<TypeDefinition<?>> unionTypes = typedef.getTypes();
+ final Module module = findParentModule(schemaContext, parentNode);
- final GeneratedTOBuilder unionGenTOBuilder;
+ final GeneratedTOBuilderImpl unionGenTOBuilder;
if (typeDefName != null && !typeDefName.isEmpty()) {
final String typeName = BindingMapping.getClassName(typeDefName);
unionGenTOBuilder = new GeneratedTOBuilderImpl(basePackageName, typeName);
+ unionGenTOBuilder.setDescription(typedef.getDescription());
+ unionGenTOBuilder.setReference(typedef.getReference());
+ unionGenTOBuilder.setSchemaPath(typedef.getPath().getPathFromRoot());
+ unionGenTOBuilder.setModuleName(module.getName());
} else {
- unionGenTOBuilder = typedefToTransferObject(basePackageName, typedef);
+ unionGenTOBuilder = typedefToTransferObject(basePackageName, typedef, module.getName());
}
generatedTOBuilders.add(unionGenTOBuilder);
* list of strings with the regular expressions
*/
private void resolveExtendedSubtypeAsUnion(final GeneratedTOBuilder parentUnionGenTOBuilder,
- final ExtendedType unionSubtype, final List<String> regularExpressions,
- final SchemaNode parentNode) {
+ final ExtendedType unionSubtype, final List<String> regularExpressions, final SchemaNode parentNode) {
final String unionTypeName = unionSubtype.getQName().getLocalName();
final Type genTO = findGenTO(unionTypeName, unionSubtype);
if (genTO != null) {
* generated TO builder which is converted to generated TO and
* stored
*/
- private void storeGenTO(final TypeDefinition<?> newTypeDef, final GeneratedTOBuilder genTOBuilder, final SchemaNode parentNode) {
+ private void storeGenTO(final TypeDefinition<?> newTypeDef, final GeneratedTOBuilder genTOBuilder,
+ final SchemaNode parentNode) {
if (!(newTypeDef instanceof UnionType)) {
final Module parentModule = findParentModule(schemaContext, parentNode);
* @return generated TO builder which contains data from
* <code>typedef</code> and <code>basePackageName</code>
*/
- private GeneratedTOBuilder typedefToTransferObject(final String basePackageName, final TypeDefinition<?> typedef) {
+ private GeneratedTOBuilderImpl typedefToTransferObject(final String basePackageName,
+ final TypeDefinition<?> typedef, final String moduleName) {
final String packageName = packageNameForGeneratedType(basePackageName, typedef.getPath());
final String typeDefTOName = typedef.getQName().getLocalName();
if ((packageName != null) && (typedef != null) && (typeDefTOName != null)) {
final String genTOName = BindingMapping.getClassName(typeDefTOName);
- final GeneratedTOBuilder newType = new GeneratedTOBuilderImpl(packageName, genTOName);
- newType.addComment(typedef.getDescription());
+ final GeneratedTOBuilderImpl newType = new GeneratedTOBuilderImpl(packageName, genTOName);
+
+ newType.setDescription(typedef.getDescription());
+ newType.setReference(typedef.getReference());
+ newType.setSchemaPath(typedef.getPath().getPathFromRoot());
+ newType.setModuleName(moduleName);
+
return newType;
}
return null;
* </ul>
*/
public GeneratedTOBuilder provideGeneratedTOBuilderForBitsTypeDefinition(final String basePackageName,
- final TypeDefinition<?> typeDef, final String typeDefName) {
+ final TypeDefinition<?> typeDef, final String typeDefName, final String moduleName) {
Preconditions.checkArgument(typeDef != null, "typeDef cannot be NULL!");
Preconditions.checkArgument(basePackageName != null, "Base Package Name cannot be NULL!");
BitsTypeDefinition bitsTypeDefinition = (BitsTypeDefinition) typeDef;
final String typeName = BindingMapping.getClassName(typeDefName);
- final GeneratedTOBuilder genTOBuilder = new GeneratedTOBuilderImpl(basePackageName, typeName);
+ final GeneratedTOBuilderImpl genTOBuilder = new GeneratedTOBuilderImpl(basePackageName, typeName);
+
+ genTOBuilder.setDescription(typeDef.getDescription());
+ genTOBuilder.setReference(typeDef.getReference());
+ genTOBuilder.setSchemaPath(typeDef.getPath().getPathFromRoot());
+ genTOBuilder.setModuleName(moduleName);
final List<Bit> bitList = bitsTypeDefinition.getBits();
GeneratedPropertyBuilder genPropertyBuilder;
* </ul>
*/
private GeneratedTransferObject provideGeneratedTOFromExtendedType(final TypeDefinition<?> typedef,
- final ExtendedType innerExtendedType, final String basePackageName) {
+ final ExtendedType innerExtendedType, final String basePackageName, final String moduleName) {
Preconditions.checkArgument(innerExtendedType != null, "Extended type cannot be NULL!");
Preconditions.checkArgument(basePackageName != null, "String with base package name cannot be NULL!");
final String classTypedefName = BindingMapping.getClassName(typedefName);
final String innerTypeDef = innerExtendedType.getQName().getLocalName();
final GeneratedTOBuilderImpl genTOBuilder = new GeneratedTOBuilderImpl(basePackageName, classTypedefName);
+
+ genTOBuilder.setDescription(typedef.getDescription());
+ genTOBuilder.setReference(typedef.getReference());
+ genTOBuilder.setSchemaPath(typedef.getPath().getPathFromRoot());
+ genTOBuilder.setModuleName(moduleName);
genTOBuilder.setTypedef(true);
Restrictions r = BindingGeneratorUtil.getRestrictions(typedef);
genTOBuilder.setRestrictions(r);
return sb.toString();
}
- private String bitsToDef(final BitsTypeDefinition type, final String className, final String defaultValue, final boolean isExt) {
+ private String bitsToDef(final BitsTypeDefinition type, final String className, final String defaultValue,
+ final boolean isExt) {
List<Bit> bits = new ArrayList<>(type.getBits());
Collections.sort(bits, new Comparator<Bit>() {
@Override
<groupId>org.eclipse.xtend</groupId>
<artifactId>xtend-maven-plugin</artifactId>
</plugin>
- <plugin>
- <artifactId>maven-clean-plugin</artifactId>
- </plugin>
</plugins>
</build>
</dependency>
</dependencies>
</plugin>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>build-helper-maven-plugin</artifactId>
- <executions>
- <execution>
- <phase>generate-sources</phase>
- <goals>
- <goal>add-source</goal>
- </goals>
- <configuration>
- <sources>
- <source>target/generated-sources/sal</source>
- </sources>
- </configuration>
- </execution>
- </executions>
- </plugin>
</plugins>
</build>
<dependencies>
</dependency>
</dependencies>
</plugin>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>build-helper-maven-plugin</artifactId>
- <executions>
- <execution>
- <phase>generate-sources</phase>
- <goals>
- <goal>add-source</goal>
- </goals>
- <configuration>
- <sources>
- <source>target/generated-sources/sal</source>
- </sources>
- </configuration>
- </execution>
- </executions>
- </plugin>
</plugins>
</build>
<dependencies>
<feature version='${project.version}'>yangtools-common</feature>
<feature version='${project.version}'>yangtools-concepts</feature>
<feature version='${project.version}'>yangtools-binding-generator</feature>
+ <feature version='${project.version}'>yangtools-restconf</feature>
</feature>
<feature name='yangtools-models' version='${project.version}'>
<bundle>mvn:org.opendaylight.yangtools/yang-model-util/${project.version}</bundle>
<bundle>mvn:org.opendaylight.yangtools/yang-parser-api/${project.version}</bundle>
</feature>
+ <feature name="yangtools-restconf" version='${project.version}'>
+ <bundle>mvn:org.opendaylight.yangtools/restconf-client-api/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.yangtools/restconf-client-impl/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.yangtools/restconf-common/${project.version}</bundle>
+ </feature>
+
</features>
<execute />
</action>
</pluginExecution>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <versionRange>[1.0,)</versionRange>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <execute/>
+ </action>
+ </pluginExecution>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <versionRange>[0.5,)</versionRange>
+ <goals>
+ <goal>generate-sources</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <ignore />
+ </action>
+ </pluginExecution>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>properties-maven-plugin</artifactId>
+ <versionRange>1.0-alpha-2</versionRange>
+ <goals>
+ <goal>write-project-properties</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <ignore />
+ </action>
+ </pluginExecution>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>org.ops4j.pax.exam</groupId>
+ <artifactId>maven-paxexam-plugin</artifactId>
+ <versionRange>1.2.4</versionRange>
+ <goals>
+ <goal>generate-depends-file</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <ignore />
+ </action>
+ </pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
</execution>
</executions>
</plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <version>1.8</version>
+ <executions>
+ <execution>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>add-source</goal>
+ </goals>
+ <configuration>
+ <sources>
+ <source>target/generated-sources/parser</source>
+ <source>target/generated-sources/sal</source>
+ <source>${basedir}/src/main/xtend-gen</source>
+ </sources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
</plugins>
</pluginManagement>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
</plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ </plugin>
</plugins>
</build>
import com.google.common.collect.Iterables;
import com.romix.scala.collection.concurrent.TrieMap;
-/*
+/**
* A simple layer on top of maps, which performs snapshot mediation and optimization of
* what the underlying implementation is.
*/
</dependency>
</dependencies>
</plugin>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>build-helper-maven-plugin</artifactId>
- <executions>
- <execution>
- <phase>generate-sources</phase>
- <goals>
- <goal>add-source</goal>
- </goals>
- <configuration>
- <sources>
- <source>target/generated-sources/sal</source>
- </sources>
- </configuration>
- </execution>
- </executions>
- </plugin>
</plugins>
</build>
<description>${project.artifactId}</description>
<dependencies>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
return localName;
}
- /**
- * QName Constructor.
- *
- * @param namespace
- * the namespace assigned to the YANG module
- * @param revision
- * the revision of the YANG module
- * @param localName
- * YANG schema identifier
- *
- * @deprecated Use {@link #create(URI, Date, String)} instead.
- */
- @Deprecated
- public QName(final URI namespace, final Date revision, final String localName) {
- this(QNameModule.create(namespace, revision), null, localName);
- }
-
- /**
- * Construct new QName which reuses namespace, revision and prefix from
- * base.
- *
- * @param base
- * @param localName
- * @deprecated Use {@link #create(QName, String)} instead.
- */
- @Deprecated
- public QName(final QName base, final String localName) {
- this(base.getNamespace(), base.getRevision(), base.getPrefix(), localName);
- }
-
- /**
- * @deprecated Use {@link #create(String)} instead. This implementation is
- * broken.
- */
- @Deprecated
- public QName(final String input) throws ParseException {
- final String nsAndRev = input.substring(input.indexOf("(") + 1, input.indexOf(")"));
- final Date revision;
- final URI namespace;
- if (nsAndRev.contains("?")) {
- String[] splitted = nsAndRev.split("\\?");
- namespace = URI.create(splitted[0]);
- revision = getRevisionFormat().parse(splitted[1]);
- } else {
- namespace = URI.create(nsAndRev);
- revision = null;
- }
-
- this.localName = checkLocalName(input.substring(input.indexOf(")") + 1));
- this.prefix = null;
- this.module = QNameModule.create(namespace, revision);
- }
-
public static QName create(final String input) {
Matcher matcher = QNAME_PATTERN_FULL.matcher(input);
if (matcher.matches()) {
}
public static QName create(final QName base, final String localName) {
- return new QName(base, localName);
+ return new QName(base.getModule(), base.getPrefix(), localName);
}
+ /**
+ * Creates new QName.
+ *
+ * @param qnameModule
+ * Namespace and revision enclosed as a QNameModule
+ * @param prefix
+ * Namespace prefix
+ * @param localName
+ * Local name part of QName. MUST NOT BE null.
+ * @return Instance of QName
+ */
public static QName create(final QNameModule module, final String prefix, final String localName) {
if (module == null) {
throw new NullPointerException("module may not be null");
* <p>
* The following outlines suggested values as defined by netconf (<a href="https://tools.ietf.org/html/rfc6241#page-89">RFC 6241</a>):
* <pre>
- * access_denied
- * bad_attribute
- * bad_element
- * data_exists
- * data_missing
- * in_use
- * invalid_value
- * lock_denied
- * malformed_message
- * missing_attribute
- * missing_element
- * operation_failed
- * operation_not_supported
- * resource_denied
- * rollback_failed
- * too_big
- * unknown_attribute
- * unknown_element
- * unknown_namespace
+ * access-denied
+ * bad-attribute
+ * bad-element
+ * data-exists
+ * data-missing
+ * in-use
+ * invalid-value
+ * lock-denied
+ * malformed-message
+ * missing-attribute
+ * missing-element
+ * operation-failed
+ * operation-not-supported
+ * resource-denied
+ * rollback-failed
+ * too-big
+ * unknown-attribute
+ * unknown-element
+ * unknown-namespace
* </pre>
* @return a string if available or null otherwise.
*/
package org.opendaylight.yangtools.yang.common;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import org.opendaylight.yangtools.yang.common.RpcError.ErrorSeverity;
import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
+import com.google.common.collect.ImmutableList;
+
/**
* A builder for creating RpcResult instances.
*
*
* @param <T> the result value type
*/
-public class RpcResultBuilder<T> {
+public final class RpcResultBuilder<T> {
private static class RpcResultImpl<T> implements RpcResult<T> {
}
}
- private Collection<RpcError> errors;
+ private ImmutableList.Builder<RpcError> errors;
private T result;
private final boolean successful;
return new RpcResultBuilder<T>( false, null );
}
+ /**
+ * Returns a builder based on the given status.
+ *
+ * @param success true if successful, false otherwise.
+ */
+ public static <T> RpcResultBuilder<T> status( boolean success ) {
+ return new RpcResultBuilder<T>( success, null );
+ }
+
+ /**
+ * Returns a builder from another RpcResult.
+ *
+ * @param other the other RpcResult.
+ */
+ public static <T> RpcResultBuilder<T> from( RpcResult<T> other ) {
+ return new RpcResultBuilder<T>( other.isSuccessful(), other.getResult() )
+ .withRpcErrors( other.getErrors() );
+ }
+
+ /**
+ * Creates an RpcError with severity ERROR for reuse.
+ *
+ * @param errorType the conceptual layer at which the error occurred.
+ * @param tag a short string that identifies the general type of error condition. See
+ * {@link RpcError#getTag} for a list of suggested values.
+ * @param message a string suitable for human display that describes the error condition.
+ *
+ * @return an RpcError
+ */
+ public static RpcError newError( ErrorType errorType, String tag, String message ) {
+ return new RpcErrorImpl( ErrorSeverity.ERROR, errorType, tag, message, null, null, null );
+ }
+
+ /**
+ * Creates an RpcError with severity ERROR for reuse.
+ *
+ * @param errorType the conceptual layer at which the error occurred.
+ * @param tag a short string that identifies the general type of error condition. See
+ * {@link RpcError#getTag} for a list of suggested values.
+ * @param message a string suitable for human display that describes the error condition.
+ * * @param applicationTag a short string that identifies the specific type of error condition.
+ * @param info a string containing additional information to provide extended
+ * and/or implementation-specific debugging information.
+ * @param cause the exception that triggered the error.
+ *
+ * @return an RpcError
+ */
+ public static RpcError newError( ErrorType errorType, String tag, String message,
+ String applicationTag, String info, Throwable cause ) {
+ return new RpcErrorImpl( ErrorSeverity.ERROR, errorType, tag, message,
+ applicationTag, info, cause );
+ }
+
+ /**
+ * Creates an RpcError with severity WARNING for reuse.
+ *
+ * @param errorType the conceptual layer at which the warning occurred.
+ * @param tag a short string that identifies the general type of warning condition. See
+ * {@link RpcError#getTag} for a list of suggested values.
+ * @param message a string suitable for human display that describes the warning condition.
+ *
+ * @return an RpcError
+ */
+ public static RpcError newWarning( ErrorType errorType, String tag, String message ) {
+ return new RpcErrorImpl( ErrorSeverity.WARNING, errorType, tag, message, null, null, null );
+ }
+
+ /**
+ * Creates an RpcError with severity WARNING for reuse.
+ *
+ * @param errorType the conceptual layer at which the warning occurred.
+ * @param tag a short string that identifies the general type of warning condition. See
+ * {@link RpcError#getTag} for a list of suggested values.
+ * @param message a string suitable for human display that describes the warning condition.
+ * * @param applicationTag a short string that identifies the specific type of warning condition.
+ * @param info a string containing additional information to provide extended
+ * and/or implementation-specific debugging information.
+ * @param cause the exception that triggered the warning.
+ *
+ * @return an RpcError
+ */
+ public static RpcError newWarning( ErrorType errorType, String tag, String message,
+ String applicationTag, String info, Throwable cause ) {
+ return new RpcErrorImpl( ErrorSeverity.WARNING, errorType, tag, message,
+ applicationTag, info, cause );
+ }
+
/**
* Sets the value of the result.
*
String tag, String message, String applicationTag, String info,
Throwable cause ) {
+ addError( new RpcErrorImpl( severity, errorType,
+ tag != null ? tag : "operation-failed", message,
+ applicationTag, info, cause ) );
+ }
+
+ private void addError( RpcError error ) {
+
if( errors == null ) {
- errors = new ArrayList<>();
+ errors = new ImmutableList.Builder<RpcError>();
}
- errors.add( new RpcErrorImpl( severity, errorType, tag, message,
- applicationTag, info, cause ) );
+ errors.add( error );
}
/**
* @param message a string suitable for human display that describes the error condition.
*/
public RpcResultBuilder<T> withError( ErrorType errorType, String message ) {
- addError( ErrorSeverity.ERROR, errorType, "operation-failed", message, null, null, null );
+ addError( ErrorSeverity.ERROR, errorType, null, message, null, null, null );
return this;
}
return this;
}
+ /**
+ * Adds an error to the result. The general error tag defaults to "operation-failed".
+ *
+ * @param errorType the conceptual layer at which the error occurred.
+ * @param message a string suitable for human display that describes the error condition.
+ * @param cause the exception that triggered the error.
+ */
+ public RpcResultBuilder<T> withError( ErrorType errorType, String message,
+ Throwable cause ) {
+ addError( ErrorSeverity.ERROR, errorType, null, message, null, null, cause );
+ return this;
+ }
+
/**
* Adds an error to the result.
*
return this;
}
+ /**
+ * Adds an RpcError.
+ *
+ * @param error the RpcError
+ */
+ public RpcResultBuilder<T> withRpcError( RpcError error ) {
+ addError( error );
+ return this;
+ }
+
+ /**
+ * Adds RpcErrors.
+ *
+ * @param errors the list of RpcErrors
+ */
+ public RpcResultBuilder<T> withRpcErrors( Collection<RpcError> errors ) {
+ if( errors != null ) {
+ for( RpcError error: errors ) {
+ addError( error );
+ }
+ }
+ return this;
+ }
+
public RpcResult<T> build() {
return new RpcResultImpl<T>( successful, result,
- errors != null ? errors : Collections.<RpcError>emptyList() );
+ errors != null ? errors.build() : Collections.<RpcError>emptyList() );
}
}
@Test
public void testFailed() {
Throwable cause = new Throwable( "mock cause" );
+ Throwable cause2 = new Throwable( "mock cause2" );
RpcResult<String> result = RpcResultBuilder.<String>failed()
.withError( ErrorType.PROTOCOL, "error message 1" )
.withError( ErrorType.APPLICATION, "lock_denied", "error message 2" )
.withError( ErrorType.RPC, "in-use", "error message 3", "my-app-tag", "my-info", cause )
+ .withError( ErrorType.TRANSPORT, "error message 4", cause2 )
.build();
verifyRpcResult( result, false, null );
verifyRpcError( result, 0, ErrorSeverity.ERROR, ErrorType.PROTOCOL, "operation-failed",
"error message 2", null, null, null );
verifyRpcError( result, 2, ErrorSeverity.ERROR, ErrorType.RPC, "in-use",
"error message 3", "my-app-tag", "my-info", cause );
- assertEquals( "getErrors size", 3, result.getErrors().size() );
+ verifyRpcError( result, 3, ErrorSeverity.ERROR, ErrorType.TRANSPORT, "operation-failed",
+ "error message 4", null, null, cause2 );
+ assertEquals( "getErrors size", 4, result.getErrors().size() );
}
@Test
assertEquals( "getErrors size", 2, result.getErrors().size() );
}
+ @Test
+ public void testFrom() {
+ Throwable cause = new Throwable( "mock cause" );
+ RpcResult<String> result = RpcResultBuilder.<String>success()
+ .withResult( "foo" )
+ .withWarning( ErrorType.RPC, "in-use", "message", "my-app-tag", "my-info", cause )
+ .build();
+
+ RpcResult<String> copy = RpcResultBuilder.<String>from( result )
+ .withError( ErrorType.PROTOCOL, "error message" )
+ .build();
+ verifyRpcResult( copy, true, "foo" );
+ verifyRpcError( copy, 0, ErrorSeverity.WARNING, ErrorType.RPC, "in-use",
+ "message", "my-app-tag", "my-info", cause );
+ verifyRpcError( copy, 1, ErrorSeverity.ERROR, ErrorType.PROTOCOL, "operation-failed",
+ "error message", null, null, null );
+ }
+
+ @Test
+ public void testWithRpcErrors() {
+ Throwable cause = new Throwable( "mock cause" );
+ RpcResult<String> result = RpcResultBuilder.<String>failed()
+ .withWarning( ErrorType.RPC, "in-use", "message", "my-app-tag", "my-info", cause )
+ .withError( ErrorType.PROTOCOL, "error message" )
+ .build();
+
+ RpcResult<String> result2 = RpcResultBuilder.<String>failed()
+ .withRpcErrors( result.getErrors() )
+ .build();
+ verifyRpcError( result2, 0, ErrorSeverity.WARNING, ErrorType.RPC, "in-use",
+ "message", "my-app-tag", "my-info", cause );
+ verifyRpcError( result2, 1, ErrorSeverity.ERROR, ErrorType.PROTOCOL, "operation-failed",
+ "error message", null, null, null );
+ }
+
void verifyRpcError( RpcResult<?> result, int errorIndex, ErrorSeverity expSeverity,
ErrorType expErrorType, String expTag, String expMessage, String expAppTag,
String expInfo, Throwable expCause ) {
import org.opendaylight.yangtools.concepts.Identifiable;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.Node;
/**
*
* @param <K> Local identifier of node
* @param <V> Value of node
*/
-public interface NormalizedNode<K extends InstanceIdentifier.PathArgument,V> extends
- Identifiable<K>, //
- Node<V> {
-
+public interface NormalizedNode<K extends InstanceIdentifier.PathArgument, V> extends Identifiable<K> {
/**
- *
* QName of the node as defined in YANG schema.
*
+ * @return QName of this node, non-null.
*/
- @Override
QName getNodeType();
/**
+ * Locally unique identifier of the node.
*
- * Locally unique identifier of nodes
- *
+ * @return Node identifier, non-null.
*/
@Override
K getIdentifier();
/**
+ * Value of node.
*
- * Value of node
- *
+ * @return Value of the node, may be null.
*/
- @Override
V getValue();
}
do {
final StringBuilder sb = new StringBuilder();
for (int i = 0; i < 4; i++) {
- sb.append('a' + random.nextInt(25));
+ sb.append((char)('a' + random.nextInt(25)));
}
prefix = sb.toString();
return prefix + ':' + qname.getLocalName();
}
-}
\ No newline at end of file
+}
import static com.google.common.base.Preconditions.checkState;
-import com.google.common.base.Function;
-import com.google.common.base.Objects;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Strings;
-import com.google.common.collect.ImmutableList;
-
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+import javax.xml.transform.dom.DOMResult;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.AttributesContainer;
import org.opendaylight.yangtools.yang.data.api.ModifyAction;
import org.opendaylight.yangtools.yang.data.api.Node;
import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl;
import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
-public class XmlDocumentUtils {
+import com.google.common.base.Function;
+import com.google.common.base.Objects;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableList;
+public class XmlDocumentUtils {
private static class ElementWithSchemaContext {
Element element;
SchemaContext schemaContext;
}
}
+ public static final QName OPERATION_ATTRIBUTE_QNAME = QName.create(URI.create("urn:ietf:params:xml:ns:netconf:base:1.0"), null, "operation");
+ private static final Logger logger = LoggerFactory.getLogger(XmlDocumentUtils.class);
+ private static final XMLOutputFactory FACTORY = XMLOutputFactory.newFactory();
private static final XmlCodecProvider DEFAULT_XML_VALUE_CODEC_PROVIDER = new XmlCodecProvider() {
-
@Override
public TypeDefinitionAwareCodec<Object, ? extends TypeDefinition<?>> codecFor(final TypeDefinition<?> baseType) {
return TypeDefinitionAwareCodec.from(baseType);
}
};
- private static final Logger logger = LoggerFactory.getLogger(XmlDocumentUtils.class);
-
/**
* Converts Data DOM structure to XML Document for specified XML Codec Provider and corresponding
* Data Node Container schema. The CompositeNode data parameter enters as root of Data DOM tree and will
Preconditions.checkNotNull(data);
Preconditions.checkNotNull(schema);
- Document doc = getDocument();
+ if (!(schema instanceof ContainerSchemaNode || schema instanceof ListSchemaNode)) {
+ throw new UnsupportedDataTypeException("Schema can be ContainerSchemaNode or ListSchemaNode. Other types are not supported yet.");
+ }
- if (schema instanceof ContainerSchemaNode || schema instanceof ListSchemaNode) {
- doc.appendChild(createXmlRootElement(doc, data, (SchemaNode) schema, codecProvider));
- return doc;
- } else {
- throw new UnsupportedDataTypeException(
- "Schema can be ContainerSchemaNode or ListSchemaNode. Other types are not supported yet.");
+ final DOMResult result = new DOMResult();
+ result.setNode(getDocument());
+ try {
+ final XMLStreamWriter writer = FACTORY.createXMLStreamWriter(result);
+ XmlStreamUtils.create(codecProvider).writeDocument(writer, data, (SchemaNode)schema);
+ writer.close();
+ return (Document)result.getNode();
+ } catch (XMLStreamException e) {
+ logger.error("Failed to serialize data {}", data, e);
+ return null;
}
}
* @return new instance of XML Document
* @throws UnsupportedDataTypeException
*/
- public static Document toDocument(final CompositeNode data, final XmlCodecProvider codecProvider)
- throws UnsupportedDataTypeException {
- Preconditions.checkNotNull(data);
-
- DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
- dbf.setNamespaceAware(true);
- Document doc = null;
+ public static Document toDocument(final CompositeNode data, final XmlCodecProvider codecProvider) {
+ final DOMResult result = new DOMResult();
try {
- DocumentBuilder bob = dbf.newDocumentBuilder();
- doc = bob.newDocument();
- } catch (ParserConfigurationException e) {
+ final XMLStreamWriter writer = FACTORY.createXMLStreamWriter(result);
+ XmlStreamUtils.create(codecProvider).writeDocument(writer, data);
+ writer.close();
+ return (Document)result.getNode();
+ } catch (XMLStreamException e) {
+ logger.error("Failed to serialize data {}", data, e);
return null;
}
-
- doc.appendChild(createXmlRootElement(doc, data, null, codecProvider));
- return doc;
}
- private static Element createXmlRootElement(final Document doc, final Node<?> data, final SchemaNode schema,
- final XmlCodecProvider codecProvider) throws UnsupportedDataTypeException {
- Element itemEl = createElementFor(doc, data);
- if (data instanceof SimpleNode<?>) {
- if (schema instanceof LeafListSchemaNode) {
- writeValueByType(itemEl, (SimpleNode<?>) data, ((LeafListSchemaNode) schema).getType(),
- (DataSchemaNode) schema, codecProvider);
- } else if (schema instanceof LeafSchemaNode) {
- writeValueByType(itemEl, (SimpleNode<?>) data, ((LeafSchemaNode) schema).getType(),
- (DataSchemaNode) schema, codecProvider);
- } else {
- Object value = data.getValue();
- if (value != null) {
- itemEl.setTextContent(String.valueOf(value));
- }
- }
- } else { // CompositeNode
- for (Node<?> child : ((CompositeNode) data).getValue()) {
- DataSchemaNode childSchema = null;
- if (schema instanceof DataNodeContainer) {
- childSchema = findFirstSchema(child.getNodeType(), ((DataNodeContainer) schema).getChildNodes()).orNull();
- if (logger.isDebugEnabled()) {
- if (childSchema == null) {
- logger.debug("Probably the data node \""
- + ((child == null) ? "" : child.getNodeType().getLocalName())
- + "\" is not conform to schema");
- }
- }
+ private static final Element createElementFor(final Document doc, final QName qname, final Object obj) {
+ final Element ret;
+ if (qname.getNamespace() != null) {
+ ret = doc.createElementNS(qname.getNamespace().toString(), qname.getLocalName());
+ } else {
+ ret = doc.createElementNS(null, qname.getLocalName());
+ }
+
+ if (obj instanceof AttributesContainer) {
+ final Map<QName, String> attrs = ((AttributesContainer)obj).getAttributes();
+
+ if (attrs != null) {
+ for (Entry<QName, String> attribute : attrs.entrySet()) {
+ ret.setAttributeNS(attribute.getKey().getNamespace().toString(), attribute.getKey().getLocalName(),
+ attribute.getValue());
}
- itemEl.appendChild(createXmlRootElement(doc, child, childSchema, codecProvider));
}
}
- return itemEl;
+
+ return ret;
}
public static Element createElementFor(final Document doc, final Node<?> data) {
- QName dataType = data.getNodeType();
- Element ret;
- if (dataType.getNamespace() != null) {
- ret = doc.createElementNS(dataType.getNamespace().toString(), dataType.getLocalName());
- } else {
- ret = doc.createElementNS(null, dataType.getLocalName());
- }
- if (data instanceof AttributesContainer && ((AttributesContainer) data).getAttributes() != null) {
- for (Entry<QName, String> attribute : ((AttributesContainer) data).getAttributes().entrySet()) {
- ret.setAttributeNS(attribute.getKey().getNamespace().toString(), attribute.getKey().getLocalName(),
- attribute.getValue());
- }
+ return createElementFor(doc, data.getNodeType(), data);
+ }
- }
- return ret;
+ public static Element createElementFor(final Document doc, final NormalizedNode<?, ?> data) {
+ return createElementFor(doc, data.getNodeType(), data);
}
public static void writeValueByType(final Element element, final SimpleNode<?> node, final TypeDefinition<?> type,
return ImmutableCompositeNode.create(qName, values, modifyAction.orNull());
}
- public static final QName OPERATION_ATTRIBUTE_QNAME = QName.create(URI.create("urn:ietf:params:xml:ns:netconf:base:1.0"), null, "operation");
-
public static Optional<ModifyAction> getModifyOperationFromAttributes(final Element xmlElement) {
Attr attributeNodeNS = xmlElement.getAttributeNodeNS(OPERATION_ATTRIBUTE_QNAME.getNamespace().toString(), OPERATION_ATTRIBUTE_QNAME.getLocalName());
if(attributeNodeNS == null) {
- return Optional.absent();
- }
+ return Optional.absent();
+ }
ModifyAction action = ModifyAction.fromXmlValue(attributeNodeNS.getValue());
Preconditions.checkArgument(action.isOnElementPermitted(), "Unexpected operation %s on %s", action, xmlElement);
package org.opendaylight.yangtools.yang.data.impl.codec.xml;
+import com.google.common.annotations.Beta;
import com.google.common.base.Preconditions;
import java.net.URI;
import java.util.Map.Entry;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+/**
+ * Utility class for bridging JAXP Stream and YANG Data APIs. Note that the definition of this class
+ * by no means final and subject to change as more functionality is centralized here.
+ */
+@Beta
public class XmlStreamUtils {
private static final Logger LOG = LoggerFactory.getLogger(XmlStreamUtils.class);
+ private final XmlCodecProvider codecProvider;
- public static void writeDataDocument(final XMLStreamWriter writer, final CompositeNode data, final SchemaNode schema, final XmlCodecProvider codecProvider) throws XMLStreamException {
- // final Boolean repairing = (Boolean) writer.getProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES);
- // Preconditions.checkArgument(repairing == true, "XML Stream Writer has to be repairing namespaces");
+ protected XmlStreamUtils(final XmlCodecProvider codecProvider) {
+ this.codecProvider = Preconditions.checkNotNull(codecProvider);
+ }
- writer.writeStartDocument();
- writeData(writer, data, schema, codecProvider);
- writer.writeEndDocument();
- writer.flush();
+ /**
+ * Create a new instance encapsulating a particular codec provider.
+ *
+ * @param codecProvider XML codec provider
+ * @return A new instance
+ */
+ public static XmlStreamUtils create(final XmlCodecProvider codecProvider) {
+ return new XmlStreamUtils(codecProvider);
}
- public static void writeDataDocument(final XMLStreamWriter writer, final CompositeNode data, final XmlCodecProvider codecProvider) throws XMLStreamException {
- writeDataDocument(writer, data, null, codecProvider);
+ /**
+ * Check if a particular data element can be emitted as an empty element, bypassing value encoding. This
+ * functionality is optional, as valid XML stream is produced even if start/end element is produced unconditionally.
+ *
+ * @param data Data node
+ * @return True if the data node will result in empty element body.
+ */
+ public static boolean isEmptyElement(final Node<?> data) {
+ if (data == null) {
+ return true;
+ }
+
+ if (data instanceof CompositeNode) {
+ return ((CompositeNode) data).getValue().isEmpty();
+ }
+ if (data instanceof SimpleNode) {
+ return data.getValue() == null;
+ }
+
+ // Safe default
+ return false;
}
- public static void write(final XMLStreamWriter writer, final InstanceIdentifier id) throws XMLStreamException {
+ /**
+ * Write an InstanceIdentifier into the output stream. Calling corresponding {@link XMLStreamWriter#writeStartElement(String)}
+ * and {@link XMLStreamWriter#writeEndElement()} is the responsibility of the caller.
+ *
+ * @param writer XML Stream writer
+ * @param id InstanceIdentifier
+ * @throws XMLStreamException
+ */
+ public static void write(final @Nonnull XMLStreamWriter writer, final @Nonnull InstanceIdentifier id) throws XMLStreamException {
Preconditions.checkNotNull(writer, "Writer may not be null");
Preconditions.checkNotNull(id, "Variable should contain instance of instance identifier and can't be null");
writer.writeCharacters(str);
}
- public static void writeData(final XMLStreamWriter writer, final Node<?> data, final SchemaNode schema, final XmlCodecProvider codecProvider) throws XMLStreamException {
+ /**
+ * Write a full XML document corresponding to a CompositeNode into an XML stream writer.
+ *
+ * @param writer XML Stream writer
+ * @param data data node
+ * @param schema corresponding schema node, may be null
+ * @throws XMLStreamException if an encoding problem occurs
+ */
+ public void writeDocument(final @Nonnull XMLStreamWriter writer, final @Nonnull CompositeNode data, final @Nullable SchemaNode schema) throws XMLStreamException {
+ // final Boolean repairing = (Boolean) writer.getProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES);
+ // Preconditions.checkArgument(repairing == true, "XML Stream Writer has to be repairing namespaces");
+
+ writer.writeStartDocument();
+ writeElement(writer, data, schema);
+ writer.writeEndDocument();
+ writer.flush();
+ }
+
+ /**
+ * Short-hand for {@link #writeDataDocument(XMLStreamWriter, CompositeNode, SchemaNode, XmlCodecProvider)} with
+ * null SchemaNode.
+ *
+ * @param writer XML Stream writer
+ * @param data data node
+ * @param schema corresponding schema node, may be null
+ * @throws XMLStreamException if an encoding problem occurs
+ */
+ public void writeDocument(final XMLStreamWriter writer, final CompositeNode data) throws XMLStreamException {
+ writeDocument(writer, data, null);
+ }
+
+ /**
+ * Write an element into a XML stream writer. This includes the element start/end tags and
+ * the value of the element.
+ *
+ * @param writer XML Stream writer
+ * @param data data node
+ * @param schema Schema node
+ * @throws XMLStreamException if an encoding problem occurs
+ */
+ public void writeElement(final XMLStreamWriter writer, final @Nonnull Node<?> data, final SchemaNode schema) throws XMLStreamException {
final QName qname = data.getNodeType();
final String pfx = qname.getPrefix() != null ? qname.getPrefix() : "";
- final String ns;
- if (qname.getNamespace() != null) {
- ns = qname.getNamespace().toString();
- } else {
- ns = "";
+ final String ns = qname.getNamespace() != null ? qname.getNamespace().toString() : "";
+
+ if (isEmptyElement(data)) {
+ writer.writeEmptyElement(pfx, qname.getLocalName(), ns);
+ return;
}
writer.writeStartElement(pfx, qname.getLocalName(), ns);
if (data instanceof SimpleNode<?>) {
// Simple node
if (schema instanceof LeafListSchemaNode) {
- writeValue(writer, ((LeafListSchemaNode) schema).getType(), codecProvider, data.getValue());
+ writeValue(writer, ((LeafListSchemaNode) schema).getType(), data.getValue());
} else if (schema instanceof LeafSchemaNode) {
- writeValue(writer, ((LeafSchemaNode) schema).getType(), codecProvider, data.getValue());
+ writeValue(writer, ((LeafSchemaNode) schema).getType(), data.getValue());
} else {
Object value = data.getValue();
if (value != null) {
}
}
- writeData(writer, child, childSchema, codecProvider);
+ writeElement(writer, child, childSchema);
}
}
writer.writeEndElement();
}
- public static void writeValue(final XMLStreamWriter writer, final TypeDefinition<?> type, final XmlCodecProvider codecProvider, final Object nodeValue) throws XMLStreamException {
- TypeDefinition<?> baseType = XmlUtils.resolveBaseTypeFrom(type);
+ /**
+ * Write a value into a XML stream writer. This method assumes the start and end of element is
+ * emitted by the caller.
+ *
+ * @param writer XML Stream writer
+ * @param data data node
+ * @param schema Schema node
+ * @throws XMLStreamException if an encoding problem occurs
+ */
+ public void writeValue(final @Nonnull XMLStreamWriter writer, final @Nonnull TypeDefinition<?> type, final Object value) throws XMLStreamException {
+ if (value == null) {
+ LOG.debug("Value of {}:{} is null, not encoding it", type.getQName().getNamespace(), type.getQName().getLocalName());
+ return;
+ }
+
+ final TypeDefinition<?> baseType = XmlUtils.resolveBaseTypeFrom(type);
if (baseType instanceof IdentityrefTypeDefinition) {
- if (nodeValue instanceof QName) {
- QName value = (QName) nodeValue;
- String prefix = "x";
- if (value.getPrefix() != null && !value.getPrefix().isEmpty()) {
- prefix = value.getPrefix();
+ write(writer, (IdentityrefTypeDefinition) baseType, value);
+ } else if (baseType instanceof InstanceIdentifierTypeDefinition) {
+ write(writer, (InstanceIdentifierTypeDefinition) baseType, value);
+ } else {
+ final TypeDefinitionAwareCodec<Object, ?> codec = codecProvider.codecFor(baseType);
+ String text;
+ if (codec != null) {
+ try {
+ text = codec.serialize(value);
+ } catch (ClassCastException e) {
+ LOG.error("Provided node value {} did not have type {} required by mapping. Using stream instead.", value, baseType, e);
+ text = String.valueOf(value);
}
-
- writer.writeNamespace(prefix, value.getNamespace().toString());
- writer.writeCharacters(prefix + ':' + value.getLocalName());
} else {
- Object value = nodeValue;
- LOG.debug("Value of {}:{} is not instance of QName but is {}", baseType.getQName().getNamespace(),
- baseType.getQName().getLocalName(), value != null ? value.getClass() : "null");
- if (value != null) {
- writer.writeCharacters(String.valueOf(value));
- }
+ LOG.error("Failed to find codec for {}, falling back to using stream", baseType);
+ text = String.valueOf(value);
}
- } else if (baseType instanceof InstanceIdentifierTypeDefinition) {
- if (nodeValue instanceof InstanceIdentifier) {
- write(writer, (InstanceIdentifier)nodeValue);
+ writer.writeCharacters(text);
+ }
+ }
+
+ private static void write(final @Nonnull XMLStreamWriter writer, final @Nonnull IdentityrefTypeDefinition type, final @Nonnull Object value) throws XMLStreamException {
+ if (value instanceof QName) {
+ final QName qname = (QName) value;
+ final String prefix;
+ if (qname.getPrefix() != null && !qname.getPrefix().isEmpty()) {
+ prefix = qname.getPrefix();
} else {
- Object value = nodeValue;
- LOG.debug("Value of {}:{} is not instance of InstanceIdentifier but is {}", baseType.getQName()
- .getNamespace(), //
- baseType.getQName().getLocalName(), value != null ? value.getClass() : "null");
- if (value != null) {
- writer.writeCharacters(String.valueOf(value));
- }
+ prefix = "x";
}
+
+ writer.writeNamespace(prefix, qname.getNamespace().toString());
+ writer.writeCharacters(prefix + ':' + qname.getLocalName());
} else {
- if (nodeValue != null) {
- final TypeDefinitionAwareCodec<Object, ?> codec = codecProvider.codecFor(baseType);
- String text;
- if (codec != null) {
- try {
- text = codec.serialize(nodeValue);
- } catch (ClassCastException e) {
- LOG.error("Provided node value {} did not have type {} required by mapping. Using stream instead.", nodeValue, baseType, e);
- text = String.valueOf(nodeValue);
- }
- } else {
- LOG.error("Failed to find codec for {}, falling back to using stream", baseType);
- text = String.valueOf(nodeValue);
- }
- writer.writeCharacters(text);
- }
+ LOG.debug("Value of {}:{} is not a QName but {}", type.getQName().getNamespace(), type.getQName().getLocalName(), value.getClass());
+ writer.writeCharacters(String.valueOf(value));
+ }
+ }
+
+ private static void write(final @Nonnull XMLStreamWriter writer, final @Nonnull InstanceIdentifierTypeDefinition type, final @Nonnull Object value) throws XMLStreamException {
+ if (value instanceof InstanceIdentifier) {
+ write(writer, (InstanceIdentifier)value);
+ } else {
+ LOG.debug("Value of {}:{} is not an InstanceIdentifier but {}", type.getQName().getNamespace(), type.getQName().getLocalName(), value.getClass());
+ writer.writeCharacters(String.valueOf(value));
}
}
}
import java.util.Map;
+import javax.annotation.Nonnull;
+
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
}
- public static TypeDefinition<?> resolveBaseTypeFrom(final TypeDefinition<?> type) {
+ public static TypeDefinition<?> resolveBaseTypeFrom(final @Nonnull TypeDefinition<?> type) {
TypeDefinition<?> superType = type;
while (superType.getBaseType() != null) {
superType = superType.getBaseType();
*/
package org.opendaylight.yangtools.yang.data.impl.schema.nodes;
-import org.opendaylight.yangtools.concepts.Immutable;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
import com.google.common.base.Preconditions;
-public abstract class AbstractImmutableNormalizedNode<K extends InstanceIdentifier.PathArgument,V>
- implements NormalizedNode<K, V>, Immutable {
+import org.opendaylight.yangtools.concepts.Immutable;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+public abstract class AbstractImmutableNormalizedNode<K extends InstanceIdentifier.PathArgument,V> implements NormalizedNode<K, V>, Immutable {
private final K nodeIdentifier;
protected AbstractImmutableNormalizedNode(final K nodeIdentifier) {
return nodeIdentifier;
}
- @Override
- public final CompositeNode getParent() {
- throw new UnsupportedOperationException("Deprecated");
- }
-
- @Override
- public final QName getKey() {
- return getNodeType();
- }
-
- @Override
- public final V setValue(final V value) {
- throw new UnsupportedOperationException("Immutable");
- }
-
@Override
public final String toString() {
return addToStringAttributes(Objects.toStringHelper(this)).toString();
public synchronized void setSchemaContext(final SchemaContext newSchemaContext) {
Preconditions.checkNotNull(newSchemaContext);
- LOG.info("Attempting to install schema context {}", newSchemaContext);
+ LOG.info("Attempting to install schema contexts");
+ LOG.debug("Following schema contexts will be attempted {}",newSchemaContext);
/*
* FIXME: we should walk the schema contexts, both current and new and see
--- /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.yang.data.impl.codec.xml;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.RandomPrefix;
+
+/**
+ * @author tkubas
+ */
+public class RandomPrefixTest {
+ private RandomPrefix randomPrefix;
+
+ /**
+ * setup {@link #randomPrefix} instance
+ */
+ @Before
+ public void setUp() {
+ randomPrefix = new RandomPrefix();
+ }
+ /**
+ * Test method for {@link org.opendaylight.yangtools.yang.data.impl.codec.xml.RandomPrefix#encodeQName(QName)}.
+ */
+ @Test
+ public void testEncodeQName() {
+ QName node = QName.create("","2013-06-07","node");
+ String encodedQName = randomPrefix.encodeQName(node);
+ Assert.assertNotNull(encodedQName);
+ Assert.assertTrue("prefix is expected to contain 4 small letters as prefix but result is: "+encodedQName,
+ encodedQName.matches("[a-z]{4}:node"));
+ }
+
+}
--- /dev/null
+package org.opendaylight.yangtools.yang.data.impl.schema.tree;
+
+import com.google.common.base.Optional;
+import junit.framework.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNodeFactory;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.Version;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Map;
+
+import static org.junit.Assert.*;
+import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.*;
+
+
+public class TreeNodeUtilsTest {
+ private static final Logger LOG = LoggerFactory.getLogger(TreeNodeUtilsTest.class);
+
+ private static final Short ONE_ID = 1;
+ private static final Short TWO_ID = 2;
+ private static final String TWO_ONE_NAME = "one";
+ private static final String TWO_TWO_NAME = "two";
+
+ private static final InstanceIdentifier OUTER_LIST_1_PATH = InstanceIdentifier.builder(TestModel.OUTER_LIST_PATH)
+ .nodeWithKey(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, ONE_ID) //
+ .build();
+
+ private static final InstanceIdentifier OUTER_LIST_2_PATH = InstanceIdentifier.builder(TestModel.OUTER_LIST_PATH)
+ .nodeWithKey(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, TWO_ID) //
+ .build();
+
+ private static final InstanceIdentifier TWO_TWO_PATH = InstanceIdentifier.builder(OUTER_LIST_2_PATH)
+ .node(TestModel.INNER_LIST_QNAME) //
+ .nodeWithKey(TestModel.INNER_LIST_QNAME, TestModel.NAME_QNAME, TWO_TWO_NAME) //
+ .build();
+
+ private static final MapEntryNode BAR_NODE = mapEntryBuilder(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, TWO_ID) //
+ .withChild(mapNodeBuilder(TestModel.INNER_LIST_QNAME) //
+ .withChild(mapEntry(TestModel.INNER_LIST_QNAME, TestModel.NAME_QNAME, TWO_ONE_NAME)) //
+ .withChild(mapEntry(TestModel.INNER_LIST_QNAME, TestModel.NAME_QNAME, TWO_TWO_NAME)) //
+ .build()) //
+ .build();
+
+ private SchemaContext schemaContext;
+ private RootModificationApplyOperation rootOper;
+
+ @Before
+ public void prepare() {
+ schemaContext = TestModel.createTestContext();
+ assertNotNull("Schema context must not be null.", schemaContext);
+ rootOper = RootModificationApplyOperation.from(SchemaAwareApplyOperation.from(schemaContext));
+ }
+
+ public NormalizedNode<?, ?> createDocumentOne() {
+ return ImmutableContainerNodeBuilder
+ .create()
+ .withNodeIdentifier(new InstanceIdentifier.NodeIdentifier(schemaContext.getQName()))
+ .withChild(createTestContainer()).build();
+
+ }
+
+ private ContainerNode createTestContainer() {
+ return ImmutableContainerNodeBuilder
+ .create()
+ .withNodeIdentifier(new InstanceIdentifier.NodeIdentifier(TestModel.TEST_QNAME))
+ .withChild(
+ mapNodeBuilder(TestModel.OUTER_LIST_QNAME)
+ .withChild(mapEntry(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, ONE_ID))
+ .withChild(BAR_NODE).build()).build();
+ }
+
+ private static <T> T assertPresentAndType(final Optional<?> potential, final Class<T> type) {
+ assertNotNull(potential);
+ assertTrue(potential.isPresent());
+ assertTrue(type.isInstance(potential.get()));
+ return type.cast(potential.get());
+ }
+
+ @Test
+ public void findNodeTestNodeFound() {
+ InMemoryDataTreeSnapshot inMemoryDataTreeSnapshot = new InMemoryDataTreeSnapshot(schemaContext,
+ TreeNodeFactory.createTreeNode(createDocumentOne(), Version.initial()), rootOper);
+ TreeNode rootNode = inMemoryDataTreeSnapshot.getRootNode();
+ Optional<TreeNode> node = TreeNodeUtils.findNode(rootNode, OUTER_LIST_1_PATH);
+ assertPresentAndType(node, TreeNode.class);
+ }
+
+ @Test
+ public void findNodeTestNodeNotFound() {
+ InMemoryDataTreeSnapshot inMemoryDataTreeSnapshot = new InMemoryDataTreeSnapshot(schemaContext,
+ TreeNodeFactory.createTreeNode(createDocumentOne(), Version.initial()), rootOper);
+ TreeNode rootNode = inMemoryDataTreeSnapshot.getRootNode();
+ final InstanceIdentifier outerList1InvalidPath = InstanceIdentifier.builder(TestModel.OUTER_LIST_PATH)
+ .nodeWithKey(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 3) //
+ .build();
+ Optional<TreeNode> node = TreeNodeUtils.findNode(rootNode, outerList1InvalidPath);
+ Assert.assertFalse(node.isPresent());
+ }
+
+ @Test
+ public void findNodeCheckedTestNodeFound() {
+ InMemoryDataTreeSnapshot inMemoryDataTreeSnapshot = new InMemoryDataTreeSnapshot(schemaContext,
+ TreeNodeFactory.createTreeNode(createDocumentOne(), Version.initial()), rootOper);
+ TreeNode rootNode = inMemoryDataTreeSnapshot.getRootNode();
+ TreeNode foundNode = null;
+ try {
+ foundNode = TreeNodeUtils.findNodeChecked(rootNode, OUTER_LIST_1_PATH);
+ } catch (IllegalArgumentException e) {
+ fail("Illegal argument exception was thrown and should not have been" + e.getMessage());
+ }
+ Assert.assertNotNull(foundNode);
+ }
+
+ @Test
+ public void findNodeCheckedTestNodeNotFound() {
+ InMemoryDataTreeSnapshot inMemoryDataTreeSnapshot = new InMemoryDataTreeSnapshot(schemaContext,
+ TreeNodeFactory.createTreeNode(createDocumentOne(), Version.initial()), rootOper);
+ TreeNode rootNode = inMemoryDataTreeSnapshot.getRootNode();
+ final InstanceIdentifier outerList1InvalidPath = InstanceIdentifier.builder(TestModel.OUTER_LIST_PATH)
+ .nodeWithKey(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 3) //
+ .build();
+ try {
+ TreeNodeUtils.findNodeChecked(rootNode, outerList1InvalidPath);
+ fail("Illegal argument exception should have been thrown");
+ } catch (IllegalArgumentException e) {
+ LOG.debug("Illegal argument exception was thrown as expected: '{}' - '{}'", e.getClass(), e.getMessage());
+ }
+ }
+
+ @Test
+ public void findClosestOrFirstMatchTestNodeExists() {
+ InMemoryDataTreeSnapshot inMemoryDataTreeSnapshot = new InMemoryDataTreeSnapshot(schemaContext,
+ TreeNodeFactory.createTreeNode(createDocumentOne(), Version.initial()), rootOper);
+ TreeNode rootNode = inMemoryDataTreeSnapshot.getRootNode();
+ Optional<TreeNode> expectedNode = TreeNodeUtils.findNode(rootNode, TWO_TWO_PATH);
+ assertPresentAndType(expectedNode, TreeNode.class);
+ Map.Entry<InstanceIdentifier, TreeNode> actualNode = TreeNodeUtils.findClosest(rootNode, TWO_TWO_PATH);
+ Assert.assertEquals("Expected node and actual node are not the same", expectedNode.get(), actualNode.getValue());
+ }
+
+ @Test
+ public void findClosestOrFirstMatchTestNodeDoesNotExist() {
+ InMemoryDataTreeSnapshot inMemoryDataTreeSnapshot = new InMemoryDataTreeSnapshot(schemaContext,
+ TreeNodeFactory.createTreeNode(createDocumentOne(), Version.initial()), rootOper);
+ TreeNode rootNode = inMemoryDataTreeSnapshot.getRootNode();
+ final InstanceIdentifier outerListInnerListPath = InstanceIdentifier.builder(OUTER_LIST_2_PATH)
+ .node(TestModel.INNER_LIST_QNAME)
+ .build();
+ final InstanceIdentifier twoTwoInvalidPath = InstanceIdentifier.builder(OUTER_LIST_2_PATH)
+ .node(TestModel.INNER_LIST_QNAME) //
+ .nodeWithKey(TestModel.INNER_LIST_QNAME, TestModel.NAME_QNAME, "three") //
+ .build();
+ Optional<TreeNode> expectedNode = TreeNodeUtils.findNode(rootNode, outerListInnerListPath);
+ assertPresentAndType(expectedNode, TreeNode.class);
+ Map.Entry<InstanceIdentifier, TreeNode> actualNode = TreeNodeUtils.findClosest(rootNode, twoTwoInvalidPath);
+ Assert.assertEquals("Expected node and actual node are not the same", expectedNode.get(), actualNode.getValue());
+ }
+
+ @Test
+ public void getChildTestChildFound() {
+ InMemoryDataTreeSnapshot inMemoryDataTreeSnapshot = new InMemoryDataTreeSnapshot(schemaContext,
+ TreeNodeFactory.createTreeNode(createDocumentOne(), Version.initial()), rootOper);
+ TreeNode rootNode = inMemoryDataTreeSnapshot.getRootNode();
+ Optional<TreeNode> node = TreeNodeUtils.getChild(Optional.fromNullable(rootNode),
+ TestModel.TEST_PATH.getLastPathArgument());
+ assertPresentAndType(node, TreeNode.class);
+ }
+
+ @Test
+ public void getChildTestChildNotFound() {
+ InMemoryDataTreeSnapshot inMemoryDataTreeSnapshot = new InMemoryDataTreeSnapshot(schemaContext,
+ TreeNodeFactory.createTreeNode(createDocumentOne(), Version.initial()), rootOper);
+ TreeNode rootNode = inMemoryDataTreeSnapshot.getRootNode();
+ Optional<TreeNode> node = TreeNodeUtils.getChild(Optional.fromNullable(rootNode),
+ TestModel.OUTER_LIST_PATH.getLastPathArgument());
+ Assert.assertFalse(node.isPresent());
+ }
+}
*/
package org.opendaylight.yangtools.yang.data.operations;
+import com.google.common.base.Optional;
+
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.Node;
import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import com.google.common.base.Optional;
-
public class DataModificationException extends Exception {
// TODO replace QName as identifier for node with schema or NodeIdentifier,
// Augmentation does not have a QName
super(String.format("Data missing for node: %s, %s", nodeType, modificationNode), nodeType);
}
+ public DataMissingException(final QName nodeType, final NormalizedNode<?, ?> modificationNode) {
+ super(String.format("Data missing for node: %s, %s", nodeType, modificationNode), nodeType);
+ }
+
static void check(final QName nodeQName, final Optional<? extends NormalizedNode<?, ?>> actualNode) throws DataMissingException {
if (!actualNode.isPresent()) {
throw new DataMissingException(nodeQName);
*/
package org.opendaylight.yangtools.yang.model.util;
+import com.google.common.base.Optional;
+
import java.util.Collections;
import java.util.List;
import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition;
import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
-import com.google.common.base.Optional;
-
/**
* The Abstract Integer class defines implementation of IntegerTypeDefinition
* interface which represents SIGNED Integer values defined in Yang language. <br>
* @param name Name of type
* @param description Description of type
* @param minRange Minimal range
- * @param maxRange Maxium range
+ * @param maxRange Maximum range
* @param units Units
*/
protected AbstractSignedInteger(final QName name, final String description, final Number minRange,
final Number maxRange, final String units) {
this.name = name;
- this.path = SchemaPath.create(Collections.singletonList(name), true);
+ this.path = SchemaPath.create(true, name);
this.description = description;
this.units = units;
final String rangeDescription = "Integer values between " + minRange + " and " + maxRange + ", inclusively.";
*/
package org.opendaylight.yangtools.yang.model.util;
+import com.google.common.base.Optional;
+
import java.util.Collections;
import java.util.List;
import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition;
-import com.google.common.base.Optional;
-
/**
* The Abstract Integer class defines implementation of IntegerTypeDefinition
* interface which represents UNSIGNED Integer values defined in Yang language. <br>
*/
public AbstractUnsignedInteger(final QName name, final String description, final Number maxRange, final String units) {
this.name = name;
- this.path = SchemaPath.create(Collections.singletonList(name), true);
+ this.path = SchemaPath.create(true, name);
this.description = description;
this.units = units;
final String rangeDescription = "Integer values between " + MIN_VALUE + " and " + maxRange + ", inclusively.";
*/
package org.opendaylight.yangtools.yang.model.util;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableSet;
+
import java.net.URI;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Set;
import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableSet;
-
/**
* Utility methods and constants to work with built-in YANG types
*
}
public static final URI BASE_TYPES_NAMESPACE = URI.create("urn:ietf:params:xml:ns:yang:1");
+ public static final QNameModule BASE_TYPES_MODULE = QNameModule.create(BASE_TYPES_NAMESPACE, null);
public static final QName BINARY_QNAME = constructQName("binary");
public static final QName BITS_QNAME = constructQName("bits");
* @return built-in base yang type QName.
*/
public static QName constructQName(final String typeName) {
- return new QName(BASE_TYPES_NAMESPACE, typeName);
+ return QName.create(BASE_TYPES_MODULE, "", typeName);
}
/**
*/
@Deprecated
public static SchemaPath schemaPath(final QName typeName) {
- return SchemaPath.create(Collections.singletonList(typeName), true);
+ return SchemaPath.create(true, typeName);
}
/**
}
final List<QName> pathList = new ArrayList<QName>();
for (final String path : actualPath) {
- final QName qname = new QName(namespace, revision, path);
+ final QName qname = QName.create(namespace, revision, path);
if (qname != null) {
pathList.add(qname);
}
*/
public final class BooleanType implements BooleanTypeDefinition {
private static final BooleanType INSTANCE = new BooleanType();
- private static final SchemaPath PATH = SchemaPath.create(Collections.singletonList(BaseTypes.BOOLEAN_QNAME), true);
+ private static final SchemaPath PATH = SchemaPath.create(true, BaseTypes.BOOLEAN_QNAME);
private static final String DESCRIPTION = "The boolean built-in type represents a boolean value.";
private static final String REFERENCE = "https://tools.ietf.org/html/rfc6020#section-9.5";
private static final String UNITS = "";
*/
package org.opendaylight.yangtools.yang.model.util;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
import java.net.URI;
import java.util.Collections;
import java.util.Date;
import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
/**
* Extended Type represents YANG type derived from other type.
*
private final boolean addedByUses;
/**
- *
- * Creates Builder for extended / derived type.
- *
- * @param typeName QName of derived type
- * @param baseType Base type of derived type
- * @param description Description of type
- * @param reference Reference of Type
- * @param path Schema path to type definition.
- */
+ *
+ * Creates Builder for extended / derived type.
+ *
+ * @param typeName QName of derived type
+ * @param baseType Base type of derived type
+ * @param description Description of type
+ * @param reference Reference of Type
+ * @param path Schema path to type definition.
+ */
public static final Builder builder(final QName typeName,final TypeDefinition<?> baseType,final Optional<String> description,final Optional<String> reference,final SchemaPath path) {
return new Builder(typeName, baseType, description.or(""), reference.or(""), path);
}
public Builder unknownSchemaNodes(
final List<UnknownSchemaNode> unknownSchemaNodes) {
- this.unknownSchemaNodes = unknownSchemaNodes;
+ if (unknownSchemaNodes.isEmpty()) {
+ this.unknownSchemaNodes = Collections.emptyList();
+ } else {
+ this.unknownSchemaNodes = unknownSchemaNodes;
+ }
return this;
}
if (path != null ? !path.equals(that.path) : that.path != null) {
return false;
}
- if (typeName != null ? !typeName.equals(that.typeName) : that.typeName != null)
+ if (typeName != null ? !typeName.equals(that.typeName) : that.typeName != null) {
return false;
+ }
return true;
}
public final class InstanceIdentifier implements InstanceIdentifierTypeDefinition, Immutable {
private static final QName NAME = BaseTypes.INSTANCE_IDENTIFIER_QNAME;
- private static final SchemaPath PATH = SchemaPath.create(Collections.singletonList(NAME), true);
+ private static final SchemaPath PATH = SchemaPath.create(true, NAME);
private static final String DESCRIPTION = "The instance-identifier built-in type is used to "
+ "uniquely identify a particular instance node in the data tree.";
private static final String REFERENCE = "https://tools.ietf.org/html/rfc6020#section-9.13";
*/
package org.opendaylight.yangtools.yang.model.util;
+import com.google.common.base.Preconditions;
import java.util.Collections;
import java.util.List;
-
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
-import com.google.common.base.Preconditions;
-
/**
* The <code>default</code> implementation of Instance Leafref Type Definition
* interface.
*/
public final class Leafref implements LeafrefTypeDefinition {
private static final QName NAME = BaseTypes.constructQName("leafref");
- private static final SchemaPath PATH = BaseTypes.schemaPath(NAME);
+ private static final SchemaPath PATH = SchemaPath.create(true, NAME);
private static final String DESCRIPTION = "The leafref type is used to reference a particular leaf instance in the data tree.";
private static final String REF = "https://tools.ietf.org/html/rfc6020#section-9.9";
import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
-import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.SchemaNode;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
-import org.opendaylight.yangtools.yang.model.api.UsesNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
return findNodeInModule(module, path);
}
- public static GroupingDefinition findGrouping(final SchemaContext context, final Module module, final Iterable<QName> path) {
- Iterator<QName> iterator = path.iterator();
- QName first = iterator.next();
- Module m = context.findModuleByNamespace(first.getNamespace()).iterator().next();
- DataNodeContainer currentParent = m;
- for (QName qname : path) {
- boolean found = false;
- DataNodeContainer node = (DataNodeContainer) currentParent.getDataChildByName(qname.getLocalName());
- if (node == null) {
- Set<GroupingDefinition> groupings = currentParent.getGroupings();
- for (GroupingDefinition gr : groupings) {
- if (gr.getQName().getLocalName().equals(qname.getLocalName())) {
- currentParent = gr;
- found = true;
- }
- }
- } else {
- found = true;
- currentParent = node;
- }
-
- Preconditions.checkArgument(found, "Failed to find referenced grouping: %s(%s)", path, qname.getLocalName());
- }
-
- return (GroupingDefinition) currentParent;
- }
-
private static SchemaNode findNodeInModule(final Module module, final Iterable<QName> path) {
final QName current = path.iterator().next();
return node;
}
- public static SchemaNode findNodeInCase(final ChoiceCaseNode parent, final Iterable<QName> path) {
+ private static SchemaNode findNodeInCase(final ChoiceCaseNode parent, final Iterable<QName> path) {
final QName current = Iterables.getFirst(path, null);
if (current == null) {
return parent;
return findNode(node, nextLevel(path));
}
- public static RpcDefinition getRpcByName(final Module module, final QName name) {
+ private static RpcDefinition getRpcByName(final Module module, final QName name) {
for (RpcDefinition rpc : module.getRpcs()) {
if (rpc.getQName().equals(name)) {
return rpc;
return Iterables.skip(path, 1);
}
- public static NotificationDefinition getNotificationByName(final Module module, final QName name) {
+ private static NotificationDefinition getNotificationByName(final Module module, final QName name) {
for (NotificationDefinition notification : module.getNotifications()) {
if (notification.getQName().equals(name)) {
return notification;
return null;
}
- public static GroupingDefinition getGroupingByName(final Module module, final QName name) {
+ private static GroupingDefinition getGroupingByName(final Module module, final QName name) {
for (GroupingDefinition grouping : module.getGroupings()) {
if (grouping.getQName().equals(name)) {
return grouping;
return null;
}
- /**
- * Utility method which search for original node defined in grouping.
- *
- * @param node
- * @return
- */
- public static DataSchemaNode findOriginal(final DataSchemaNode node, final SchemaContext ctx) {
- DataSchemaNode result = findCorrectTargetFromGrouping(node, ctx);
- if (result == null) {
- result = findCorrectTargetFromAugment(node, ctx);
- if (result != null) {
- if (result.isAddedByUses()) {
- result = findOriginal(result, ctx);
- }
- }
- }
- return result;
- }
-
- private static DataSchemaNode findCorrectImmediateTargetFromGrouping(final DataSchemaNode node, final SchemaContext ctx) {
- // uses is under module statement
- final Module m = findParentModule(ctx, node);
- Preconditions.checkArgument(m != null, "Failed to find module for node {} in context {}", node, ctx);
-
- for (final UsesNode u : m.getUses()) {
- final SchemaNode targetGrouping = findNodeInSchemaContext(ctx, u.getGroupingPath().getPathFromRoot());
- Preconditions.checkArgument(targetGrouping instanceof GroupingDefinition,
- "Failed to generate code for augment in %s", u);
-
- LOG.trace("Checking grouping {} for node {}", targetGrouping, node);
- final GroupingDefinition gr = (GroupingDefinition) targetGrouping;
- final DataSchemaNode result = gr.getDataChildByName(node.getQName().getLocalName());
- if (result != null) {
- return result;
- }
-
- LOG.debug("Skipped grouping {}, no matching node found", gr);
- }
-
- throw new IllegalArgumentException(
- String.format("Failed to find uses node matching {} in context {}", node, ctx));
- }
-
- private static DataSchemaNode findCorrectTargetFromGrouping(final DataSchemaNode node, final SchemaContext ctx) {
- if (Iterables.size(node.getPath().getPathTowardsRoot()) != 1) {
- QName currentName = node.getQName();
- // tmpPath is used to track level of nesting
- List<QName> tmpPath = new ArrayList<>();
- Object parent = null;
-
- // create schema path of parent node
- SchemaPath sp = node.getPath().getParent();
- parent = findDataSchemaNode(ctx, sp);
-
- do {
- tmpPath.add(currentName);
-
- DataSchemaNode result = null;
- // search parent node's used groupings for presence of wanted
- // node
- if (parent instanceof DataNodeContainer) {
- DataNodeContainer dataNodeParent = (DataNodeContainer) parent;
- for (UsesNode u : dataNodeParent.getUses()) {
- result = getResultFromUses(u, currentName.getLocalName(), ctx);
- if (result != null) {
- break;
- }
- }
- }
-
- // if node is not found in any of current parent's used
- // groupings => parent is added by grouping too, so repeat same
- // process for parent
- if (result == null) {
- final SchemaNode sn = (SchemaNode) parent;
-
- // set current name to name of parent node
- currentName = sn.getQName();
- Preconditions.checkArgument(parent instanceof SchemaNode,
- "Failed to generate code for augmend node {} at parent {}", node, parent);
-
- // create schema path for parent of current parent
- final SchemaPath parentSp = sn.getPath().getParent();
- parent = parentSp.getPathFromRoot().iterator().hasNext() ? findDataSchemaNode(ctx, parentSp)
- : getParentModule(sn, ctx);
- } else {
- // if wanted node was found in grouping, traverse this node
- // based on level of nesting
- return getTargetNode(tmpPath, result, ctx);
- }
- } while (!(parent instanceof Module));
-
- return null;
- } else {
- return findCorrectImmediateTargetFromGrouping(node, ctx);
- }
- }
-
- private static DataSchemaNode findCorrectTargetFromAugment(final DataSchemaNode node, final SchemaContext ctx) {
- if (!node.isAugmenting()) {
- return null;
- }
-
- QName currentName = node.getQName();
- Object currentNode = node;
- Object parent = node;
- List<QName> tmpPath = new ArrayList<QName>();
- List<SchemaNode> tmpTree = new ArrayList<SchemaNode>();
-
- AugmentationSchema augment = null;
- do {
- SchemaPath sp = ((SchemaNode) parent).getPath();
- parent = findDataSchemaNode(ctx, sp.getParent());
- if (parent instanceof AugmentationTarget) {
- tmpPath.add(currentName);
- tmpTree.add((SchemaNode) currentNode);
- augment = findNodeInAugment(((AugmentationTarget) parent).getAvailableAugmentations(), currentName);
- if (augment == null) {
- currentName = ((DataSchemaNode) parent).getQName();
- currentNode = parent;
- }
- }
- } while (((DataSchemaNode) parent).isAugmenting() && augment == null);
-
- if (augment == null) {
- return null;
- } else {
- Collections.reverse(tmpPath);
- Collections.reverse(tmpTree);
- Object actualParent = augment;
- DataSchemaNode result = null;
- for (QName name : tmpPath) {
- if (actualParent instanceof DataNodeContainer) {
- result = ((DataNodeContainer) actualParent).getDataChildByName(name.getLocalName());
- actualParent = ((DataNodeContainer) actualParent).getDataChildByName(name.getLocalName());
- } else {
- if (actualParent instanceof ChoiceNode) {
- result = ((ChoiceNode) actualParent).getCaseNodeByName(name.getLocalName());
- actualParent = ((ChoiceNode) actualParent).getCaseNodeByName(name.getLocalName());
- }
- }
- }
-
- if (result.isAddedByUses()) {
- result = findCorrectTargetFromAugmentGrouping(result, augment, tmpTree, ctx);
- }
-
- return result;
- }
- }
-
- private static DataSchemaNode getResultFromUses(final UsesNode u, final String currentName, final SchemaContext ctx) {
- SchemaNode targetGrouping = SchemaContextUtil.findNodeInSchemaContext(ctx, u.getGroupingPath()
- .getPathFromRoot());
- if (!(targetGrouping instanceof GroupingDefinition)) {
- targetGrouping = findGrouping(ctx, getParentModule(targetGrouping, ctx), u.getGroupingPath()
- .getPathFromRoot());
- }
- Preconditions.checkArgument(targetGrouping instanceof GroupingDefinition,
- "Failed to generate code for augment in %s", u);
- GroupingDefinition gr = (GroupingDefinition) targetGrouping;
- return gr.getDataChildByName(currentName);
- }
-
- private static Module getParentModule(final SchemaNode node, final SchemaContext ctx) {
- QName qname = node.getPath().getPathFromRoot().iterator().next();
- URI namespace = qname.getNamespace();
- Date revision = qname.getRevision();
- return ctx.findModuleByNamespaceAndRevision(namespace, revision);
- }
-
- private static DataSchemaNode getTargetNode(final List<QName> tmpPath, final DataSchemaNode node, final SchemaContext ctx) {
- DataSchemaNode result = node;
- if (tmpPath.size() == 1) {
- if (result != null && result.isAddedByUses()) {
- result = findOriginal(result, ctx);
- }
- return result;
- } else {
- DataSchemaNode newParent = result;
- Collections.reverse(tmpPath);
-
- tmpPath.remove(0);
- for (QName name : tmpPath) {
- // searching by local name is must, because node has different
- // namespace in its original location
- if (newParent == null) {
- break;
- }
- if (newParent instanceof DataNodeContainer) {
- newParent = ((DataNodeContainer) newParent).getDataChildByName(name.getLocalName());
- } else {
- newParent = ((ChoiceNode) newParent).getCaseNodeByName(name.getLocalName());
- }
- }
- if (newParent != null && newParent.isAddedByUses()) {
- newParent = findOriginal(newParent, ctx);
- }
- return newParent;
- }
- }
-
- private static AugmentationSchema findNodeInAugment(final Collection<AugmentationSchema> augments, final QName name) {
- for (AugmentationSchema augment : augments) {
- DataSchemaNode node = augment.getDataChildByName(name);
- if (node != null) {
- return augment;
- }
- }
- return null;
- }
-
- private static DataSchemaNode findCorrectTargetFromAugmentGrouping(final DataSchemaNode node,
- final AugmentationSchema parentNode, final List<SchemaNode> dataTree, final SchemaContext ctx) {
-
- DataSchemaNode result = null;
- QName currentName = node.getQName();
- List<QName> tmpPath = new ArrayList<>();
- tmpPath.add(currentName);
- int i = 1;
- Object parent = null;
-
- do {
- if (dataTree.size() < 2 || dataTree.size() == i) {
- parent = parentNode;
- } else {
- parent = dataTree.get(dataTree.size() - (i + 1));
- tmpPath.add(((SchemaNode) parent).getQName());
- }
-
- if (parent instanceof DataNodeContainer) {
- DataNodeContainer dataNodeParent = (DataNodeContainer) parent;
- for (UsesNode u : dataNodeParent.getUses()) {
- if (result == null) {
- result = getResultFromUses(u, currentName.getLocalName(), ctx);
- }
- }
- }
-
- if (result == null) {
- i = i + 1;
- currentName = ((SchemaNode) parent).getQName();
- }
- } while (result == null);
-
- if (result != null) {
- result = getTargetNode(tmpPath, result, ctx);
- }
- return result;
- }
-
/**
* Transforms string representation of XPath to Queue of QNames. The XPath
* is split by "/" and for each part of XPath is assigned correct module in
*/
package org.opendaylight.yangtools.yang.model.util;
+import com.google.common.base.Optional;
+
import java.util.Collections;
import java.util.List;
import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition;
-import com.google.common.base.Optional;
-
/**
* The <code>default</code> implementation of String Type Definition interface.
*
*/
public final class StringType implements StringTypeDefinition, Immutable {
private static final QName NAME = BaseTypes.STRING_QNAME;
- private static final SchemaPath PATH = SchemaPath.create(Collections.singletonList(NAME), true);
+ private static final SchemaPath PATH = SchemaPath.create(true, NAME);
private static final String DEFAULT_VALUE = "";
private static final String DESCRIPTION = "";
private static final String REFERENCE = "";
*/
package org.opendaylight.yangtools.yang.model.util;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+
import java.util.Collections;
import java.util.List;
import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
-
public final class UnionType implements UnionTypeDefinition {
- private final SchemaPath path = SchemaPath.create(Collections.singletonList(BaseTypes.UNION_QNAME),true);
+ private static final SchemaPath PATH = SchemaPath.create(true, BaseTypes.UNION_QNAME);
private static final String DESCRIPTION = "The union built-in type represents a value that corresponds to one of its member types.";
private static final String REFERENCE = "https://tools.ietf.org/html/rfc6020#section-9.12";
private final List<TypeDefinition<?>> types;
@Override
public SchemaPath getPath() {
- return path;
+ return PATH;
}
@Override
* Unknown type definition is derived type, for
* which base built-in type is not yet known. This types
* are possible during parsing and resolving of YANG model
- * without all requisites allready processed.
- *
- *
+ * without all requisites already processed.
*/
public final class UnknownType implements UnknownTypeDefinition {
public Builder(final QName name, final String description, final String reference) {
this.name = name;
- this.path = BaseTypes.schemaPath(name);
+ this.path = SchemaPath.create(true, name);
this.description = description;
this.reference = reference;
}
public Builder(final QName name) {
this.name = name;
- this.path = BaseTypes.schemaPath(name);
+ this.path = SchemaPath.create(true, name);
}
public Builder description(final String description) {
<listener>true</listener>
</configuration>
</plugin>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>build-helper-maven-plugin</artifactId>
- <executions>
- <execution>
- <phase>generate-sources</phase>
- <goals>
- <goal>add-source</goal>
- </goals>
- <configuration>
- <sources>
- <source>target/generated-sources/parser</source>
- </sources>
- </configuration>
- </execution>
- </executions>
- </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
+
import java.net.URI;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
+
import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.QNameModule;
import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
import org.opendaylight.yangtools.yang.model.api.NamespaceRevisionAware;
import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
import org.opendaylight.yangtools.yang.parser.builder.util.AbstractDocumentedDataNodeContainer;
import org.opendaylight.yangtools.yang.parser.builder.util.AbstractDocumentedDataNodeContainerBuilder;
-public final class AugmentationSchemaBuilderImpl extends AbstractDocumentedDataNodeContainerBuilder implements
- AugmentationSchemaBuilder {
+public final class AugmentationSchemaBuilderImpl extends AbstractDocumentedDataNodeContainerBuilder implements AugmentationSchemaBuilder {
private final int order;
private AugmentationSchemaImpl instance;
private String whenCondition;
if (parent instanceof UsesNodeBuilder) {
final ModuleBuilder mb = BuilderUtils.getParentModule(this);
- final QNameModule qm = QNameModule.create(mb.getNamespace(), mb.getRevision());
List<QName> newPath = new ArrayList<>();
for (QName name : targetPath.getPathFromRoot()) {
- newPath.add(QName.create(qm, name.getPrefix(), name.getLocalName()));
+ newPath.add(QName.create(mb.getQNameModule(), name.getPrefix(), name.getLocalName()));
}
instance.targetPath = SchemaPath.create(newPath, false);
} else {
copyOf = old;
}
- private static final class AugmentationSchemaImpl extends AbstractDocumentedDataNodeContainer implements AugmentationSchema, NamespaceRevisionAware,
- Comparable<AugmentationSchemaImpl> {
+ private static final class AugmentationSchemaImpl extends AbstractDocumentedDataNodeContainer implements AugmentationSchema, NamespaceRevisionAware, Comparable<AugmentationSchemaImpl> {
private final int order;
private SchemaPath targetPath;
private RevisionAwareXPath whenCondition;
import com.google.common.base.Splitter;
import com.google.common.collect.Collections2;
import com.google.common.io.ByteSource;
+
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import org.apache.commons.io.IOUtils;
import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
final QName name;
if (it.hasNext()) {
- name = new QName(null, null, s, it.next());
+ name = QName.create(QNameModule.create(null, null), s, it.next());
} else {
- name = new QName(null, null, null, s);
+ name = QName.create(QNameModule.create(null, null), s);
}
path.add(name);
}
}
}
- public static ModuleBuilder getModuleByPrefix(ModuleBuilder module, String prefix) {
+ public static ModuleBuilder getModuleByPrefix(final ModuleBuilder module, final String prefix) {
if (prefix == null || prefix.isEmpty() || prefix.equals(module.getPrefix())) {
return module;
} else {
if (newParent instanceof ModuleBuilder) {
ModuleBuilder parent = (ModuleBuilder) newParent;
if (updateQName) {
- newQName = new QName(parent.getNamespace(), parent.getRevision(), parent.getPrefix(), old.getQName()
+ newQName = QName.create(parent.getQNameModule(), parent.getPrefix(), old.getQName()
.getLocalName());
} else {
newQName = old.getQName();
AugmentationSchemaBuilder augment = (AugmentationSchemaBuilder) newParent;
ModuleBuilder parent = BuilderUtils.getParentModule(newParent);
if (updateQName) {
- newQName = new QName(parent.getNamespace(), parent.getRevision(), parent.getPrefix(), old.getQName()
+ newQName = QName.create(parent.getQNameModule(), parent.getPrefix(), old.getQName()
.getLocalName());
} else {
newQName = old.getQName();
*/
package org.opendaylight.yangtools.yang.parser.builder.impl;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
-
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
import org.opendaylight.yangtools.yang.model.api.ConstraintDefinition;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.DerivableSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
import org.opendaylight.yangtools.yang.parser.builder.api.UnknownSchemaNodeBuilder;
import org.opendaylight.yangtools.yang.parser.builder.util.AbstractDocumentedDataNodeContainer;
import org.opendaylight.yangtools.yang.parser.builder.util.AbstractDocumentedDataNodeContainerBuilder;
+import org.opendaylight.yangtools.yang.parser.util.YangParseException;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-
-public final class ListSchemaNodeBuilder extends AbstractDocumentedDataNodeContainerBuilder implements DataSchemaNodeBuilder,
-AugmentationTargetBuilder {
+public final class ListSchemaNodeBuilder extends AbstractDocumentedDataNodeContainerBuilder implements
+ DataSchemaNodeBuilder, AugmentationTargetBuilder {
private ListSchemaNodeImpl instance;
private boolean userOrdered;
private List<String> keys;
public ListSchemaNodeBuilder(final String moduleName, final int line, final QName qname, final SchemaPath path,
final ListSchemaNode base) {
- super(moduleName, line, qname,path,base);
+ super(moduleName, line, qname, path, base);
this.schemaPath = Preconditions.checkNotNull(path, "Schema Path must not be null");
constraints = new ConstraintsBuilderImpl(moduleName, line, base.getConstraints());
return instance;
}
buildChildren();
- instance = new ListSchemaNodeImpl(qname, schemaPath,this);
+ instance = new ListSchemaNodeImpl(qname, schemaPath, this);
instance.augmenting = augmenting;
instance.addedByUses = addedByUses;
} else {
keyDefinition = new ArrayList<>();
for (String key : keys) {
- keyDefinition.add(instance.getDataChildByName(key).getQName());
+ DataSchemaNode keyPart = instance.getDataChildByName(key);
+ if (keyPart == null) {
+ throw new YangParseException(getModuleName(), getLine(), "Failed to resolve list key for name "
+ + key);
+ }
+ keyDefinition.add(keyPart.getQName());
}
instance.keyDefinition = ImmutableList.copyOf(keyDefinition);
}
return "list " + qname.getLocalName();
}
- private static final class ListSchemaNodeImpl extends AbstractDocumentedDataNodeContainer implements ListSchemaNode, DerivableSchemaNode {
+ private static final class ListSchemaNodeImpl extends AbstractDocumentedDataNodeContainer implements
+ ListSchemaNode, DerivableSchemaNode {
private final QName qname;
private final SchemaPath path;
private ImmutableList<QName> keyDefinition;
}
public ModuleBuilder(final Module base) {
- super(base.getName(), 0, new QName(base.getNamespace(), base.getRevision(), base.getPrefix(), base.getName()),
+ super(base.getName(), 0, QName.create(base.getQNameModule(), base.getPrefix(), base.getName()),
SCHEMA_PATH, base);
this.name = base.getName();
this.sourcePath = base.getModuleSourcePath();
*/
package org.opendaylight.yangtools.yang.parser.builder.impl;
+import static org.opendaylight.yangtools.yang.parser.builder.impl.BuilderUtils.findBaseIdentity;
+
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
toRemove.add(unionType);
}
}
+ // special handling for identityref types under union
+ for (TypeDefinitionBuilder unionType : union.getTypedefs()) {
+ if (unionType instanceof IdentityrefTypeBuilder) {
+ IdentityrefTypeBuilder idref = (IdentityrefTypeBuilder) unionType;
+ IdentitySchemaNodeBuilder identity = findBaseIdentity(modules, module, idref.getBaseString(),
+ idref.getLine());
+ if (identity == null) {
+ throw new YangParseException(module.getName(), idref.getLine(), "Failed to find base identity");
+ }
+ idref.setBaseIdentity(identity);
+ }
+ }
unionTypes.removeAll(toRemove);
}
final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
final QName utQName = ut.getQName();
final ModuleBuilder dependentModuleBuilder = BuilderUtils.getModuleByPrefix(module, utQName.getPrefix());
+ if (dependentModuleBuilder == null) {
+ throw new YangParseException(module.getName(), union.getLine(), "No module found with prefix "
+ + utQName.getPrefix());
+ }
final TypeDefinitionBuilder resolvedType = findTypeDefinitionBuilder(union, dependentModuleBuilder,
utQName.getLocalName(), module.getName(), union.getLine());
union.setTypedef(resolvedType);
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
import org.opendaylight.yangtools.yang.model.api.Status;
* types.
*/
public final class UnionTypeBuilder extends AbstractTypeAwareBuilder implements TypeDefinitionBuilder {
+ private static final SchemaPath SCHEMA_PATH = SchemaPath.create(true, BaseTypes.UNION_QNAME);
private static final String NAME = "union";
- private static final QName QNAME = BaseTypes.constructQName(NAME);
private final List<TypeDefinition<?>> types;
private final List<TypeDefinitionBuilder> typedefs;
private boolean isBuilt;
public UnionTypeBuilder(final String moduleName, final int line) {
- super(moduleName, line, BaseTypes.constructQName(NAME));
+ super(moduleName, line, BaseTypes.UNION_QNAME);
types = new ArrayList<>();
typedefs = new ArrayList<>();
}
@Override
public SchemaPath getPath() {
- return SchemaPath.create(true, QNAME);
+ return SCHEMA_PATH;
}
@Override
import com.google.common.base.Splitter;
import com.google.common.collect.HashBiMap;
import com.google.common.io.ByteSource;
+
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
+
import javax.annotation.concurrent.Immutable;
+
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTree;
@Override
public SchemaContext parseFile(final File yangFile, final File directory) throws IOException,
- YangSyntaxErrorException {
+ YangSyntaxErrorException {
Preconditions.checkState(yangFile.exists(), yangFile + " does not exists");
Preconditions.checkState(directory.exists(), directory + " does not exists");
Preconditions.checkState(directory.isDirectory(), directory + " is not a directory");
@Override
public SchemaContext parseFiles(final Collection<File> yangFiles, final SchemaContext context) throws IOException,
- YangSyntaxErrorException {
+ YangSyntaxErrorException {
if (yangFiles == null) {
return resolveSchemaContext(Collections.<Module> emptySet());
}
@Override
public SchemaContext parseSources(final Collection<ByteSource> sources) throws IOException,
- YangSyntaxErrorException {
+ YangSyntaxErrorException {
Collection<Module> unsorted = parseYangModelSources(sources).values();
Set<Module> sorted = new LinkedHashSet<>(
ModuleDependencySort.sort(unsorted.toArray(new Module[unsorted.size()])));
return resolveSchemaContext(result);
}
- private LinkedHashMap<String, TreeMap<Date, ModuleBuilder>> resolveModulesWithImports(List<ModuleBuilder> sorted,
- SchemaContext context) {
+ private LinkedHashMap<String, TreeMap<Date, ModuleBuilder>> resolveModulesWithImports(final List<ModuleBuilder> sorted,
+ final SchemaContext context) {
final LinkedHashMap<String, TreeMap<Date, ModuleBuilder>> modules = orderModules(sorted);
for (ModuleBuilder module : sorted) {
if (module != null) {
}
private Map<ByteSource, Module> parseYangModelSources(final Collection<ByteSource> sources) throws IOException,
- YangSyntaxErrorException {
+ YangSyntaxErrorException {
if (sources == null || sources.isEmpty()) {
return Collections.emptyMap();
}
*/
// TODO: remove ByteSource result after removing YangModelParser
private Map<ByteSource, ModuleBuilder> resolveSources(final Collection<ByteSource> streams) throws IOException,
- YangSyntaxErrorException {
+ YangSyntaxErrorException {
Map<ByteSource, ModuleBuilder> builders = parseSourcesToBuilders(streams);
return resolveSubmodules(builders);
}
}
private Map<ByteSource, ParseTree> parseYangSources(final Collection<ByteSource> sources) throws IOException,
- YangSyntaxErrorException {
+ YangSyntaxErrorException {
final Map<ByteSource, ParseTree> trees = new HashMap<>();
for (ByteSource source : sources) {
trees.put(source, parseYangSource(source));
private void setCorrectAugmentTargetPath(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
final AugmentationSchemaBuilder augment) {
ModuleBuilder module = BuilderUtils.getParentModule(augment);
- Iterable<QName> oldPath = augment.getTargetPath().getPathFromRoot();
- List<QName> newPath = new ArrayList<>();
+ final SchemaPath newSchemaPath;
Builder parent = augment.getParent();
if (parent instanceof UsesNodeBuilder) {
DataNodeContainerBuilder usesParent = ((UsesNodeBuilder) parent).getParent();
- newPath.addAll(usesParent.getPath().getPath());
QName baseQName = usesParent.getQName();
final QNameModule qnm;
prefix = baseQName.getPrefix();
}
- for (QName qn : oldPath) {
- newPath.add(QName.create(qnm, prefix, qn.getLocalName()));
+ SchemaPath s = usesParent.getPath();
+ for (QName qn : augment.getTargetPath().getPathFromRoot()) {
+ s = s.createChild(QName.create(qnm, prefix, qn.getLocalName()));
}
+
+ newSchemaPath = s;
} else {
- for (QName qn : oldPath) {
+ final List<QName> newPath = new ArrayList<>();
+
+ for (QName qn : augment.getTargetPath().getPathFromRoot()) {
QNameModule qnm = module.getQNameModule();
String localPrefix = qn.getPrefix();
if (localPrefix != null && !localPrefix.isEmpty()) {
}
qnm = currentModule.getQNameModule();
}
- newPath.add(new QName(qnm.getNamespace(), qnm.getRevision(), localPrefix, qn.getLocalName()));
+ newPath.add(QName.create(qnm, localPrefix, qn.getLocalName()));
}
+
+ /*
+ * FIXME: this method of SchemaPath construction is highly ineffective.
+ * It would be great if we could actually dive into the context,
+ * find the actual target node and reuse its SchemaPath. Can we
+ * do that?
+ */
+ newSchemaPath = SchemaPath.create(newPath, true);
}
- augment.setTargetNodeSchemaPath(SchemaPath.create(newPath, true));
+ augment.setTargetNodeSchemaPath(newSchemaPath);
for (DataSchemaNodeBuilder childNode : augment.getChildNodeBuilders()) {
correctPathForAugmentNodes(childNode, augment.getTargetNodeSchemaPath());
}
}
- private void resolveIdentity(final Map<String, TreeMap<Date, ModuleBuilder>> modules, ModuleBuilder module,
+ private void resolveIdentity(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module,
final IdentitySchemaNodeBuilder identity) {
final String baseIdentityName = identity.getBaseIdentityName();
if (baseIdentityName != null) {
usnb.setExtensionDefinition(extDef);
}
} else {
- usnb.setNodeType(new QName(extBuilder.getQName().getNamespace(), extBuilder.getQName().getRevision(),
+ usnb.setNodeType(QName.create(extBuilder.getQName().getModule(),
nodeType.getPrefix(), extBuilder.getQName().getLocalName()));
usnb.setExtensionBuilder(extBuilder);
}
import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Yang_version_stmtContext;
import org.opendaylight.yangtools.antlrv4.code.gen.YangParserBaseListener;
import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
import org.opendaylight.yangtools.yang.model.util.BaseTypes;
setLog("namespace", namespaceStr);
} else if (treeNode instanceof Prefix_stmtContext) {
final String yangModelPrefix = stringFromNode(treeNode);
- this.moduleQName = new QName(moduleQName.getNamespace(), moduleQName.getRevision(), yangModelPrefix, moduleQName.getLocalName());
+ this.moduleQName = QName.create(moduleQName.getModule(), yangModelPrefix, moduleQName.getLocalName());
moduleBuilder.setPrefix(yangModelPrefix);
setLog("prefix", yangModelPrefix);
} else if (treeNode instanceof Yang_version_stmtContext) {
if (prefix.equals(moduleQName.getPrefix())) {
typeQName = QName.create(moduleQName, name);
} else {
- typeQName = new QName(null, null, prefix, name);
+ typeQName = QName.create(QNameModule.create(null, null), prefix, name);
}
} else {
typeQName = QName.create(moduleQName, typeName);
final String e0 = splittedElement.next();
final QName nodeType;
if (splittedElement.hasNext()) {
- nodeType = new QName(moduleQName.getNamespace(), moduleQName.getRevision(), e0, splittedElement.next());
+ nodeType = QName.create(moduleQName.getModule(), e0, splittedElement.next());
} else {
nodeType = QName.create(moduleQName, e0);
}
final Iterator<String> it = splittedName.iterator();
if (Iterables.size(splittedName) == 2) {
- qname = new QName(null, null, it.next(), it.next());
+ qname = QName.create(QNameModule.create(null, null), it.next(), it.next());
} else {
qname = QName.create(moduleQName, it.next());
}
import java.util.Set;
import org.junit.Test;
import org.opendaylight.yangtools.yang.model.api.Module;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.parser.api.YangModelParser;
public class TwoRevisionsTest {
@Test
public void testTwoRevisions() throws Exception {
- YangModelParser parser = new YangParserImpl();
-
Set<Module> modules = TestUtils.loadModules(getClass().getResource("/ietf").toURI());
assertEquals(2, TestUtils.findModules(modules, "network-topology").size());
-
- SchemaContext schemaContext = parser.resolveSchemaContext(modules);
- assertEquals(2, TestUtils.findModules(schemaContext.getModules(), "network-topology").size());
-
}
}
}
} catch (YangParseException e) {
String expected = "Error in module 'typedef' at line 10: typedef with same name 'int-ext' already declared at line 6.";
- assertTrue(e.getMessage().contains("'typedef' at line 10: typedef with same name 'int-ext' already declared at line 6."));
+ assertEquals(expected, e.getMessage());
}
}
}
}
+ @Test
+ public void testInvalidListKeyDefinition() throws Exception {
+ File yang1 = new File(getClass().getResource("/negative-scenario/invalid-list-key-def.yang").toURI());
+ try {
+ try (InputStream stream1 = new FileInputStream(yang1)) {
+ TestUtils.loadModule(stream1);
+ fail("YangParseException should by thrown");
+ }
+ } catch (YangParseException e) {
+ String expected = "Error in module 'invalid-list-key-def' at line 6: Failed to resolve list key for name rib-id";
+ assertEquals(expected, e.getMessage());
+ }
+ }
+
}
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import com.google.common.base.Optional;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
@Test
public void testMustEqualsBranch() {
assertEquals("rh should equal to rh1", rh, rh1);
- rh1.setMust(new MustDefinitionImpl("mustStr1", "description1", "reference1", "errorAppTag1", "errorMessage1"));
+ rh1.setMust(MustDefinitionImpl.create("mustStr1", Optional.of("description1"), Optional.of("reference1"),
+ Optional.of("errorAppTag1"), Optional.of("errorMessage1")));
assertFalse("rh shouldn't equal to rh1", rh.equals(rh1));
- rh.setMust(new MustDefinitionImpl("mustStr1", "description1", "reference1", "errorAppTag1", "errorMessage1"));
+ rh.setMust(MustDefinitionImpl.create("mustStr1", Optional.of("description1"), Optional.of("reference1"),
+ Optional.of("errorAppTag1"), Optional.of("errorMessage1")));
assertEquals("rh should equal to rh1", rh, rh1);
- rh.setMust(new MustDefinitionImpl("mustStr", "description", "reference", "errorAppTag", "errorMessage"));
+ rh.setMust(MustDefinitionImpl.create("mustStr", Optional.of("description"), Optional.of("reference"),
+ Optional.of("errorAppTag"), Optional.of("errorMessage")));
assertFalse("rh shouldn't equal to rh1", rh.equals(rh1));
- rh1.setMust(new MustDefinitionImpl("mustStr", "description", "reference", "errorAppTag", "errorMessage"));
+ rh1.setMust(MustDefinitionImpl.create("mustStr", Optional.of("description"), Optional.of("reference"),
+ Optional.of("errorAppTag"), Optional.of("errorMessage")));
}
@Test
--- /dev/null
+module invalid-list-key-def {
+ yang-version 1;
+ namespace "invalid:list:key:def";
+ prefix "p";
+
+ list application-map {
+ key "rib-id";
+
+ leaf bgp-id {
+ type string;
+ }
+ }
+
+}