*.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 com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil.computeDefaultSUID;
-import static org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil.moduleNamespaceToPackageName;
import static org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil.packageNameForGeneratedType;
import static org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil.parseToValidParamName;
import static org.opendaylight.yangtools.binding.generator.util.BindingTypes.DATA_OBJECT;
if (!m.getChildNodes().isEmpty()) {
final GeneratedTypeBuilder moduleType = moduleToDataType(m);
genCtx.get(m).addModuleNode(moduleType);
- final String basePackageName = moduleNamespaceToPackageName(m);
+ final String basePackageName = BindingMapping.getRootPackageName(m.getQNameModule());
resolveDataSchemaNodes(m, basePackageName, moduleType, moduleType, m.getChildNodes());
}
}
}
private void processUsesAugments(final DataNodeContainer node, final Module module) {
- final String basePackageName = moduleNamespaceToPackageName(module);
+ final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule());
for (UsesNode usesNode : node.getUses()) {
for (AugmentationSchema augment : usesNode.getAugmentations()) {
usesAugmentationToGenTypes(basePackageName, augment, module, usesNode, node);
checkArgument(module.getName() != null, "Module name cannot be NULL.");
checkState(module.getAugmentations() != null, "Augmentations Set cannot be NULL.");
- final String basePackageName = moduleNamespaceToPackageName(module);
+ final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule());
final List<AugmentationSchema> augmentations = resolveAugmentations(module);
for (AugmentationSchema augment : augmentations) {
augmentationToGenTypes(basePackageName, augment, module);
return;
}
- final String basePackageName = moduleNamespaceToPackageName(module);
+ final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule());
final GeneratedTypeBuilder interfaceBuilder = moduleTypeBuilder(module, "Service");
interfaceBuilder.addImplementsType(Types.typeForClass(RpcService.class));
for (RpcDefinition rpc : rpcDefinitions) {
final GeneratedTypeBuilder listenerInterface = moduleTypeBuilder(module, "Listener");
listenerInterface.addImplementsType(BindingTypes.NOTIFICATION_LISTENER);
- final String basePackageName = moduleNamespaceToPackageName(module);
+ final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule());
for (NotificationDefinition notification : notifications) {
if (notification != null) {
*/
private void allIdentitiesToGenTypes(final Module module, final SchemaContext context) {
final Set<IdentitySchemaNode> schemaIdentities = module.getIdentities();
- final String basePackageName = moduleNamespaceToPackageName(module);
+ final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule());
if (schemaIdentities != null && !schemaIdentities.isEmpty()) {
for (IdentitySchemaNode identity : schemaIdentities) {
newType.setExtendsType(gto.toInstance());
} else {
final Module baseIdentityParentModule = SchemaContextUtil.findParentModule(context, baseIdentity);
- final String returnTypePkgName = moduleNamespaceToPackageName(baseIdentityParentModule);
+ final String returnTypePkgName = BindingMapping.getRootPackageName(baseIdentityParentModule.getQNameModule());
final String returnTypeName = BindingMapping.getClassName(baseIdentity.getQName());
final GeneratedTransferObject gto = new GeneratedTOBuilderImpl(returnTypePkgName, returnTypeName)
.toInstance();
*
*/
private void groupingsToGenTypes(final Module module, final Collection<GroupingDefinition> groupings) {
- final String basePackageName = moduleNamespaceToPackageName(module);
+ final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule());
final List<GroupingDefinition> groupingsSortedByDependencies = new GroupingDefinitionDependencySort()
.sort(groupings);
for (GroupingDefinition grouping : groupingsSortedByDependencies) {
*/
private GeneratedTypeBuilder moduleTypeBuilder(final Module module, final String postfix) {
checkArgument(module != null, "Module reference cannot be NULL.");
- final String packageName = moduleNamespaceToPackageName(module);
+ final String packageName = BindingMapping.getRootPackageName(module.getQNameModule());
final String moduleName = BindingMapping.getClassName(module.getName()) + postfix;
return new GeneratedTypeBuilderImpl(packageName, moduleName);
}
final int length = Iterables.size(splittedElement);
if (length == 1) {
identity = findIdentityByName(module.getIdentities(), iterator.next());
- basePackageName = moduleNamespaceToPackageName(module);
+ basePackageName = BindingMapping.getRootPackageName(module.getQNameModule());
} else if (length == 2) {
String prefix = iterator.next();
final Module dependentModule = findModuleFromImports(module.getImports(), prefix);
+ prefix);
}
identity = findIdentityByName(dependentModule.getIdentities(), iterator.next());
- basePackageName = moduleNamespaceToPackageName(dependentModule);
+ basePackageName = BindingMapping.getRootPackageName(dependentModule.getQNameModule());
} else {
throw new IllegalArgumentException("Failed to process context-reference: unknown identity "
+ nodeParam);
import org.opendaylight.yangtools.yang.binding.Augmentation;
import org.opendaylight.yangtools.yang.binding.BaseIdentity;
import org.opendaylight.yangtools.yang.binding.BindingCodec;
+import org.opendaylight.yangtools.yang.binding.BindingMapping;
import org.opendaylight.yangtools.yang.binding.DataContainer;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.Identifier;
@Override
public Class<?> deserialize(final QName input) {
+ if(input == null) {
+ return null;
+ }
Type type = qnamesToIdentityMap.get(input);
if (type == null) {
- throw new IllegalArgumentException( "Invalid value \"" + input + "\"." );
+ String packageName = BindingMapping.getRootPackageName(input);
+ String className = BindingMapping.getClassName(input);
+ type = new ReferencedTypeImpl(packageName, className);
}
ReferencedTypeImpl typeref = new ReferencedTypeImpl(type.getPackageName(), type.getName());
WeakReference<Class> softref = typeToClass.get(typeref);
if (qname != null) {
return qname;
}
- ConcreteType typeref = Types.typeForClass(input);
- qname = typeToQname.get(typeref);
+ qname = BindingReflections.findQName(input);
if (qname != null) {
identityQNames.put(input, qname);
}
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.base.Splitter;
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.text.SimpleDateFormat;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
+
import org.opendaylight.yangtools.sal.binding.model.api.AccessModifier;
import org.opendaylight.yangtools.sal.binding.model.api.Restrictions;
import org.opendaylight.yangtools.sal.binding.model.api.Type;
import org.opendaylight.yangtools.sal.binding.model.api.type.builder.TypeMemberBuilder;
import org.opendaylight.yangtools.yang.binding.BindingMapping;
import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
*/
public final class BindingGeneratorUtil {
- private static final ThreadLocal<SimpleDateFormat> DATE_FORMAT = new ThreadLocal<SimpleDateFormat>() {
-
- @Override
- protected SimpleDateFormat initialValue() {
- return new SimpleDateFormat("yyMMdd");
- }
-
- @Override
- public void set(final SimpleDateFormat value) {
- throw new UnsupportedOperationException();
- }
- };
-
/**
* Impossible to instantiate this class. All of the methods or attributes
* are static.
/**
* Pre-compiled replacement pattern.
*/
- private static final Pattern COLON_SLASH_SLASH = Pattern.compile("://", Pattern.LITERAL);
- private static final String QUOTED_DOT = Matcher.quoteReplacement(".");
- private static final Splitter DOT_SPLITTER = Splitter.on('.');
private static final CharMatcher DOT_MATCHER = CharMatcher.is('.');
private static final CharMatcher DASH_COLON_MATCHER = CharMatcher.anyOf("-:");
- /**
- * Converts string <code>packageName</code> to valid JAVA package name.
- *
- * If some words of package name are digits of JAVA reserved words they are
- * prefixed with underscore character.
- *
- * @param packageName
- * string which contains words separated by point.
- * @return package name which contains words separated by point.
- */
- private static String validateJavaPackage(final String packageName) {
- if (packageName == null) {
- return null;
+ private static final Restrictions EMPTY_RESTRICTIONS = new Restrictions() {
+ @Override
+ public List<LengthConstraint> getLengthConstraints() {
+ return Collections.emptyList();
}
- final StringBuilder builder = new StringBuilder();
- boolean first = true;
+ @Override
+ public List<PatternConstraint> getPatternConstraints() {
+ return Collections.emptyList();
+ }
- for (String p : DOT_SPLITTER.split(packageName.toLowerCase())) {
- if (first) {
- first = false;
- } else {
- builder.append('.');
- }
+ @Override
+ public List<RangeConstraint> getRangeConstraints() {
+ return Collections.emptyList();
+ }
- if (Character.isDigit(p.charAt(0)) || BindingMapping.JAVA_RESERVED_WORDS.contains(p)) {
- builder.append('_');
- }
- builder.append(p);
+ @Override
+ public boolean isEmpty() {
+ return true;
}
+ };
- return builder.toString();
- }
+ 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.
* @throws IllegalArgumentException
* if the revision date of the <code>module</code> equals
* <code>null</code>
+ * @deprecated USe {@link BindingMapping#getRootPackageName(QNameModule)} with {@link Module#getQNameModule()}.
*/
+ @Deprecated
public static String moduleNamespaceToPackageName(final Module module) {
- final StringBuilder packageNameBuilder = new StringBuilder();
-
- if (module.getRevision() == null) {
- throw new IllegalArgumentException("Module " + module.getName() + " does not specify revision date!");
- }
- packageNameBuilder.append(BindingMapping.PACKAGE_PREFIX);
- packageNameBuilder.append('.');
-
- String namespace = module.getNamespace().toString();
- namespace = COLON_SLASH_SLASH.matcher(namespace).replaceAll(QUOTED_DOT);
-
- final char[] chars = namespace.toCharArray();
- for (int i = 0; i < chars.length; ++i) {
- switch (chars[i]) {
- case '/':
- case ':':
- case '-':
- case '@':
- case '$':
- case '#':
- case '\'':
- case '*':
- case '+':
- case ',':
- case ';':
- case '=':
- chars[i] = '.';
- }
- }
-
- packageNameBuilder.append(chars);
- packageNameBuilder.append(".rev");
- packageNameBuilder.append(DATE_FORMAT.get().format(module.getRevision()));
-
- return validateJavaPackage(packageNameBuilder.toString());
+ return BindingMapping.getRootPackageName(module.getQNameModule());
}
public static String packageNameForGeneratedType(final String basePackageName, final SchemaPath schemaPath) {
for (int i = 0; i < traversalSteps; ++i) {
builder.append('.');
String nodeLocalName = iterator.next().getLocalName();
-
+ // FIXME: Collon ":" is invalid in node local name as per RFC6020, identifier statement.
builder.append(DASH_COLON_MATCHER.replaceFrom(nodeLocalName, '.'));
}
- return validateJavaPackage(builder.toString());
+ return BindingMapping.normalizePackageName(builder.toString());
}
/**
final StringBuilder builder = new StringBuilder();
builder.append(basePackageName);
- return validateJavaPackage(builder.toString());
+ return BindingMapping.normalizePackageName(builder.toString());
}
/**
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;
}
};
}
<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>
«generateLengthRestriction(returnType, restrictions, paramName, isNestedType)»
«ENDIF»
«IF !restrictions.rangeConstraints.empty»
- «generateRangeRestriction(returnType, restrictions, paramName, isNestedType)»
+ «generateRangeRestriction(returnType, paramName, isNestedType)»
«ENDIF»
«ENDIF»
'''
}
'''
- def private generateRangeRestriction(Type returnType, Restrictions restrictions, String paramName, boolean isNestedType) '''
- «val clazz = restrictions.rangeConstraints.iterator.next.min.class»
+ def private generateRangeRestriction(Type returnType, String paramName, boolean isNestedType) '''
if («paramName» != null) {
- «printRangeConstraint(returnType, clazz, paramName, isNestedType)»
+ «printRangeConstraint(returnType, paramName, isNestedType)»
boolean isValidRange = false;
- for («Range.importedName»<«clazz.importedNumber»> r : «IF isNestedType»«returnType.importedName».«ENDIF»range()) {
+ for («Range.importedName»<«returnType.importedNumber»> r : «IF isNestedType»«returnType.importedName».«ENDIF»range()) {
if (r.contains(_constraint)) {
isValidRange = true;
}
«clazz.importedNumber» _constraint = «clazz.importedNumber».valueOf(«paramName»«IF isNestedType».getValue()«ENDIF».length«IF !isArray»()«ENDIF»);
'''
- def printRangeConstraint(Type returnType, Class<? extends Number> clazz, String paramName, boolean isNestedType) '''
- «IF clazz.canonicalName.equals(BigDecimal.canonicalName)»
- «clazz.importedNumber» _constraint = new «clazz.importedNumber»(«paramName»«IF isNestedType».getValue()«ENDIF».toString());
+ def printRangeConstraint(Type returnType, String paramName, boolean isNestedType) '''
+ «IF BigDecimal.canonicalName.equals(returnType.fullyQualifiedName)»
+ «BigDecimal.importedName» _constraint = new «BigDecimal.importedName»(«paramName»«IF isNestedType».getValue()«ENDIF».toString());
«ELSE»
«IF isNestedType»
«val propReturnType = findProperty(returnType as GeneratedTransferObject, "value").returnType»
«IF propReturnType.fullyQualifiedName.equals(BigInteger.canonicalName)»
- «clazz.importedNumber» _constraint = «paramName».getValue();
+ «BigInteger.importedName» _constraint = «paramName».getValue();
«ELSE»
- «clazz.importedNumber» _constraint = «clazz.importedNumber».valueOf(«paramName».getValue());
+ «BigInteger.importedName» _constraint = «BigInteger.importedName».valueOf(«paramName».getValue());
«ENDIF»
«ELSE»
«IF returnType.fullyQualifiedName.equals(BigInteger.canonicalName)»
- «clazz.importedNumber» _constraint = «paramName»;
+ «BigInteger.importedName» _constraint = «paramName»;
«ELSE»
- «clazz.importedNumber» _constraint = «clazz.importedNumber».valueOf(«paramName»);
+ «BigInteger.importedName» _constraint = «BigInteger.importedName».valueOf(«paramName»);
«ENDIF»
«ENDIF»
«ENDIF»
«ENDIF»
'''
- def GeneratedProperty getPropByName(GeneratedType gt, String name) {
- for (GeneratedProperty prop : gt.properties) {
- if (prop.name.equals(name)) {
- return prop;
- }
- }
- return null;
- }
-
def getRestrictions(Type type) {
var Restrictions restrictions = null
if (type instanceof ConcreteType) {
return «varName»;
'''
- def protected generateRangeMethod(String methodName, Type type, String className, String varName) '''
- «val Restrictions restrictions = type.restrictions»
+ def protected generateRangeMethod(String methodName, Restrictions restrictions, Type returnType, String className, String varName) '''
«IF restrictions != null && !(restrictions.rangeConstraints.empty)»
- «val numberClass = restrictions.rangeConstraints.iterator.next.min.class»
- public static «List.importedName»<«Range.importedName»<«numberClass.importedNumber»>> «methodName»() {
- «IF numberClass.equals(typeof(BigDecimal))»
- «rangeMethodBody(restrictions, numberClass, className, varName)»
+ «val number = returnType.importedNumber»
+ public static «List.importedName»<«Range.importedName»<«number»>> «methodName»() {
+ «IF returnType.fullyQualifiedName.equals(BigDecimal.canonicalName)»
+ «rangeMethodBody(restrictions, BigDecimal, className, varName)»
+ «ELSE»
+ «rangeMethodBody(restrictions, BigInteger, className, varName)»
+ «ENDIF»
+ }
+ «ENDIF»
+ '''
+
+ def protected generateRangeMethod(String methodName, Restrictions restrictions, String className, String varName, Iterable<GeneratedProperty> properties) '''
+ «IF restrictions != null && !(restrictions.rangeConstraints.empty)»
+ «val returnType = properties.iterator.next.returnType»
+ public static «List.importedName»<«Range.importedName»<«returnType.importedNumber»>> «methodName»() {
+ «IF returnType.fullyQualifiedName.equals(BigDecimal.canonicalName)»
+ «rangeMethodBody(restrictions, BigDecimal, className, varName)»
«ELSE»
- «rangeMethodBody(restrictions, typeof(BigInteger), className, varName)»
+ «rangeMethodBody(restrictions, BigInteger, className, varName)»
«ENDIF»
}
«ENDIF»
return BigInteger.importedName
}
+ def protected String importedNumber(Type clazz) {
+ if (clazz.fullyQualifiedName.equals(BigDecimal.canonicalName)) {
+ return BigDecimal.importedName
+ }
+ return BigInteger.importedName
+ }
+
def private String numericValue(Class<? extends Number> clazz, Object numberValue) {
val number = clazz.importedName;
val value = numberValue.toString
«val restrictions = f.returnType.restrictions»
«IF !_final && restrictions != null»
«IF !(restrictions.lengthConstraints.empty)»
- «val clazz = restrictions.lengthConstraints.iterator.next.min.class»
- private static «List.importedName»<«Range.importedName»<«clazz.importedNumber»>> «f.fieldName»_length;
+ private static «List.importedName»<«Range.importedName»<«f.returnType.importedNumber»>> «f.fieldName»_length;
«ENDIF»
«IF !(restrictions.rangeConstraints.empty)»
- «val clazz = restrictions.rangeConstraints.iterator.next.min.class»
- private static «List.importedName»<«Range.importedName»<«clazz.importedNumber»>> «f.fieldName»_range;
+ private static «List.importedName»<«Range.importedName»<«f.returnType.importedNumber»>> «f.fieldName»_range;
«ENDIF»
«ENDIF»
«ENDFOR»
return this;
}
«generateLengthMethod(length, field.returnType, type.name+BUILDER, length)»
- «generateRangeMethod(range, field.returnType, type.name+BUILDER, range)»
+ «generateRangeMethod(range, field.returnType.restrictions, field.returnType, type.name+BUILDER, range)»
«ENDFOR»
«IF augmentField != null»
«generateLengthRestriction(type, paramName, lengthGetter, isNestedType, isArray)»
«ENDIF»
«IF !restrictions.rangeConstraints.empty»
- «generateRangeRestriction(type, paramName, rangeGetter, isNestedType, isArray)»
+ «generateRangeRestriction(type, paramName, rangeGetter, isNestedType)»
«ENDIF»
«ENDIF»
'''
}
'''
- def private generateRangeRestriction(Type type, String paramName, String getterName, boolean isNestedType, boolean isArray) '''
- «val restrictions = type.getRestrictions»
+ def private generateRangeRestriction(Type type, String paramName, String getterName, boolean isNestedType) '''
if («paramName» != null) {
- «val clazz = restrictions.rangeConstraints.iterator.next.min.class»
- «printRangeConstraint(type, clazz, paramName, isNestedType)»
+ «printRangeConstraint(type, paramName, isNestedType)»
boolean isValidRange = false;
- for («Range.importedName»<«clazz.importedNumber»> r : «getterName»()) {
+ for («Range.importedName»<«type.importedNumber»> r : «getterName»()) {
if (r.contains(_constraint)) {
isValidRange = true;
}
«generateLengthMethod("length", genTO, genTO.importedName, "_length")»
- «generateRangeMethod("range", genTO, genTO.importedName, "_range")»
+ «generateRangeMethod("range", genTO.restrictions, genTO.importedName, "_range", allProperties)»
}
'''
*/
def protected generateFields() '''
«IF restrictions != null»
- «IF !(restrictions.lengthConstraints.empty)»
- «val numberClass = restrictions.lengthConstraints.iterator.next.min.class»
- private static «List.importedName»<«Range.importedName»<«numberClass.importedNumber»>> _length;
- «ENDIF»
- «IF !(restrictions.rangeConstraints.empty)»
- «val numberClass = restrictions.rangeConstraints.iterator.next.min.class»
- private static «List.importedName»<«Range.importedName»<«numberClass.importedNumber»>> _range;
+ «val prop = getPropByName("value")»
+ «IF prop != null»
+ «IF !(restrictions.lengthConstraints.empty)»
+ private static «List.importedName»<«Range.importedName»<«prop.returnType.importedNumber»>> _length;
+ «ENDIF»
+ «IF !(restrictions.rangeConstraints.empty)»
+ private static «List.importedName»<«Range.importedName»<«prop.returnType.importedNumber»>> _range;
+ «ENDIF»
«ENDIF»
«ENDIF»
«IF !properties.empty»
«ENDIF»
'''
-
/**
* Template method which generates the method <code>hashCode()</code>.
*
«ENDIF»
'''
+ def GeneratedProperty getPropByName(String name) {
+ for (GeneratedProperty prop : allProperties) {
+ if (prop.name.equals(name)) {
+ return prop;
+ }
+ }
+ return null;
+ }
+
}
assertTrue(unionExt2.exists());
assertTrue(unionExt3.exists());
assertTrue(unionExt4.exists());
- assertFilesCount(parent, 30);
+ assertFilesCount(parent, 31);
// Test if sources are compilable
testCompilation(sourcesOutputDir, compiledOutputDir);
Class<?> int32Ext1Class = Class.forName(pkg + ".Int32Ext1", true, loader);
Class<?> int32Ext2Class = Class.forName(pkg + ".Int32Ext2", true, loader);
Class<?> myDecimalTypeClass = Class.forName(pkg + ".MyDecimalType", true, loader);
+ Class<?> myDecimalType2Class = Class.forName(pkg + ".MyDecimalType2", true, loader);
Class<?> stringExt1Class = Class.forName(pkg + ".StringExt1", true, loader);
Class<?> stringExt2Class = Class.forName(pkg + ".StringExt2", true, loader);
Class<?> stringExt3Class = Class.forName(pkg + ".StringExt3", true, loader);
obj = expectedConstructor.newInstance(new BigDecimal("3.14"));
assertEquals(obj, defInst.invoke(null, "3.14"));
+ // typedef my-decimal-type2
+ assertFalse(myDecimalType2Class.isInterface());
+ assertContainsField(myDecimalType2Class, VAL, BigDecimal.class);
+ assertContainsField(myDecimalType2Class, RANGE, List.class);
+ assertContainsFieldWithValue(myDecimalType2Class, "serialVersionUID", Long.TYPE, -672265764962082714L, BigDecimal.class);
+ assertEquals(3, myDecimalType2Class.getDeclaredFields().length);
+ assertContainsMethod(myDecimalType2Class, BigDecimal.class, "getValue");
+ expectedConstructor = assertContainsConstructor(myDecimalType2Class, BigDecimal.class);
+ assertContainsConstructor(myDecimalType2Class, myDecimalType2Class);
+ assertEquals(2, myDecimalType2Class.getDeclaredConstructors().length);
+ assertContainsMethod(myDecimalType2Class, BigDecimal.class, GET_VAL);
+ assertContainsDefaultMethods(myDecimalType2Class);
+ defInst = assertContainsMethod(myDecimalType2Class, myDecimalType2Class, "getDefaultInstance", String.class);
+ assertContainsGetLengthOrRange(myDecimalType2Class, false);
+ assertEquals(6, myDecimalType2Class.getDeclaredMethods().length);
+
+ List<Range<BigDecimal>> decimal2RangeConstraints = new ArrayList<>();
+ decimal2RangeConstraints.add(Range.closed(new BigDecimal("0"), new BigDecimal("1")));
+ arg = new BigDecimal("1.4");
+ expectedMsg = String.format("Invalid range: %s, expected: %s.", arg, decimal2RangeConstraints);
+ assertContainsRestrictionCheck(expectedConstructor, expectedMsg, arg);
+ obj = expectedConstructor.newInstance(new BigDecimal("0.14"));
+ assertEquals(obj, defInst.invoke(null, "0.14"));
+
// typedef union-ext1
assertFalse(unionExt1Class.isInterface());
assertContainsField(unionExt1Class, "_int16", Short.class);
}
}
+ typedef my-decimal-type2 {
+ type decimal64 {
+ fraction-digits 18;
+ range "0..1";
+ }
+ }
+
typedef union-ext1 {
type union {
type int16 {
<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 name='yangtools-all' version='${project.version}'>
<feature version='${project.version}'>yangtools-models</feature>
- <feature version='${project.version}'>yangtools-binding</feature>
+ <feature version='${project.version}'>yangtools-data-binding</feature>
<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.model/ietf-topology/${ietf.topology.version}</bundle>
</feature>
- <feature name='yangtools-binding' version='${project.version}'>
+ <feature name='yangtools-data-binding' version='${project.version}'>
<feature version='${project.version}'>yangtools-concepts</feature>
+ <feature version='${project.version}'>yangtools-binding</feature>
<bundle>mvn:org.opendaylight.yangtools.thirdparty/antlr4-runtime-osgi-nohead/${antlr4.version}</bundle>
<bundle>mvn:commons-io/commons-io/${commons.io.version}</bundle>
- <bundle>mvn:org.opendaylight.yangtools/yang-binding/${project.version}</bundle>
<bundle>mvn:org.opendaylight.yangtools/yang-data-api/${project.version}</bundle>
<bundle>mvn:org.opendaylight.yangtools/yang-data-impl/${project.version}</bundle>
<bundle>mvn:org.opendaylight.yangtools/yang-data-json/${project.version}</bundle>
<bundle>mvn:org.opendaylight.yangtools/yang-parser-api/${project.version}</bundle>
</feature>
+ <feature name='yangtools-binding' version='${project.version}'>
+ <feature version='${project.version}'>yangtools-concepts</feature>
+ <bundle>mvn:com.google.guava/guava/${guava.version}</bundle>
+ <bundle>mvn:org.opendaylight.yangtools/yang-binding/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.yangtools/util/${project.version}</bundle>
+ </feature>
+
<feature name='yangtools-concepts' version='${project.version}'>
<bundle>mvn:org.opendaylight.yangtools/concepts/${project.version}</bundle>
<bundle>mvn:org.opendaylight.yangtools/yang-common/${project.version}</bundle>
- <bundle>wrap:mvn:com.google.guava/guava/${guava.version}</bundle>
- <bundle>wrap:mvn:org.eclipse.xtend/org.eclipse.xtend.lib/${xtend.version}</bundle>
- <bundle>wrap:mvn:org.eclipse.xtext/org.eclipse.xtext.xbase.lib/${xtend.version}</bundle>
+ <bundle>mvn:com.google.guava/guava/${guava.version}</bundle>
</feature>
<feature name="yangtools-common" version='${project.version}'>
<bundle>mvn:org.opendaylight.yangtools/util/${project.version}</bundle>
<bundle>mvn:org.opendaylight.yangtools/object-cache-noop/${project.version}</bundle>
</feature>
<feature name='yangtools-binding-generator' version='${project.version}'>
- <feature version='${project.version}'>yangtools-binding</feature>
+ <feature version='${project.version}'>yangtools-data-binding</feature>
<bundle>mvn:org.javassist/javassist/${javassist.version}</bundle>
<bundle>mvn:org.apache.commons/commons-lang3/${commons.lang3.version}</bundle>
<bundle>mvn:org.opendaylight.yangtools/binding-generator-api/${project.version}</bundle>
<bundle>mvn:org.opendaylight.yangtools/binding-generator-util/${project.version}</bundle>
<bundle>mvn:org.opendaylight.yangtools/binding-model-api/${project.version}</bundle>
<bundle>mvn:org.opendaylight.yangtools/binding-type-provider/${project.version}</bundle>
-
+ <bundle>wrap:mvn:org.eclipse.xtend/org.eclipse.xtend.lib/${xtend.version}</bundle>
+ <bundle>wrap:mvn:org.eclipse.xtext/org.eclipse.xtext.xbase.lib/${xtend.version}</bundle>
+ <bundle>mvn:org.opendaylight.yangtools/yang-model-api/${project.version}</bundle>
+ <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>
import static com.google.common.base.Preconditions.checkArgument;
+import java.text.SimpleDateFormat;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+
import com.google.common.base.CharMatcher;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableSet;
-import java.util.Set;
-import org.opendaylight.yangtools.yang.common.QName;
public final class BindingMapping {
private static final Splitter CAMEL_SPLITTER = Splitter.on(CharMatcher.anyOf(" _.-").precomputed())
.omitEmptyStrings().trimResults();
+ private static final Pattern COLON_SLASH_SLASH = Pattern.compile("://", Pattern.LITERAL);
+ private static final String QUOTED_DOT = Matcher.quoteReplacement(".");
+ private static final Splitter DOT_SPLITTER = Splitter.on('.');
public static final String MODULE_INFO_CLASS_NAME = "$YangModuleInfoImpl";
public static final String MODEL_BINDING_PROVIDER_CLASS_NAME = "$YangModelBindingProvider";
public static final String RPC_INPUT_SUFFIX = "Input";
public static final String RPC_OUTPUT_SUFFIX = "Output";
+ private static final ThreadLocal<SimpleDateFormat> PACKAGE_DATE_FORMAT = new ThreadLocal<SimpleDateFormat>() {
+
+ @Override
+ protected SimpleDateFormat initialValue() {
+ return new SimpleDateFormat("yyMMdd");
+ }
+
+ @Override
+ public void set(final SimpleDateFormat value) {
+ throw new UnsupportedOperationException();
+ }
+ };
+
private BindingMapping() {
throw new UnsupportedOperationException("Utility class should not be instantiated");
}
+ public static final String getRootPackageName(final QName module) {
+ return getRootPackageName(module.getModule());
+ }
+
+ public static final String getRootPackageName(final QNameModule module) {
+ checkArgument(module != null, "Module must not be null");
+ checkArgument(module.getRevision() != null, "Revision must not be null");
+ checkArgument(module.getNamespace() != null, "Namespace must not be null");
+ final StringBuilder packageNameBuilder = new StringBuilder();
+
+ packageNameBuilder.append(BindingMapping.PACKAGE_PREFIX);
+ packageNameBuilder.append('.');
+
+ String namespace = module.getNamespace().toString();
+ namespace = COLON_SLASH_SLASH.matcher(namespace).replaceAll(QUOTED_DOT);
+
+ final char[] chars = namespace.toCharArray();
+ for (int i = 0; i < chars.length; ++i) {
+ switch (chars[i]) {
+ case '/':
+ case ':':
+ case '-':
+ case '@':
+ case '$':
+ case '#':
+ case '\'':
+ case '*':
+ case '+':
+ case ',':
+ case ';':
+ case '=':
+ chars[i] = '.';
+ }
+ }
+
+ packageNameBuilder.append(chars);
+ packageNameBuilder.append(".rev");
+ packageNameBuilder.append(PACKAGE_DATE_FORMAT.get().format(module.getRevision()));
+ return normalizePackageName(packageNameBuilder.toString());
+
+ }
+
+ public static String normalizePackageName(final String packageName) {
+ if (packageName == null) {
+ return null;
+ }
+
+ final StringBuilder builder = new StringBuilder();
+ boolean first = true;
+
+ for (String p : DOT_SPLITTER.split(packageName.toLowerCase())) {
+ if (first) {
+ first = false;
+ } else {
+ builder.append('.');
+ }
+
+ if (Character.isDigit(p.charAt(0)) || BindingMapping.JAVA_RESERVED_WORDS.contains(p)) {
+ builder.append('_');
+ }
+ builder.append(p);
+ }
+
+ return builder.toString();
+ }
+
public static final String getMethodName(final QName name) {
checkArgument(name != null, "Name should not be null.");
return getMethodName(name.getLocalName());
<description>${project.artifactId}</description>
<dependencies>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
*/
@Deprecated
public QName(final QName base, final String localName) {
- this(base.getNamespace(), base.getRevision(), base.getPrefix(), localName);
+ this(base.getModule(), base.getPrefix(), localName);
}
/**
}
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");
package org.opendaylight.yangtools.yang.common;
/**
- *
- * Representation of Error in YANG enabled system.
- *
- * Which may be send / received by YANG modeled / enabled systems.
+ * Representation of an error.
*
*/
public interface RpcError {
+ public enum ErrorSeverity {
+ ERROR,
+ WARNING
+ }
+
+ public enum ErrorType {
+ /**
+ * Indicates an error occurred during transport of data, eg over the network.
+ */
+ TRANSPORT,
+
+ /**
+ * Indicates an error occurred during a remote procedure call.
+ */
+ RPC,
+
+ /**
+ * Indicates an error at a protocol layer, eg if invalid data was passed by the caller.
+ */
+ PROTOCOL,
+
+ /**
+ * Indicates an error occurred during internal processing.
+ */
+ APPLICATION
+ }
+
/**
+ * Returns the error severity, as determined by the application reporting the error.
*
- * Returns error severity, as determined by component reporting the error.
- *
- * @return error severity
+ * @return an {@link ErrorSeverity} enum.
*/
ErrorSeverity getSeverity();
/**
- *
- * Returns a string identifying the error condition.
- *
- * @return string identifying the error condition.
+ * Returns a short string that identifies the general type of error condition.
+ * <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
+ * </pre>
+ * @return a string if available or null otherwise.
*/
String getTag();
/**
+ * Returns a short string that identifies the specific type of error condition as
+ * determined by the application reporting the error.
*
- * Returns a string identifying the data-model-specific or
- * implementation-specific error condition, if one exists. This element will
- * not be present if no appropriate application error-tag can be associated
- * with a particular error condition. If a data-model-specific and an
- * implementation-specific error-app-tag both exist, then the
- * data-model-specific value MUST be used by the reporter.
- *
- * @return Returns a string identifying the data-model-specific or
- * implementation-specific error condition, or null if does not
- * exists.
+ * @return a string if available or null otherwise.
*/
String getApplicationTag();
/**
- *
* Returns a string suitable for human display that describes the error
- * condition. This element will not be present if no appropriate message is
- * provided for a particular error condition.
+ * condition.
*
- * @return returns an error description for human display.
+ * @return a message string.
*/
String getMessage();
/**
*
- * Contains protocol- or data-model-specific error content. This value may
- * be not be present if no such error content is provided for a particular
- * error condition.
- *
- * The list in Appendix A defines any mandatory error-info content for each
- * error. After any protocol-mandated content, a data model definition MAY
- * mandate that certain application-layer error information be included in
- * the error-info container.
- *
- * An implementation MAY include additional information to provide extended
- * and/or implementation- specific debugging information.
+ * Returns a string containing additional information to provide extended
+ * and/or implementation-specific debugging information.
*
- * @return
+ * @return a string if available or null otherwise.
*/
String getInfo();
/**
*
- * Return a cause if available.
+ * Returns an exception cause.
*
- * @return cause of this error, if error was triggered by exception.
+ * @return a Throwable if the error was triggered by exception, null otherwise.
*/
Throwable getCause();
/**
- * Returns the conceptual layer that on which the error occurred.
+ * Returns the conceptual layer at which the error occurred.
*
- * @return the conceptual layer that on which the error occurred.
+ * @return an {@link ErrorType} enum.
*/
ErrorType getErrorType();
-
- public enum ErrorSeverity {
- ERROR, WARNING,
- }
-
- public enum ErrorType {
- TRANSPORT, RPC, PROTOCOL, APPLICATION
- }
}
import java.util.Collection;
/**
+ * Represents a general result of a call, request, or operation.
*
- * Result of call to YANG enabled system.
- *
- *
- * @param <T> Return type
+ * @param <T> the result value type
*/
public interface RpcResult<T> {
/**
- * True if processing of request was successful
+ * Returns whether or not processing of the call was successful.
*
- * @return true if processing was successful.
+ * @return true if processing was successful, false otherwise.
*/
boolean isSuccessful();
/**
- *
- * Returns result of call or null if no result is available.
- *
- * @return result of call or null if no result is available.
- *
+ * Returns the value result of the call or null if no result is available.
*/
T getResult();
/**
+ * Returns a set of errors and warnings which occurred during processing
+ * the call.
*
- * Returns set of errors and warnings which occured during processing
- * the request.
- *
- * @return
+ * @return a Collection of {@link RpcError}
*/
Collection<RpcError> getErrors();
}
--- /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.yang.common;
+
+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.
+ *
+ * @author Thomas Pantelis
+ *
+ * @param <T> the result value type
+ */
+public final class RpcResultBuilder<T> {
+
+ private static class RpcResultImpl<T> implements RpcResult<T> {
+
+ private final Collection<RpcError> errors;
+ private final T result;
+ private final boolean successful;
+
+ RpcResultImpl( boolean successful, T result,
+ Collection<RpcError> errors ) {
+ this.successful = successful;
+ this.result = result;
+ this.errors = errors;
+ }
+
+ @Override
+ public Collection<RpcError> getErrors() {
+ return errors;
+ }
+
+ @Override
+ public T getResult() {
+ return result;
+ }
+
+ @Override
+ public boolean isSuccessful() {
+ return successful;
+ }
+
+ @Override
+ public String toString(){
+ return "RpcResult [successful=" + successful + ", result="
+ + result + ", errors=" + errors + "]";
+ }
+ }
+
+ private static class RpcErrorImpl implements RpcError {
+
+ private final String applicationTag;
+ private final String tag;
+ private final String info;
+ private final ErrorSeverity severity;
+ private final String message;
+ private final ErrorType errorType;
+ private final Throwable cause;
+
+ RpcErrorImpl( ErrorSeverity severity, ErrorType errorType,
+ String tag, String message, String applicationTag, String info,
+ Throwable cause ) {
+ this.severity = severity;
+ this.errorType = errorType;
+ this.tag = tag;
+ this.message = message;
+ this.applicationTag = applicationTag;
+ this.info = info;
+ this.cause = cause;
+ }
+
+ @Override
+ public String getApplicationTag() {
+ return applicationTag;
+ }
+
+ @Override
+ public String getTag() {
+ return tag;
+ }
+
+ @Override
+ public String getInfo() {
+ return info;
+ }
+
+ @Override
+ public ErrorSeverity getSeverity() {
+ return severity;
+ }
+
+ @Override
+ public String getMessage(){
+ return message;
+ }
+
+ @Override
+ public ErrorType getErrorType() {
+ return errorType;
+ }
+
+ @Override
+ public Throwable getCause() {
+ return cause;
+ }
+
+ @Override
+ public String toString(){
+ return "RpcError [message=" + message + ", severity="
+ + severity + ", errorType=" + errorType + ", tag=" + tag
+ + ", applicationTag=" + applicationTag + ", info=" + info
+ + ", cause=" + cause + "]";
+ }
+ }
+
+ private ImmutableList.Builder<RpcError> errors;
+ private T result;
+ private final boolean successful;
+
+ private RpcResultBuilder( boolean successful, T result ) {
+ this.successful = successful;
+ this.result = result;
+ }
+
+ /**
+ * Returns a builder for a successful result.
+ */
+ public static <T> RpcResultBuilder<T> success() {
+ return new RpcResultBuilder<T>( true, null );
+ }
+
+ /**
+ * Returns a builder for a successful result.
+ *
+ * @param result the result value
+ */
+ public static <T> RpcResultBuilder<T> success( T result ) {
+ return new RpcResultBuilder<T>( true, result );
+ }
+
+ /**
+ * Returns a builder for a failed result.
+ */
+ public static <T> RpcResultBuilder<T> failed() {
+ 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.
+ *
+ * @param result the result value
+ */
+ public RpcResultBuilder<T> withResult( T result ) {
+ this.result = result;
+ return this;
+ }
+
+ private void addError( ErrorSeverity severity, ErrorType errorType,
+ 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 ImmutableList.Builder<RpcError>();
+ }
+
+ errors.add( error );
+ }
+
+ /**
+ * Adds a warning to the result.
+ *
+ * @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.
+ */
+ public RpcResultBuilder<T> withWarning( ErrorType errorType, String tag, String message ) {
+ addError( ErrorSeverity.WARNING, errorType, tag, message, null, null, null );
+ return this;
+ }
+
+ /**
+ * Adds a warning to the result.
+ *
+ * @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.
+ */
+ public RpcResultBuilder<T> withWarning( ErrorType errorType, String tag, String message,
+ String applicationTag, String info, Throwable cause ) {
+ addError( ErrorSeverity.WARNING, errorType, tag, message, applicationTag, info, cause );
+ 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.
+ */
+ public RpcResultBuilder<T> withError( ErrorType errorType, String message ) {
+ addError( ErrorSeverity.ERROR, errorType, null, message, null, null, null );
+ return this;
+ }
+
+ /**
+ * Adds an error to the result.
+ *
+ * @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.
+ */
+ public RpcResultBuilder<T> withError( ErrorType errorType, String tag, String message ) {
+ addError( ErrorSeverity.ERROR, errorType, tag, message, null, null, null );
+ 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.
+ *
+ * @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.
+ */
+ public RpcResultBuilder<T> withError( ErrorType errorType, String tag, String message,
+ String applicationTag, String info, Throwable cause ) {
+ addError( ErrorSeverity.ERROR, errorType, tag, message, applicationTag, info, cause );
+ 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.build() : Collections.<RpcError>emptyList() );
+ }
+}
--- /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.yang.common;
+
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.common.RpcError.ErrorSeverity;
+import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
+
+/**
+ * Unit tests for RpcResultBuilder.
+ *
+ * @author Thomas Pantelis
+ */
+public class RpcResultBuilderTest {
+
+ @Test
+ public void testSuccess() {
+ RpcResult<String> result = RpcResultBuilder.<String>success().withResult( "foo" ).build();
+ verifyRpcResult( result, true, "foo" );
+ assertNotNull( "getErrors returned null", result.getErrors() );
+ assertEquals( "getErrors size", 0, result.getErrors().size() );
+
+ result = RpcResultBuilder.<String>success( "bar" ).build();
+ verifyRpcResult( result, true, "bar" );
+ }
+
+ @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 1", null, null, null );
+ verifyRpcError( result, 1, ErrorSeverity.ERROR, ErrorType.APPLICATION, "lock_denied",
+ "error message 2", null, null, null );
+ verifyRpcError( result, 2, ErrorSeverity.ERROR, ErrorType.RPC, "in-use",
+ "error message 3", "my-app-tag", "my-info", cause );
+ verifyRpcError( result, 3, ErrorSeverity.ERROR, ErrorType.TRANSPORT, "operation-failed",
+ "error message 4", null, null, cause2 );
+ assertEquals( "getErrors size", 4, result.getErrors().size() );
+ }
+
+ @Test
+ public void testWithWarnings() {
+ Throwable cause = new Throwable( "mock cause" );
+ RpcResult<String> result = RpcResultBuilder.<String>success()
+ .withWarning( ErrorType.APPLICATION, "lock_denied", "message 1" )
+ .withWarning( ErrorType.RPC, "in-use", "message 2", "my-app-tag", "my-info", cause )
+ .build();
+ verifyRpcResult( result, true, null );
+ verifyRpcError( result, 0, ErrorSeverity.WARNING, ErrorType.APPLICATION, "lock_denied",
+ "message 1", null, null, null );
+ verifyRpcError( result, 1, ErrorSeverity.WARNING, ErrorType.RPC, "in-use",
+ "message 2", "my-app-tag", "my-info", cause );
+ 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 ) {
+
+ List<RpcError> errors = new ArrayList<>( result.getErrors() );
+ assertTrue( "Expected error at index " + errorIndex + " not found",
+ errorIndex < errors.size() );
+ RpcError error = errors.get( errorIndex );
+ assertEquals( "getSeverity", expSeverity, error.getSeverity() );
+ assertEquals( "getErrorType", expErrorType, error.getErrorType() );
+ assertEquals( "getTag", expTag, error.getTag() );
+ assertEquals( "getMessage", expMessage, error.getMessage() );
+ assertEquals( "getApplicationTag", expAppTag, error.getApplicationTag() );
+ assertEquals( "getInfo", expInfo, error.getInfo() );
+ assertEquals( "getCause", expCause, error.getCause() );
+ }
+
+ void verifyRpcResult( RpcResult<?> result, boolean expSuccess, Object expValue ) {
+ assertEquals( "isSuccessful", expSuccess, result.isSuccessful() );
+ assertEquals( "getResult", expValue, result.getResult() );
+ }
+}
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();
}
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.concurrent.ThreadLocalRandom;
+import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeWithValue;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
return InstanceIdentifier.create(result);
}
- public static Element serialize(final InstanceIdentifier data, final Element element) {
- Preconditions.checkNotNull(data, "Variable should contain instance of instance identifier and can't be null");
+ public static Element serialize(final InstanceIdentifier id, final Element element) {
+ Preconditions.checkNotNull(id, "Variable should contain instance of instance identifier and can't be null");
Preconditions.checkNotNull(element, "DOM element can't be null");
- Map<String, String> prefixes = new HashMap<>();
- StringBuilder textContent = new StringBuilder();
- for (PathArgument pathArgument : data.getPathArguments()) {
- textContent.append('/');
- writeIdentifierWithNamespacePrefix(element, textContent, pathArgument.getNodeType(), prefixes);
- if (pathArgument instanceof NodeIdentifierWithPredicates) {
- Map<QName, Object> predicates = ((NodeIdentifierWithPredicates) pathArgument).getKeyValues();
-
- for (QName keyValue : predicates.keySet()) {
- String predicateValue = String.valueOf(predicates.get(keyValue));
- textContent.append('[');
- writeIdentifierWithNamespacePrefix(element, textContent, keyValue, prefixes);
- textContent.append("='");
- textContent.append(predicateValue);
- textContent.append("']");
- }
- } else if (pathArgument instanceof NodeWithValue) {
- textContent.append("[.='");
- textContent.append(((NodeWithValue) pathArgument).getValue());
- textContent.append("']");
- }
+
+ final RandomPrefix prefixes = new RandomPrefix();
+ final String str = XmlUtils.encodeIdentifier(prefixes, id);
+
+ for (Entry<URI, String> e: prefixes.getPrefixes()) {
+ element.setAttribute("xmlns:" + e.getValue(), e.getKey().toString());
}
- element.setTextContent(textContent.toString());
+ element.setTextContent(str);
return element;
}
return null;
}
}
-
- private static void writeIdentifierWithNamespacePrefix(final Element element, final StringBuilder textContent, final QName qName,
- final Map<String, String> prefixes) {
- String namespace = qName.getNamespace().toString();
- String prefix = prefixes.get(namespace);
- if (prefix == null) {
- prefix = qName.getPrefix();
- if (prefix == null || prefix.isEmpty() || prefixes.containsValue(prefix)) {
- prefix = generateNewPrefix(prefixes.values());
- }
- }
-
- element.setAttribute("xmlns:" + prefix, namespace.toString());
- textContent.append(prefix);
- prefixes.put(namespace, prefix);
-
- textContent.append(':');
- textContent.append(qName.getLocalName());
- }
-
- private static String generateNewPrefix(final Collection<String> prefixes) {
- String result;
-
- final ThreadLocalRandom random = ThreadLocalRandom.current();
- do {
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < 4; i++) {
- sb.append('a' + random.nextInt(25));
- }
-
- result = sb.toString();
- } while (prefixes.contains(result));
-
- return result;
- }
}
--- /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 java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.ThreadLocalRandom;
+
+import org.opendaylight.yangtools.yang.common.QName;
+
+final class RandomPrefix {
+ final Map<URI, String> prefixes = new HashMap<>();
+
+ Iterable<Entry<URI, String>> getPrefixes() {
+ return prefixes.entrySet();
+ }
+
+ String encodeQName(final QName qname) {
+ String prefix = prefixes.get(qname.getNamespace());
+ if (prefix == null) {
+ prefix = qname.getPrefix();
+ if (prefix == null || prefix.isEmpty() || prefixes.containsValue(prefix)) {
+ final ThreadLocalRandom random = ThreadLocalRandom.current();
+ do {
+ final StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < 4; i++) {
+ sb.append((char)('a' + random.nextInt(25)));
+ }
+
+ prefix = sb.toString();
+ } while (prefixes.containsValue(prefix));
+ }
+
+ prefixes.put(qname.getNamespace(), prefix);
+ }
+
+ return prefix + ':' + qname.getLocalName();
+ }
+}
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 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;
return itemEl;
}
- 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());
+ 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, dataType.getLocalName());
+ ret = doc.createElementNS(null, qname.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());
- }
+ 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());
+ }
+ }
}
+
return ret;
}
+ public static Element createElementFor(final Document doc, final Node<?> data) {
+ return createElementFor(doc, data.getNodeType(), data);
+ }
+
+ 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,
final DataSchemaNode schema, final XmlCodecProvider codecProvider) {
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);
--- /dev/null
+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.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.AttributesContainer;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec;
+import org.opendaylight.yangtools.yang.data.impl.schema.SchemaUtils;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition;
+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;
+
+ protected XmlStreamUtils(final XmlCodecProvider codecProvider) {
+ this.codecProvider = Preconditions.checkNotNull(codecProvider);
+ }
+
+ /**
+ * 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);
+ }
+
+ /**
+ * 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;
+ }
+
+ /**
+ * 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");
+
+ final RandomPrefix prefixes = new RandomPrefix();
+ final String str = XmlUtils.encodeIdentifier(prefixes, id);
+
+ for (Entry<URI, String> e: prefixes.getPrefixes()) {
+ writer.writeNamespace(e.getValue(), e.getKey().toString());
+ }
+ writer.writeCharacters(str);
+ }
+
+ /**
+ * 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 = 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 AttributesContainer && ((AttributesContainer) data).getAttributes() != null) {
+ for (Entry<QName, String> attribute : ((AttributesContainer) data).getAttributes().entrySet()) {
+ writer.writeAttribute(attribute.getKey().getNamespace().toString(), attribute.getKey().getLocalName(), attribute.getValue());
+ }
+ }
+
+ if (data instanceof SimpleNode<?>) {
+ // Simple node
+ if (schema instanceof LeafListSchemaNode) {
+ writeValue(writer, ((LeafListSchemaNode) schema).getType(), data.getValue());
+ } else if (schema instanceof LeafSchemaNode) {
+ writeValue(writer, ((LeafSchemaNode) schema).getType(), data.getValue());
+ } else {
+ Object value = data.getValue();
+ if (value != null) {
+ writer.writeCharacters(String.valueOf(value));
+ }
+ }
+ } else {
+ // CompositeNode
+ for (Node<?> child : ((CompositeNode) data).getValue()) {
+ DataSchemaNode childSchema = null;
+ if (schema instanceof DataNodeContainer) {
+ childSchema = SchemaUtils.findFirstSchema(child.getNodeType(), ((DataNodeContainer) schema).getChildNodes()).orNull();
+ if (LOG.isDebugEnabled()) {
+ if (childSchema == null) {
+ LOG.debug("Probably the data node \"{}\" does not conform to schema", child == null ? "" : child.getNodeType().getLocalName());
+ }
+ }
+ }
+
+ writeElement(writer, child, childSchema);
+ }
+ }
+
+ writer.writeEndElement();
+ }
+
+ /**
+ * 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) {
+ 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);
+ }
+ } else {
+ LOG.error("Failed to find codec for {}, falling back to using stream", baseType);
+ text = String.valueOf(value);
+ }
+ 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 {
+ prefix = "x";
+ }
+
+ writer.writeNamespace(prefix, qname.getNamespace().toString());
+ writer.writeCharacters(prefix + ':' + qname.getLocalName());
+ } else {
+ 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));
+ }
+ }
+}
--- /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 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;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeWithValue;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+
+/**
+ * Common XML-related utility methods, which are not specific to a particular
+ * JAXP API.
+ */
+final class XmlUtils {
+
+ private XmlUtils() {
+
+ }
+
+ public static TypeDefinition<?> resolveBaseTypeFrom(final @Nonnull TypeDefinition<?> type) {
+ TypeDefinition<?> superType = type;
+ while (superType.getBaseType() != null) {
+ superType = superType.getBaseType();
+ }
+ return superType;
+ }
+
+ static String encodeIdentifier(final RandomPrefix prefixes, final InstanceIdentifier id) {
+ StringBuilder textContent = new StringBuilder();
+ for (PathArgument pathArgument : id.getPathArguments()) {
+ textContent.append('/');
+ textContent.append(prefixes.encodeQName(pathArgument.getNodeType()));
+ if (pathArgument instanceof NodeIdentifierWithPredicates) {
+ Map<QName, Object> predicates = ((NodeIdentifierWithPredicates) pathArgument).getKeyValues();
+
+ for (QName keyValue : predicates.keySet()) {
+ String predicateValue = String.valueOf(predicates.get(keyValue));
+ textContent.append('[');
+ textContent.append(prefixes.encodeQName(keyValue));
+ textContent.append("='");
+ textContent.append(predicateValue);
+ textContent.append("']");
+ }
+ } else if (pathArgument instanceof NodeWithValue) {
+ textContent.append("[.='");
+ textContent.append(((NodeWithValue) pathArgument).getValue());
+ textContent.append("']");
+ }
+ }
+
+ return textContent.toString();
+ }
+}
import com.google.common.collect.Collections2;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
-import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils;
-import org.opendaylight.yangtools.yang.model.api.*;
-import java.util.*;
+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.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
public final class SchemaUtils {
private SchemaUtils() {
}
- public static DataSchemaNode findSchemaForChild(DataNodeContainer schema, QName qname) {
+ public static final Optional<DataSchemaNode> findFirstSchema(final QName qname, final Set<DataSchemaNode> dataSchemaNode) {
+ if (dataSchemaNode != null && !dataSchemaNode.isEmpty() && qname != null) {
+ for (DataSchemaNode dsn : dataSchemaNode) {
+ if (qname.isEqualWithoutRevision(dsn.getQName())) {
+ return Optional.<DataSchemaNode> of(dsn);
+ } else if (dsn instanceof ChoiceNode) {
+ for (ChoiceCaseNode choiceCase : ((ChoiceNode) dsn).getCases()) {
+ Optional<DataSchemaNode> foundDsn = findFirstSchema(qname, choiceCase.getChildNodes());
+ if (foundDsn != null && foundDsn.isPresent()) {
+ return foundDsn;
+ }
+ }
+ }
+ }
+ }
+ return Optional.absent();
+ }
+
+ public static DataSchemaNode findSchemaForChild(final DataNodeContainer schema, final QName qname) {
Set<DataSchemaNode> childNodes = schema.getChildNodes();
return findSchemaForChild(schema, qname, childNodes);
}
- public static DataSchemaNode findSchemaForChild(DataNodeContainer schema, QName qname, Set<DataSchemaNode> childNodes) {
- Optional<DataSchemaNode> childSchema = XmlDocumentUtils.findFirstSchema(qname, childNodes);
+ public static DataSchemaNode findSchemaForChild(final DataNodeContainer schema, final QName qname, final Set<DataSchemaNode> childNodes) {
+ Optional<DataSchemaNode> childSchema = findFirstSchema(qname, childNodes);
Preconditions.checkState(childSchema.isPresent(),
"Unknown child(ren) node(s) detected, identified by: %s, in: %s", qname, schema);
return childSchema.get();
}
- public static AugmentationSchema findSchemaForAugment(AugmentationTarget schema, Set<QName> qNames) {
+ public static AugmentationSchema findSchemaForAugment(final AugmentationTarget schema, final Set<QName> qNames) {
Optional<AugmentationSchema> schemaForAugment = findAugment(schema, qNames);
Preconditions.checkState(schemaForAugment.isPresent(), "Unknown augmentation node detected, identified by: %s, in: %s",
qNames, schema);
return schemaForAugment.get();
}
- public static AugmentationSchema findSchemaForAugment(ChoiceNode schema, Set<QName> qNames) {
+ public static AugmentationSchema findSchemaForAugment(final ChoiceNode schema, final Set<QName> qNames) {
Optional<AugmentationSchema> schemaForAugment = Optional.absent();
for (ChoiceCaseNode choiceCaseNode : schema.getCases()) {
return schemaForAugment.get();
}
- private static Optional<AugmentationSchema> findAugment(AugmentationTarget schema, Set<QName> qNames) {
+ private static Optional<AugmentationSchema> findAugment(final AugmentationTarget schema, final Set<QName> qNames) {
for (AugmentationSchema augment : schema.getAvailableAugmentations()) {
HashSet<QName> qNamesFromAugment = Sets.newHashSet(Collections2.transform(augment.getChildNodes(), new Function<DataSchemaNode, QName>() {
@Override
- public QName apply(DataSchemaNode input) {
+ public QName apply(final DataSchemaNode input) {
return input.getQName();
}
}));
return Optional.absent();
}
- public static DataSchemaNode findSchemaForChild(ChoiceNode schema, QName childPartialQName) {
+ public static DataSchemaNode findSchemaForChild(final ChoiceNode schema, final QName childPartialQName) {
for (ChoiceCaseNode choiceCaseNode : schema.getCases()) {
- Optional<DataSchemaNode> childSchema = XmlDocumentUtils.findFirstSchema(childPartialQName,
- choiceCaseNode.getChildNodes());
+ Optional<DataSchemaNode> childSchema = findFirstSchema(childPartialQName, choiceCaseNode.getChildNodes());
if (childSchema.isPresent()) {
return childSchema.get();
}
*
* @return Map with all child nodes, to their most top augmentation
*/
- public static Map<QName, ChoiceNode> mapChildElementsFromChoices(DataNodeContainer schema) {
+ public static Map<QName, ChoiceNode> mapChildElementsFromChoices(final DataNodeContainer schema) {
Set<DataSchemaNode> childNodes = schema.getChildNodes();
return mapChildElementsFromChoices(schema, childNodes);
}
- private static Map<QName, ChoiceNode> mapChildElementsFromChoices(DataNodeContainer schema, Set<DataSchemaNode> childNodes) {
+ private static Map<QName, ChoiceNode> mapChildElementsFromChoices(final DataNodeContainer schema, final Set<DataSchemaNode> childNodes) {
Map<QName, ChoiceNode> mappedChoices = Maps.newLinkedHashMap();
for (final DataSchemaNode childSchema : childNodes) {
return mappedChoices;
}
- private static boolean isFromAugment(DataNodeContainer schema, DataSchemaNode childSchema) {
+ private static boolean isFromAugment(final DataNodeContainer schema, final DataSchemaNode childSchema) {
if(schema instanceof AugmentationTarget == false) {
return false;
}
*
* @return Map with all child nodes, to their most top augmentation
*/
- public static Map<QName, AugmentationSchema> mapChildElementsFromAugments(AugmentationTarget schema) {
+ public static Map<QName, AugmentationSchema> mapChildElementsFromAugments(final AugmentationTarget schema) {
Map<QName, AugmentationSchema> childNodesToAugmentation = Maps.newLinkedHashMap();
for (DataSchemaNode child : ((DataNodeContainer) schema).getChildNodes()) {
// If is not augmented child, continue
- if (augments.containsKey(child.getQName()) == false)
+ if (augments.containsKey(child.getQName()) == false) {
continue;
+ }
AugmentationSchema mostTopAugmentation = augments.get(child.getQName());
*
* In case of choice, augment and cases, step in.
*/
- public static Set<QName> getChildNodesRecursive(DataNodeContainer nodeContainer) {
+ public static Set<QName> getChildNodesRecursive(final DataNodeContainer nodeContainer) {
Set<QName> allChildNodes = Sets.newHashSet();
for (DataSchemaNode childSchema : nodeContainer.getChildNodes()) {
* Schema of child node from augment is incomplete, therefore its useless for xml <-> normalizedNode translation.
*
*/
- public static Set<DataSchemaNode> getRealSchemasForAugment(AugmentationTarget targetSchema, AugmentationSchema augmentSchema) {
+ public static Set<DataSchemaNode> getRealSchemasForAugment(final AugmentationTarget targetSchema, final AugmentationSchema augmentSchema) {
if(targetSchema.getAvailableAugmentations().contains(augmentSchema) == false) {
return Collections.emptySet();
}
Set<DataSchemaNode> realChildNodes = Sets.newHashSet();
if(targetSchema instanceof DataNodeContainer) {
- realChildNodes = getRealSchemasForAugment((DataNodeContainer)targetSchema, augmentSchema);
+ realChildNodes = getRealSchemasForAugment((DataNodeContainer)targetSchema, augmentSchema);
} else if(targetSchema instanceof ChoiceNode) {
for (DataSchemaNode dataSchemaNode : augmentSchema.getChildNodes()) {
for (ChoiceCaseNode choiceCaseNode : ((ChoiceNode) targetSchema).getCases()) {
return realChildNodes;
}
- public static Set<DataSchemaNode> getRealSchemasForAugment(DataNodeContainer targetSchema,
- AugmentationSchema augmentSchema) {
+ public static Set<DataSchemaNode> getRealSchemasForAugment(final DataNodeContainer targetSchema,
+ final AugmentationSchema augmentSchema) {
Set<DataSchemaNode> realChildNodes = Sets.newHashSet();
for (DataSchemaNode dataSchemaNode : augmentSchema.getChildNodes()) {
DataSchemaNode realChild = targetSchema.getDataChildByName(dataSchemaNode.getQName());
return realChildNodes;
}
- public static Optional<ChoiceCaseNode> detectCase(ChoiceNode schema, DataContainerChild<?, ?> child) {
+ public static Optional<ChoiceCaseNode> detectCase(final ChoiceNode schema, final DataContainerChild<?, ?> child) {
for (ChoiceCaseNode choiceCaseNode : schema.getCases()) {
if (child instanceof AugmentationNode
&& belongsToCaseAugment(choiceCaseNode,
return Optional.absent();
}
- public static boolean belongsToCaseAugment(ChoiceCaseNode caseNode, InstanceIdentifier.AugmentationIdentifier childToProcess) {
+ public static boolean belongsToCaseAugment(final ChoiceCaseNode caseNode, final InstanceIdentifier.AugmentationIdentifier childToProcess) {
for (AugmentationSchema augmentationSchema : caseNode.getAvailableAugmentations()) {
Set<QName> currentAugmentChildNodes = Sets.newHashSet();
return false;
}
- public static InstanceIdentifier.AugmentationIdentifier getNodeIdentifierForAugmentation(AugmentationSchema schema) {
+ public static InstanceIdentifier.AugmentationIdentifier getNodeIdentifierForAugmentation(final AugmentationSchema schema) {
return new InstanceIdentifier.AugmentationIdentifier(getChildQNames(schema));
}
- public static Set<QName> getChildQNames(AugmentationSchema schema) {
+ public static Set<QName> getChildQNames(final AugmentationSchema schema) {
Set<QName> qnames = Sets.newHashSet();
for (DataSchemaNode dataSchemaNode : schema.getChildNodes()) {
*/
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();
*/
package org.opendaylight.yangtools.yang.data.impl.schema.tree;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree;
import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException;
import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.tree.RootModificationApplyOperation.LatestOperationHolder;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.concurrent.locks.ReadWriteLock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
/**
* Read-only snapshot of the data tree.
private static final InstanceIdentifier PUBLIC_ROOT_PATH = InstanceIdentifier.builder().build();
private final ReadWriteLock rwLock = new ReentrantReadWriteLock(true);
- private ModificationApplyOperation applyOper = new AlwaysFailOperation();
+ private final LatestOperationHolder operationHolder = new LatestOperationHolder();
private SchemaContext currentSchemaContext;
private TreeNode rootNode;
// Ready to change the context now, make sure no operations are running
rwLock.writeLock().lock();
try {
- this.applyOper = newApplyOper;
+ this.operationHolder.setCurrent(newApplyOper);
this.currentSchemaContext = newSchemaContext;
} finally {
rwLock.writeLock().unlock();
public InMemoryDataTreeSnapshot takeSnapshot() {
rwLock.readLock().lock();
try {
- return new InMemoryDataTreeSnapshot(currentSchemaContext, rootNode, applyOper);
+ return new InMemoryDataTreeSnapshot(currentSchemaContext, rootNode, operationHolder.newSnapshot());
} finally {
rwLock.readLock().unlock();
}
*/
package org.opendaylight.yangtools.yang.data.impl.schema.tree;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-
import java.util.Map.Entry;
import javax.annotation.concurrent.GuardedBy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
final class InMemoryDataTreeModification implements DataTreeModification {
private static final Logger LOG = LoggerFactory.getLogger(InMemoryDataTreeModification.class);
- private final ModificationApplyOperation strategyTree;
+ private final RootModificationApplyOperation strategyTree;
private final InMemoryDataTreeSnapshot snapshot;
private final ModifiedNode rootNode;
@GuardedBy("this")
private boolean sealed = false;
- InMemoryDataTreeModification(final InMemoryDataTreeSnapshot snapshot, final ModificationApplyOperation resolver) {
+ InMemoryDataTreeModification(final InMemoryDataTreeSnapshot snapshot, final RootModificationApplyOperation resolver) {
this.snapshot = Preconditions.checkNotNull(snapshot);
- this.strategyTree = Preconditions.checkNotNull(resolver);
+ this.strategyTree = Preconditions.checkNotNull(resolver).snapshot();
this.rootNode = ModifiedNode.createUnmodified(snapshot.getRootNode());
}
private ModificationApplyOperation resolveModificationStrategy(final InstanceIdentifier path) {
LOG.trace("Resolving modification apply strategy for {}", path);
- return TreeNodeUtils.findNodeChecked(strategyTree, path);
+ if(rootNode.getType() == ModificationType.UNMODIFIED) {
+ strategyTree.upgradeIfPossible();
+ }
+
+ return TreeNodeUtils.<ModificationApplyOperation>findNodeChecked(strategyTree, path);
}
private OperationWithModification resolveModificationFor(final InstanceIdentifier path) {
package org.opendaylight.yangtools.yang.data.impl.schema.tree;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot;
import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeUtils;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
final class InMemoryDataTreeSnapshot implements DataTreeSnapshot {
- private final ModificationApplyOperation applyOper;
+ private final RootModificationApplyOperation applyOper;
private final SchemaContext schemaContext;
private final TreeNode rootNode;
InMemoryDataTreeSnapshot(final SchemaContext schemaContext, final TreeNode rootNode,
- final ModificationApplyOperation applyOper) {
+ final RootModificationApplyOperation applyOper) {
this.schemaContext = Preconditions.checkNotNull(schemaContext);
this.rootNode = Preconditions.checkNotNull(rootNode);
this.applyOper = Preconditions.checkNotNull(applyOper);
--- /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.schema.tree;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.Version;
+
+import com.google.common.base.Optional;
+
+public abstract class RootModificationApplyOperation implements ModificationApplyOperation {
+
+ @Override
+ public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
+ return getDelegate().getChild(child);
+ }
+
+ @Override
+ public final void checkApplicable(final InstanceIdentifier path, final NodeModification modification, final Optional<TreeNode> current)
+ throws DataValidationFailedException {
+ getDelegate().checkApplicable(path, modification, current);
+ }
+
+ @Override
+ public final Optional<TreeNode> apply(final ModifiedNode modification, final Optional<TreeNode> currentMeta, final Version version) {
+ return getDelegate().apply(modification, currentMeta, version);
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ return getDelegate().equals(obj);
+ }
+
+ @Override
+ public int hashCode() {
+ return getDelegate().hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return getDelegate().toString();
+ }
+
+ @Override
+ public void verifyStructure(final ModifiedNode modification) throws IllegalArgumentException {
+ getDelegate().verifyStructure(modification);
+ }
+
+ abstract ModificationApplyOperation getDelegate();
+
+ public abstract RootModificationApplyOperation snapshot();
+
+ public abstract void upgradeIfPossible();
+
+
+
+ public static RootModificationApplyOperation from(final ModificationApplyOperation resolver) {
+ if(resolver instanceof RootModificationApplyOperation) {
+ return ((RootModificationApplyOperation) resolver).snapshot();
+ }
+ return new NotUpgradable(resolver);
+ }
+
+ private static final class Upgradable extends RootModificationApplyOperation {
+
+ private final LatestOperationHolder holder;
+ private ModificationApplyOperation delegate;
+
+
+ public Upgradable(final LatestOperationHolder holder, final ModificationApplyOperation delegate) {
+ this.holder = holder;
+ this.delegate = delegate;
+
+ }
+
+ @Override
+ public void upgradeIfPossible() {
+ ModificationApplyOperation holderCurrent = holder.getCurrent();
+ if(holderCurrent != delegate) {
+ // FIXME: Allow update only if there is addition of models, not removals.
+ delegate = holderCurrent;
+ }
+
+ }
+
+ @Override
+ ModificationApplyOperation getDelegate() {
+ return delegate;
+ }
+
+ @Override
+ public RootModificationApplyOperation snapshot() {
+ return new Upgradable(holder,getDelegate());
+ }
+
+ }
+
+ private static final class NotUpgradable extends RootModificationApplyOperation {
+
+ private final ModificationApplyOperation delegate;
+
+ public NotUpgradable(final ModificationApplyOperation delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public ModificationApplyOperation getDelegate() {
+ return delegate;
+ }
+
+ @Override
+ public void upgradeIfPossible() {
+ // Intentional noop
+ }
+
+ @Override
+ public RootModificationApplyOperation snapshot() {
+ return this;
+ }
+ }
+
+ public static class LatestOperationHolder {
+
+ private ModificationApplyOperation current = new AlwaysFailOperation();
+
+ public ModificationApplyOperation getCurrent() {
+ return current;
+ }
+
+ public void setCurrent(final ModificationApplyOperation newApplyOper) {
+ current = newApplyOper;
+ }
+
+ public RootModificationApplyOperation newSnapshot() {
+ return new Upgradable(this,current);
+ }
+
+ }
+}
import java.util.Date;
import java.util.List;
import java.util.Map;
-import java.util.Stack;
+import java.util.Deque;
+import java.util.LinkedList;
import org.junit.Assert;
import org.junit.Before;
}
private static void checkFamilyBinding(final CompositeNode treeRoot) throws Exception {
- Stack<CompositeNode> jobQueue = new Stack<>();
+ Deque<CompositeNode> jobQueue = new LinkedList<>();
jobQueue.push(treeRoot);
while (!jobQueue.isEmpty()) {
--- /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"));
+ }
+
+}
*/
package org.opendaylight.yangtools.yang.data.impl.schema.tree;
-import com.google.common.base.Optional;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntry;
+import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntryBuilder;
+import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapNodeBuilder;
+
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntry;
-import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntryBuilder;
-import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapNodeBuilder;
+import com.google.common.base.Optional;
.build();
private SchemaContext schemaContext;
- private ModificationApplyOperation applyOper;
+ private RootModificationApplyOperation rootOper;
@Before
public void prepare() {
schemaContext = TestModel.createTestContext();
assertNotNull("Schema context must not be null.", schemaContext);
- applyOper = SchemaAwareApplyOperation.from(schemaContext);
+ rootOper = RootModificationApplyOperation.from(SchemaAwareApplyOperation.from(schemaContext));
}
/**
@Test
public void basicReadWrites() {
DataTreeModification modificationTree = new InMemoryDataTreeModification(new InMemoryDataTreeSnapshot(schemaContext,
- TreeNodeFactory.createTreeNode(createDocumentOne(), Version.initial()), applyOper),
- new SchemaAwareApplyOperationRoot(schemaContext));
+ TreeNodeFactory.createTreeNode(createDocumentOne(), Version.initial()), rootOper),
+ rootOper);
Optional<NormalizedNode<?, ?>> originalBarNode = modificationTree.readNode(OUTER_LIST_2_PATH);
assertTrue(originalBarNode.isPresent());
assertSame(BAR_NODE, originalBarNode.get());
*/
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);
--- /dev/null
+package org.opendaylight.yangtools.yang.model.api;
+
+import com.google.common.base.Optional;
+
+/**
+ * Schema Node which may be derived from other schema node
+ * using augmentation or uses statement.
+ *
+ */
+public interface DerivableSchemaNode extends DataSchemaNode {
+
+ /**
+ * If this node is added by uses, returns original node definition from
+ * grouping where it was defined.
+ *
+ * @return original node definition from grouping if this node is added by
+ * uses, null otherwise
+ */
+ Optional<? extends SchemaNode> getOriginal();
+
+}
*/
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);
}
/**
*/
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";
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.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;
return findNodeInModule(module, path);
}
- public static GroupingDefinition findGrouping(final SchemaContext context, final Module module, final List<QName> path) {
- QName first = path.get(0);
+ 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) {
}
private static DataSchemaNode getResultFromUses(final UsesNode u, final String currentName, final SchemaContext ctx) {
- SchemaNode targetGrouping = findNodeInSchemaContext(ctx, u.getGroupingPath().getPathFromRoot());
-
+ 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;
--- /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.model.util;
+
+import org.opendaylight.yangtools.yang.model.api.DerivableSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+
+import com.google.common.base.Optional;
+
+public class SchemaNodeUtils {
+
+ private SchemaNodeUtils() {
+ throw new UnsupportedOperationException("Utility class");
+ }
+
+ public static final Optional<SchemaNode> getOriginalIfPossible(final SchemaNode node) {
+ if(node instanceof DerivableSchemaNode) {
+ @SuppressWarnings("unchecked")
+ final Optional<SchemaNode> ret = (Optional<SchemaNode>) (((DerivableSchemaNode) node).getOriginal());
+ return ret;
+ }
+ return Optional.absent();
+ }
+
+ public static final SchemaNode getRootOriginalIfPossible(final SchemaNode data) {
+ Optional<SchemaNode> previous = Optional.absent();
+ Optional<SchemaNode> next = getOriginalIfPossible(data);
+ while(next.isPresent()) {
+ previous = next;
+ next = getOriginalIfPossible(next.get());
+ }
+ return previous.orNull();
+ }
+}
*/
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>
*/
public interface DataSchemaNodeBuilder extends SchemaNodeBuilder, GroupingMember {
+ /**
+ * Get original builder definition from grouping, where it is defined.
+ *
+ * @return original builder definition from grouping if this node is added
+ * by uses, null otherwise
+ */
+ SchemaNodeBuilder getOriginal();
+ /**
+ * Set original builder definition from grouping
+ *
+ * @param original
+ * original builder definition from grouping
+ */
+ void setOriginal(SchemaNodeBuilder original);
/**
*
*/
package org.opendaylight.yangtools.yang.parser.builder.impl;
-import com.google.common.collect.ImmutableList;
import java.util.List;
+
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ConstraintDefinition;
+import org.opendaylight.yangtools.yang.model.api.DerivableSchemaNode;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
import org.opendaylight.yangtools.yang.model.api.Status;
import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
import org.opendaylight.yangtools.yang.parser.builder.api.ConstraintsBuilder;
import org.opendaylight.yangtools.yang.parser.builder.api.DataSchemaNodeBuilder;
+import org.opendaylight.yangtools.yang.parser.builder.api.SchemaNodeBuilder;
import org.opendaylight.yangtools.yang.parser.builder.api.UnknownSchemaNodeBuilder;
import org.opendaylight.yangtools.yang.parser.builder.util.AbstractSchemaNodeBuilder;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+
public final class AnyXmlBuilder extends AbstractSchemaNodeBuilder implements DataSchemaNodeBuilder {
private AnyXmlSchemaNodeImpl instance;
private boolean augmenting;
private boolean addedByUses;
private boolean configuration;
-
+ private AnyXmlSchemaNode originalNode;
+ private AnyXmlBuilder originalBuilder;
private final ConstraintsBuilder constraints;
public AnyXmlBuilder(final String moduleName, final int line, final QName qname, final SchemaPath path) {
status = base.getStatus();
augmenting = base.isAugmenting();
addedByUses = base.isAddedByUses();
+ originalNode = base;
configuration = base.isConfiguration();
unknownNodes.addAll(base.getUnknownSchemaNodes());
}
instance.augmenting = augmenting;
instance.addedByUses = addedByUses;
instance.configuration = configuration;
-
instance.constraintsDef = constraints.toInstance();
+ // ORIGINAL NODE
+ if (originalNode == null && originalBuilder != null) {
+ originalNode = originalBuilder.build();
+ }
+ instance.original = originalNode;
+
// UNKNOWN NODES
for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
unknownNodes.add(b.build());
this.addedByUses = addedByUses;
}
+ @Override
+ public AnyXmlBuilder getOriginal() {
+ return originalBuilder;
+ }
+
+ @Override
+ public void setOriginal(final SchemaNodeBuilder builder) {
+ Preconditions.checkArgument(builder instanceof AnyXmlBuilder, "Original of anyxml cannot be " + builder);
+ this.originalBuilder = (AnyXmlBuilder) builder;
+ }
+
@Override
public boolean isConfiguration() {
return configuration;
}
@Override
- public boolean equals(Object obj) {
+ public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
return "anyxml " + qname.getLocalName();
}
- private static final class AnyXmlSchemaNodeImpl implements AnyXmlSchemaNode {
+ private static final class AnyXmlSchemaNodeImpl implements AnyXmlSchemaNode, DerivableSchemaNode {
private final QName qname;
private final SchemaPath path;
private String description;
private String reference;
private Status status;
private boolean configuration;
+ private AnyXmlSchemaNode original;
private ConstraintDefinition constraintsDef;
private boolean augmenting;
private boolean addedByUses;
return addedByUses;
}
+ @Override
+ public Optional<AnyXmlSchemaNode> getOriginal() {
+ return Optional.fromNullable(original);
+ }
+
@Override
public boolean isConfiguration() {
return configuration;
}
@Override
- public boolean equals(Object obj) {
+ public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
sb.append("]");
return sb.toString();
}
+
}
}
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 {
*/
package org.opendaylight.yangtools.yang.parser.builder.impl;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
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.SchemaPath;
import org.opendaylight.yangtools.yang.model.api.Status;
import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
import org.opendaylight.yangtools.yang.parser.builder.api.AugmentationTargetBuilder;
import org.opendaylight.yangtools.yang.parser.builder.api.ConstraintsBuilder;
import org.opendaylight.yangtools.yang.parser.builder.api.DataSchemaNodeBuilder;
+import org.opendaylight.yangtools.yang.parser.builder.api.SchemaNodeBuilder;
import org.opendaylight.yangtools.yang.parser.builder.api.UnknownSchemaNodeBuilder;
import org.opendaylight.yangtools.yang.parser.builder.util.AbstractSchemaNodeBuilder;
import org.opendaylight.yangtools.yang.parser.builder.util.Comparators;
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 ChoiceBuilder extends AbstractSchemaNodeBuilder implements DataSchemaNodeBuilder,
AugmentationTargetBuilder {
private ChoiceNodeImpl instance;
private boolean augmenting;
private boolean addedByUses;
private boolean configuration;
+ private ChoiceNode originalNode;
+ private ChoiceBuilder originalBuilder;
private final ConstraintsBuilder constraints;
// AugmentationTarget args
private final Set<AugmentationSchema> augmentations = new HashSet<>();
status = base.getStatus();
augmenting = base.isAugmenting();
addedByUses = base.isAddedByUses();
+ originalNode = base;
configuration = base.isConfiguration();
augmentations.addAll(base.getAvailableAugmentations());
instance.constraints = constraints.toInstance();
instance.defaultCase = defaultCase;
+ // ORIGINAL NODE
+ if (originalNode == null && originalBuilder != null) {
+ originalNode = originalBuilder.build();
+ }
+ instance.original = originalNode;
+
// CASES
final Set<ChoiceCaseNode> cases = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
for (ChoiceCaseBuilder caseBuilder : caseBuilders) {
this.addedByUses = addedByUses;
}
+ @Override
+ public ChoiceBuilder getOriginal() {
+ return originalBuilder;
+ }
+
+ @Override
+ public void setOriginal(final SchemaNodeBuilder builder) {
+ Preconditions.checkArgument(builder instanceof ChoiceBuilder, "Original of choice cannot be " + builder);
+ this.originalBuilder = (ChoiceBuilder) builder;
+ }
+
@Override
public boolean isConfiguration() {
return configuration;
return "choice " + qname.getLocalName();
}
- private static final class ChoiceNodeImpl implements ChoiceNode {
+ private static final class ChoiceNodeImpl implements ChoiceNode, DerivableSchemaNode {
private final QName qname;
private final SchemaPath path;
private String description;
private Status status;
private boolean augmenting;
private boolean addedByUses;
+ private ChoiceNode original;
private boolean configuration;
private ConstraintDefinition constraints;
private ImmutableSet<ChoiceCaseNode> cases;
return addedByUses;
}
+ @Override
+ public Optional<ChoiceNode> getOriginal() {
+ return Optional.fromNullable(original);
+ }
+
@Override
public boolean isConfiguration() {
return configuration;
sb.append("]");
return sb.toString();
}
+
}
}
*/
package org.opendaylight.yangtools.yang.parser.builder.impl;
-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.model.api.AugmentationSchema;
import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
import org.opendaylight.yangtools.yang.model.api.ConstraintDefinition;
+import org.opendaylight.yangtools.yang.model.api.DerivableSchemaNode;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
-import org.opendaylight.yangtools.yang.model.api.Status;
import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
import org.opendaylight.yangtools.yang.parser.builder.api.AugmentationSchemaBuilder;
import org.opendaylight.yangtools.yang.parser.builder.api.AugmentationTargetBuilder;
import org.opendaylight.yangtools.yang.parser.builder.api.ConstraintsBuilder;
import org.opendaylight.yangtools.yang.parser.builder.api.DataSchemaNodeBuilder;
+import org.opendaylight.yangtools.yang.parser.builder.api.SchemaNodeBuilder;
import org.opendaylight.yangtools.yang.parser.builder.api.TypeDefinitionBuilder;
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 ChoiceCaseBuilder extends AbstractDocumentedDataNodeContainerBuilder implements DataSchemaNodeBuilder,
AugmentationTargetBuilder {
private ChoiceCaseNodeImpl instance;
// SchemaNode args
private SchemaPath schemaPath;
- private String description;
- private String reference;
- private Status status = Status.CURRENT;
// DataSchemaNode args
private boolean augmenting;
+ private ChoiceCaseNode originalNode;
+ private ChoiceCaseBuilder originalBuilder;
private boolean addedByUses;
private final ConstraintsBuilder constraints;
// AugmentationTarget args
public ChoiceCaseBuilder(final String moduleName, final int line, final QName qname, final SchemaPath path,
final ChoiceCaseNode base) {
-
- super(moduleName, line, qname);
- this.schemaPath = Preconditions.checkNotNull(path, "Schema Path must not be null");
+ super(moduleName, line, qname, Preconditions.checkNotNull(path, "Schema Path must not be null"), base);
+ this.schemaPath = path;
constraints = new ConstraintsBuilderImpl(moduleName, line, base.getConstraints());
- description = base.getDescription();
- reference = base.getReference();
- status = base.getStatus();
augmenting = base.isAugmenting();
addedByUses = base.isAddedByUses();
-
+ originalNode = base;
addedUnknownNodes.addAll(BuilderUtils.wrapUnknownNodes(moduleName, line, base.getUnknownSchemaNodes(), path,
qname));
augmentations.addAll(base.getAvailableAugmentations());
instance.constraints = constraints.toInstance();
+ // ORIGINAL NODE
+ if (originalNode == null && originalBuilder != null) {
+ originalNode = originalBuilder.build();
+ }
+ instance.original = originalNode;
+
// UNKNOWN NODES
for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
unknownNodes.add(b.build());
this.addedByUses = addedByUses;
}
+ @Override
+ public ChoiceCaseBuilder getOriginal() {
+ return originalBuilder;
+ }
+
+ @Override
+ public void setOriginal(final SchemaNodeBuilder builder) {
+ Preconditions.checkArgument(builder instanceof ChoiceCaseBuilder, "Original of case cannot be " + builder);
+ this.originalBuilder = (ChoiceCaseBuilder) builder;
+ }
+
@Override
public void addTypedef(final TypeDefinitionBuilder typedefBuilder) {
throw new YangParseException(getModuleName(), typedefBuilder.getLine(), "Can not add type definition to choice case.");
return "choice";
}
- private static final class ChoiceCaseNodeImpl extends AbstractDocumentedDataNodeContainer implements ChoiceCaseNode {
+ private static final class ChoiceCaseNodeImpl extends AbstractDocumentedDataNodeContainer implements ChoiceCaseNode, DerivableSchemaNode {
private final QName qname;
private final SchemaPath path;
private boolean augmenting;
private boolean addedByUses;
+ private ChoiceCaseNode original;
private ConstraintDefinition constraints;
private ImmutableSet<AugmentationSchema> augmentations;
private ImmutableList<UnknownSchemaNode> unknownNodes;
return addedByUses;
}
+ @Override
+ public Optional<ChoiceCaseNode> getOriginal() {
+ return Optional.fromNullable(original);
+ }
+
@Override
public List<UnknownSchemaNode> getUnknownSchemaNodes() {
return unknownNodes;
sb.append("]");
return sb.toString();
}
+
}
}
*/
package org.opendaylight.yangtools.yang.parser.builder.impl;
-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.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DerivableSchemaNode;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
import org.opendaylight.yangtools.yang.parser.builder.api.AugmentationSchemaBuilder;
import org.opendaylight.yangtools.yang.parser.builder.api.AugmentationTargetBuilder;
import org.opendaylight.yangtools.yang.parser.builder.api.ConstraintsBuilder;
import org.opendaylight.yangtools.yang.parser.builder.api.DataSchemaNodeBuilder;
+import org.opendaylight.yangtools.yang.parser.builder.api.SchemaNodeBuilder;
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 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 ContainerSchemaNodeBuilder extends AbstractDocumentedDataNodeContainerBuilder implements
AugmentationTargetBuilder, DataSchemaNodeBuilder {
private ContainerSchemaNodeImpl instance;
private boolean augmenting;
private boolean addedByUses;
private boolean configuration;
+ private ContainerSchemaNode originalNode;
+ private ContainerSchemaNodeBuilder originalBuilder;
private final ConstraintsBuilder constraints;
// AugmentationTarget args
private final List<AugmentationSchema> augmentations = new ArrayList<>();
augmenting = base.isAugmenting();
addedByUses = base.isAddedByUses();
+ originalNode = base;
configuration = base.isConfiguration();
presence = base.isPresenceContainer();
instance.constraints = constraints.toInstance();
instance.presence = presence;
+ // ORIGINAL NODE
+ if (originalNode == null && originalBuilder != null) {
+ originalNode = originalBuilder.build();
+ }
+ instance.original = originalNode;
+
// AUGMENTATIONS
for (AugmentationSchemaBuilder builder : augmentationBuilders) {
augmentations.add(builder.build());
this.addedByUses = addedByUses;
}
+ @Override
+ public ContainerSchemaNodeBuilder getOriginal() {
+ return originalBuilder;
+ }
+
+ @Override
+ public void setOriginal(final SchemaNodeBuilder builder) {
+ Preconditions.checkArgument(builder instanceof ContainerSchemaNodeBuilder, "Original of container cannot be "
+ + builder);
+ this.originalBuilder = (ContainerSchemaNodeBuilder) builder;
+ }
+
@Override
public boolean isConfiguration() {
return configuration;
} else if (!path.equals(other.path)) {
return false;
}
- // FIXME: Do we really need this? This actually triggers equals
- // up to the root builder.
if (getParent() == null) {
if (other.getParent() != null) {
return false;
}
private static final class ContainerSchemaNodeImpl extends AbstractDocumentedDataNodeContainer implements
- ContainerSchemaNode {
+ ContainerSchemaNode, DerivableSchemaNode {
private final QName qname;
private final SchemaPath path;
private boolean augmenting;
private boolean addedByUses;
private boolean configuration;
+ private ContainerSchemaNode original;
private ConstraintDefinition constraints;
private ImmutableSet<AugmentationSchema> augmentations;
return addedByUses;
}
+ @Override
+ public Optional<ContainerSchemaNode> getOriginal() {
+ return Optional.fromNullable(original);
+ }
+
@Override
public boolean isConfiguration() {
return configuration;
public String toString() {
return "container " + qname.getLocalName();
}
+
}
}
* parent location
* @return copy of given builder
*/
- public static DataSchemaNodeBuilder copy(final DataSchemaNodeBuilder old, final Builder newParent, final boolean updateQName) {
+ public static DataSchemaNodeBuilder copy(final DataSchemaNodeBuilder old, final Builder newParent,
+ final boolean updateQName) {
if (old instanceof AnyXmlBuilder) {
return copy((AnyXmlBuilder) old, newParent, updateQName);
} else if (old instanceof ChoiceBuilder) {
SchemaPath newSchemaPath = data.schemaPath;
AnyXmlBuilder copy = new AnyXmlBuilder(newParent.getModuleName(), newParent.getLine(), newQName, newSchemaPath);
+ copy.setOriginal(old.getOriginal() == null ? old : old.getOriginal());
copyConstraints(copy.getConstraints(), old.getConstraints());
copy.setParent(newParent);
copy.setDescription(old.getDescription());
SchemaPath newSchemaPath = data.schemaPath;
ChoiceBuilder copy = new ChoiceBuilder(newParent.getModuleName(), newParent.getLine(), newQName, newSchemaPath);
+ copy.setOriginal(old.getOriginal() == null ? old : old.getOriginal());
copyConstraints(copy.getConstraints(), old.getConstraints());
copy.setParent(newParent);
copy.setDescription(old.getDescription());
return copy;
}
- private static ChoiceCaseBuilder copy(final ChoiceCaseBuilder old, final Builder newParent, final boolean updateQName) {
+ private static ChoiceCaseBuilder copy(final ChoiceCaseBuilder old, final Builder newParent,
+ final boolean updateQName) {
DataBean data = getdata(old, newParent, updateQName);
QName newQName = data.qname;
SchemaPath newSchemaPath = data.schemaPath;
- ChoiceCaseBuilder copy = new ChoiceCaseBuilder(newParent.getModuleName(), newParent.getLine(), newQName, newSchemaPath);
+ ChoiceCaseBuilder copy = new ChoiceCaseBuilder(newParent.getModuleName(), newParent.getLine(), newQName,
+ newSchemaPath);
+ copy.setOriginal(old.getOriginal() == null ? old : old.getOriginal());
copyConstraints(copy.getConstraints(), old.getConstraints());
copy.setParent(newParent);
copy.setDescription(old.getDescription());
ContainerSchemaNodeBuilder copy = new ContainerSchemaNodeBuilder(newParent.getModuleName(),
newParent.getLine(), newQName, newSchemaPath);
+ copy.setOriginal(old.getOriginal() == null ? old : old.getOriginal());
copyConstraints(copy.getConstraints(), old.getConstraints());
copy.setParent(newParent);
copy.setDescription(old.getDescription());
return copy;
}
- private static LeafSchemaNodeBuilder copy(final LeafSchemaNodeBuilder old, final Builder newParent, final boolean updateQName) {
+ private static LeafSchemaNodeBuilder copy(final LeafSchemaNodeBuilder old, final Builder newParent,
+ final boolean updateQName) {
DataBean data = getdata(old, newParent, updateQName);
QName newQName = data.qname;
SchemaPath newSchemaPath = data.schemaPath;
LeafSchemaNodeBuilder copy = new LeafSchemaNodeBuilder(newParent.getModuleName(), newParent.getLine(),
newQName, newSchemaPath);
+ copy.setOriginal(old.getOriginal() == null ? old : old.getOriginal());
copyConstraints(copy.getConstraints(), old.getConstraints());
copy.setParent(newParent);
copy.setDescription(old.getDescription());
return copy;
}
- private static LeafListSchemaNodeBuilder copy(final LeafListSchemaNodeBuilder old, final Builder newParent, final boolean updateQName) {
+ private static LeafListSchemaNodeBuilder copy(final LeafListSchemaNodeBuilder old, final Builder newParent,
+ final boolean updateQName) {
DataBean data = getdata(old, newParent, updateQName);
QName newQName = data.qname;
SchemaPath newSchemaPath = data.schemaPath;
LeafListSchemaNodeBuilder copy = new LeafListSchemaNodeBuilder(newParent.getModuleName(), newParent.getLine(),
newQName, newSchemaPath);
+ copy.setOriginal(old.getOriginal() == null ? old : old.getOriginal());
copyConstraints(copy.getConstraints(), old.getConstraints());
copy.setParent(newParent);
copy.setDescription(old.getDescription());
return copy;
}
- private static ListSchemaNodeBuilder copy(final ListSchemaNodeBuilder old, final Builder newParent, final boolean updateQName) {
+ private static ListSchemaNodeBuilder copy(final ListSchemaNodeBuilder old, final Builder newParent,
+ final boolean updateQName) {
DataBean data = getdata(old, newParent, updateQName);
QName newQName = data.qname;
SchemaPath newSchemaPath = data.schemaPath;
ListSchemaNodeBuilder copy = new ListSchemaNodeBuilder(newParent.getModuleName(), newParent.getLine(),
newQName, newSchemaPath);
+ copy.setOriginal(old.getOriginal() == null ? old : old.getOriginal());
copyConstraints(copy.getConstraints(), old.getConstraints());
copy.setParent(newParent);
copy.setDescription(old.getDescription());
QName newQName = data.qname;
SchemaPath newSchemaPath = data.schemaPath;
- GroupingBuilderImpl copy = new GroupingBuilderImpl(newParent.getModuleName(), newParent.getLine(), newQName, newSchemaPath);
+ GroupingBuilderImpl copy = new GroupingBuilderImpl(newParent.getModuleName(), newParent.getLine(), newQName,
+ newSchemaPath);
copy.setParent(newParent);
copy.setDescription(old.getDescription());
copy.setReference(old.getReference());
return copy;
}
- public static TypeDefinitionBuilder copy(final TypeDefinitionBuilder old, final Builder newParent, final boolean updateQName) {
+ public static TypeDefinitionBuilder copy(final TypeDefinitionBuilder old, final Builder newParent,
+ final boolean updateQName) {
DataBean data = getdata(old, newParent, updateQName);
QName newQName = data.qname;
SchemaPath newSchemaPath = data.schemaPath;
return type;
}
- private static ConstraintsBuilder copyConstraints(final ConstraintsBuilder newConstraints, final ConstraintsBuilder old) {
+ private static ConstraintsBuilder copyConstraints(final ConstraintsBuilder newConstraints,
+ final ConstraintsBuilder old) {
newConstraints.getMustDefinitions().addAll(old.getMustDefinitions());
newConstraints.addWhenCondition(old.getWhenCondition());
newConstraints.setMandatory(old.isMandatory());
return copy;
}
- public static UnknownSchemaNodeBuilderImpl copy(final UnknownSchemaNodeBuilder old, final Builder newParent, final boolean updateQName) {
+ public static UnknownSchemaNodeBuilderImpl copy(final UnknownSchemaNodeBuilder old, final Builder newParent,
+ final boolean updateQName) {
DataBean data = getdata(old, newParent, updateQName);
QName newQName = data.qname;
SchemaPath newSchemaPath = data.schemaPath;
- UnknownSchemaNodeBuilderImpl c = new UnknownSchemaNodeBuilderImpl(newParent.getModuleName(), newParent.getLine(),
- newQName, newSchemaPath);
+ UnknownSchemaNodeBuilderImpl c = new UnknownSchemaNodeBuilderImpl(newParent.getModuleName(),
+ newParent.getLine(), newQName, newSchemaPath);
c.setNodeType(old.getNodeType());
c.setNodeParameter(old.getNodeParameter());
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();
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
-
import java.util.HashSet;
import java.util.List;
import java.util.Set;
-
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
-import org.opendaylight.yangtools.yang.model.api.Status;
import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
import org.opendaylight.yangtools.yang.parser.builder.api.Builder;
import org.opendaylight.yangtools.yang.parser.builder.api.DataSchemaNodeBuilder;
private GroupingDefinitionImpl instance;
// SchemaNode args
private SchemaPath schemaPath;
- private String description;
- private String reference;
- private Status status = Status.CURRENT;
// DataSchemaNode args
private boolean addedByUses;
public GroupingBuilderImpl(final String moduleName, final int line, final QName qname, final SchemaPath path,
final GroupingDefinition base) {
- super(moduleName, line, base.getQName(), path, base);
+ super(moduleName, line, base.getQName(), Preconditions.checkNotNull(path, "Schema Path must not be null"), base);
schemaPath = path;
-
- description = base.getDescription();
- reference = base.getReference();
- status = base.getStatus();
addedByUses = base.isAddedByUses();
-
addedUnknownNodes.addAll(BuilderUtils.wrapUnknownNodes(moduleName, line, base.getUnknownSchemaNodes(), path,
qname));
}
*/
package org.opendaylight.yangtools.yang.parser.builder.impl;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
import java.util.List;
+
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.ConstraintDefinition;
+import org.opendaylight.yangtools.yang.model.api.DerivableSchemaNode;
import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
import org.opendaylight.yangtools.yang.model.api.Status;
import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
import org.opendaylight.yangtools.yang.parser.builder.api.ConstraintsBuilder;
import org.opendaylight.yangtools.yang.parser.builder.api.DataSchemaNodeBuilder;
+import org.opendaylight.yangtools.yang.parser.builder.api.SchemaNodeBuilder;
import org.opendaylight.yangtools.yang.parser.builder.api.UnknownSchemaNodeBuilder;
import org.opendaylight.yangtools.yang.parser.builder.util.AbstractTypeAwareBuilder;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+
public final class LeafListSchemaNodeBuilder extends AbstractTypeAwareBuilder implements DataSchemaNodeBuilder {
private LeafListSchemaNodeImpl instance;
private boolean userOrdered;
// DataSchemaNode args
private boolean augmenting;
private boolean addedByUses;
+ private LeafListSchemaNode originalNode;
+ private LeafListSchemaNodeBuilder originalBuilder;
private boolean configuration;
private final ConstraintsBuilder constraints;
status = base.getStatus();
augmenting = base.isAugmenting();
addedByUses = base.isAddedByUses();
+ originalNode = base;
configuration = base.isConfiguration();
this.type = base.getType();
userOrdered = base.isUserOrdered();
instance.type = type;
}
+ // ORIGINAL NODE
+ if (originalNode == null && originalBuilder != null) {
+ originalNode = originalBuilder.build();
+ }
+ instance.original = originalNode;
+
// UNKNOWN NODES
for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
unknownNodes.add(b.build());
this.addedByUses = addedByUses;
}
+ @Override
+ public LeafListSchemaNodeBuilder getOriginal() {
+ return originalBuilder;
+ }
+
+ @Override
+ public void setOriginal(final SchemaNodeBuilder builder) {
+ Preconditions.checkArgument(builder instanceof LeafListSchemaNodeBuilder, "Original of leaf-list cannot be "
+ + builder);
+ this.originalBuilder = (LeafListSchemaNodeBuilder) builder;
+ }
+
@Override
public boolean isConfiguration() {
return configuration;
return "leaf-list " + qname.getLocalName();
}
- private static final class LeafListSchemaNodeImpl implements LeafListSchemaNode {
+ private static final class LeafListSchemaNodeImpl implements LeafListSchemaNode, DerivableSchemaNode {
private final QName qname;
private final SchemaPath path;
private String description;
private Status status;
private boolean augmenting;
private boolean addedByUses;
+ private LeafListSchemaNode original;
private boolean configuration;
private ConstraintDefinition constraintsDef;
private TypeDefinition<?> type;
return addedByUses;
}
+ @Override
+ public Optional<LeafListSchemaNode> getOriginal() {
+ return Optional.fromNullable(original);
+ }
+
@Override
public boolean isConfiguration() {
return configuration;
*/
package org.opendaylight.yangtools.yang.parser.builder.impl;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
import java.util.List;
+
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.ConstraintDefinition;
+import org.opendaylight.yangtools.yang.model.api.DerivableSchemaNode;
import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
import org.opendaylight.yangtools.yang.model.api.Status;
import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
import org.opendaylight.yangtools.yang.parser.builder.api.ConstraintsBuilder;
import org.opendaylight.yangtools.yang.parser.builder.api.DataSchemaNodeBuilder;
+import org.opendaylight.yangtools.yang.parser.builder.api.SchemaNodeBuilder;
import org.opendaylight.yangtools.yang.parser.builder.api.UnknownSchemaNodeBuilder;
import org.opendaylight.yangtools.yang.parser.builder.util.AbstractTypeAwareBuilder;
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;
+
public final class LeafSchemaNodeBuilder extends AbstractTypeAwareBuilder implements DataSchemaNodeBuilder {
private LeafSchemaNodeImpl instance;
private String defaultStr;
// DataSchemaNode args
private boolean augmenting;
private boolean addedByUses;
+ private LeafSchemaNode originalNode;
+ private LeafSchemaNodeBuilder originalBuilder;
private boolean configuration;
private final ConstraintsBuilder constraints;
status = base.getStatus();
augmenting = base.isAugmenting();
addedByUses = base.isAddedByUses();
+ originalNode =base;
configuration = base.isConfiguration();
this.type = base.getType();
unknownNodes.addAll(base.getUnknownSchemaNodes());
instance.type = type;
}
+ // ORIGINAL NODE
+ if (originalNode == null && originalBuilder != null) {
+ originalNode = originalBuilder.build();
+ }
+ instance.original = originalNode;
+
// UNKNOWN NODES
for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
unknownNodes.add(b.build());
this.addedByUses = addedByUses;
}
+ @Override
+ public LeafSchemaNodeBuilder getOriginal() {
+ return originalBuilder;
+ }
+
+ @Override
+ public void setOriginal(final SchemaNodeBuilder builder) {
+ Preconditions.checkArgument(builder instanceof LeafSchemaNodeBuilder, "Original of leaf cannot be " + builder);
+ this.originalBuilder = (LeafSchemaNodeBuilder) builder;
+ }
+
@Override
public boolean isConfiguration() {
return configuration;
return "leaf " + qname.getLocalName();
}
- private static final class LeafSchemaNodeImpl implements LeafSchemaNode {
+ private static final class LeafSchemaNodeImpl implements LeafSchemaNode, DerivableSchemaNode {
private final QName qname;
private final SchemaPath path;
private String description;
private Status status;
private boolean augmenting;
private boolean addedByUses;
+ private LeafSchemaNode original;
private boolean configuration;
private ConstraintDefinition constraintsDef;
private TypeDefinition<?> type;
return addedByUses;
}
+ @Override
+ public Optional<LeafSchemaNode> getOriginal() {
+ return Optional.fromNullable(original);
+ }
+
@Override
public boolean isConfiguration() {
return configuration;
*/
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.model.api.UnknownSchemaNode;
import org.opendaylight.yangtools.yang.parser.builder.api.AugmentationTargetBuilder;
import org.opendaylight.yangtools.yang.parser.builder.api.ConstraintsBuilder;
import org.opendaylight.yangtools.yang.parser.builder.api.DataSchemaNodeBuilder;
+import org.opendaylight.yangtools.yang.parser.builder.api.SchemaNodeBuilder;
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;
-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;
// DataSchemaNode args
private boolean augmenting;
private boolean addedByUses;
+ private ListSchemaNodeBuilder originalBuilder;
+ private ListSchemaNode originalNode;
private boolean configuration;
private final ConstraintsBuilder constraints;
// AugmentationTarget args
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());
augmenting = base.isAugmenting();
addedByUses = base.isAddedByUses();
+ originalNode = base;
configuration = base.isConfiguration();
addedUnknownNodes.addAll(BuilderUtils.wrapUnknownNodes(moduleName, line, base.getUnknownSchemaNodes(), path,
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);
}
+ // ORIGINAL NODE
+ if (originalNode == null && originalBuilder != null) {
+ originalNode = originalBuilder.build();
+ }
+ instance.original = originalNode;
+
// AUGMENTATIONS
for (AugmentationSchemaBuilder builder : augmentationBuilders) {
augmentations.add(builder.build());
this.addedByUses = addedByUses;
}
+ @Override
+ public ListSchemaNodeBuilder getOriginal() {
+ return originalBuilder;
+ }
+
+ @Override
+ public void setOriginal(final SchemaNodeBuilder builder) {
+ Preconditions.checkArgument(builder instanceof ListSchemaNodeBuilder, "Original of list cannot be " + builder);
+ this.originalBuilder = (ListSchemaNodeBuilder) builder;
+ }
+
@Override
public boolean isConfiguration() {
return configuration;
return "list " + qname.getLocalName();
}
- private static final class ListSchemaNodeImpl extends AbstractDocumentedDataNodeContainer implements ListSchemaNode {
+ private static final class ListSchemaNodeImpl extends AbstractDocumentedDataNodeContainer implements
+ ListSchemaNode, DerivableSchemaNode {
private final QName qname;
private final SchemaPath path;
private ImmutableList<QName> keyDefinition;
private boolean augmenting;
private boolean addedByUses;
+ private ListSchemaNode original;
private boolean configuration;
private ConstraintDefinition constraints;
private ImmutableSet<AugmentationSchema> augmentations;
return addedByUses;
}
+ @Override
+ public Optional<ListSchemaNode> getOriginal() {
+ return Optional.fromNullable(original);
+ }
+
@Override
public boolean isConfiguration() {
return configuration;
}
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();
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 java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
-
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DocumentedNode;
import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
// addedUnknownNodes.addAll(BuilderUtils.wrapUnknownNodes(moduleName,
// line, base.getUnknownSchemaNodes(), path, qname));
usesNodes.addAll(base.getUses());
+
+ if (base instanceof DocumentedNode) {
+ DocumentedNode node = (DocumentedNode) base;
+ setDescription(node.getDescription());
+ setReference(node.getReference());
+ setStatus(node.getStatus());
+ }
}
@Override
*/
package org.opendaylight.yangtools.yang.parser.impl;
-import com.google.common.base.Optional;
-import com.google.common.base.Supplier;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSetMultimap;
-import com.google.common.collect.Multimaps;
-import com.google.common.collect.SetMultimap;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
+
import javax.annotation.concurrent.Immutable;
+
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.UsesNode;
import org.opendaylight.yangtools.yang.parser.util.ModuleDependencySort;
+import com.google.common.base.Optional;
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSetMultimap;
+import com.google.common.collect.Multimaps;
+import com.google.common.collect.SetMultimap;
+
@Immutable
final class SchemaContextImpl implements SchemaContext {
private static final Supplier<HashSet<Module>> URI_SET_SUPPLIER = new Supplier<HashSet<Module>>() {
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.List;
import java.util.Map;
import java.util.Set;
+
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
import org.opendaylight.yangtools.yang.model.api.UsesNode;
import org.opendaylight.yangtools.yang.model.parser.api.YangContextParser;
+import org.opendaylight.yangtools.yang.model.util.SchemaNodeUtils;
public class GroupingTest {
private Set<Module> modules;
assertNotNull(data_g);
assertFalse(data_g.isAddedByUses());
assertFalse(data_u.equals(data_g));
+ assertEquals(data_g, SchemaNodeUtils.getRootOriginalIfPossible(data_u));
ChoiceNode how_u = (ChoiceNode) destination.getDataChildByName("how");
assertNotNull(how_u);
TestUtils.checkIsAddedByUses(how_g, false);
assertEquals(2, how_g.getCases().size());
assertFalse(how_u.equals(how_g));
+ assertEquals(how_g, SchemaNodeUtils.getRootOriginalIfPossible(how_u));
LeafSchemaNode address_u = (LeafSchemaNode) destination.getDataChildByName("address");
assertNotNull(address_u);
assertTrue(address_g.isConfiguration());
assertFalse(address_u.equals(address_g));
assertTrue(address_g.getConstraints().isMandatory());
+ assertEquals(address_g, SchemaNodeUtils.getRootOriginalIfPossible(address_u));
ContainerSchemaNode port_u = (ContainerSchemaNode) destination.getDataChildByName("port");
assertNotNull(port_u);
assertNotNull(port_g);
TestUtils.checkIsAddedByUses(port_g, false);
assertFalse(port_u.equals(port_g));
+ assertEquals(port_g, SchemaNodeUtils.getRootOriginalIfPossible(port_u));
ListSchemaNode addresses_u = (ListSchemaNode) destination.getDataChildByName("addresses");
assertNotNull(addresses_u);
assertNotNull(addresses_g);
TestUtils.checkIsAddedByUses(addresses_g, false);
assertFalse(addresses_u.equals(addresses_g));
+ assertEquals(addresses_g, SchemaNodeUtils.getRootOriginalIfPossible(addresses_u));
// grouping defined by 'uses'
Set<GroupingDefinition> groupings_u = destination.getGroupings();
assertNotNull(data_g);
assertFalse(data_g.isAddedByUses());
assertFalse(data_u.equals(data_g));
+ assertEquals(data_g, SchemaNodeUtils.getRootOriginalIfPossible(data_u));
ChoiceNode how_u = (ChoiceNode) foo.getDataChildByName("how");
assertNotNull(how_u);
assertNotNull(how_g);
TestUtils.checkIsAddedByUses(how_g, false);
assertFalse(how_u.equals(how_g));
+ assertEquals(how_g, SchemaNodeUtils.getRootOriginalIfPossible(how_u));
LeafSchemaNode address_u = (LeafSchemaNode) foo.getDataChildByName("address");
assertNotNull(address_u);
assertNull(address_g.getReference());
assertTrue(address_g.isConfiguration());
assertFalse(address_u.equals(address_g));
+ assertEquals(address_g, SchemaNodeUtils.getRootOriginalIfPossible(address_u));
ContainerSchemaNode port_u = (ContainerSchemaNode) foo.getDataChildByName("port");
assertNotNull(port_u);
assertNotNull(port_g);
TestUtils.checkIsAddedByUses(port_g, false);
assertFalse(port_u.equals(port_g));
+ assertEquals(port_g, SchemaNodeUtils.getRootOriginalIfPossible(port_u));
ListSchemaNode addresses_u = (ListSchemaNode) foo.getDataChildByName("addresses");
assertNotNull(addresses_u);
assertNotNull(addresses_g);
TestUtils.checkIsAddedByUses(addresses_g, false);
assertFalse(addresses_u.equals(addresses_g));
+ assertEquals(addresses_g, SchemaNodeUtils.getRootOriginalIfPossible(addresses_u));
// grouping defined by 'uses'
Set<GroupingDefinition> groupings_u = foo.getGroupings();
// grouping-U
Set<DataSchemaNode> childNodes = gu.getChildNodes();
assertEquals(7, childNodes.size());
- LeafSchemaNode leafGroupingU = null;
+
+ LeafSchemaNode leafGroupingU = (LeafSchemaNode) gu.getDataChildByName("leaf-grouping-U");
+ assertNotNull(leafGroupingU);
+ assertFalse(leafGroupingU.isAddedByUses());
+ assertFalse(SchemaNodeUtils.getOriginalIfPossible(leafGroupingU).isPresent());
+
for (DataSchemaNode childNode : childNodes) {
- if ("leaf-grouping-U".equals(childNode.getQName().getLocalName())) {
- leafGroupingU = (LeafSchemaNode) childNode;
- } else {
+ if (!(childNode.getQName().equals(leafGroupingU.getQName()))) {
TestUtils.checkIsAddedByUses(childNode, true);
}
}
- assertNotNull(leafGroupingU);
- assertFalse(leafGroupingU.isAddedByUses());
// grouping-V
childNodes = gv.getChildNodes();
expectedPath = TestUtils.createPath(true, expectedNS, expectedRev, expectedPref, "grouping-ZZ",
"leaf-grouping-ZZ");
assertEquals(expectedPath, leafZZinGZZ.getPath());
+
+ // TEST getOriginal from grouping-U
+ assertEquals(gv.getDataChildByName("leaf-grouping-V"), SchemaNodeUtils.getRootOriginalIfPossible(gu.getDataChildByName("leaf-grouping-V")));
+ containerGroupingV = (ContainerSchemaNode) gu.getDataChildByName("container-grouping-V");
+ assertEquals(gv.getDataChildByName("container-grouping-V"), SchemaNodeUtils.getRootOriginalIfPossible(containerGroupingV));
+ assertEquals(gx.getDataChildByName("leaf-grouping-X"), SchemaNodeUtils.getRootOriginalIfPossible(containerGroupingV.getDataChildByName("leaf-grouping-X")
+ ));
+ assertEquals(gy.getDataChildByName("leaf-grouping-Y"), SchemaNodeUtils.getRootOriginalIfPossible(containerGroupingV.getDataChildByName("leaf-grouping-Y")
+ ));
+
+ assertEquals(gz.getDataChildByName("leaf-grouping-Z"), SchemaNodeUtils.getRootOriginalIfPossible(gu.getDataChildByName("leaf-grouping-Z")));
+ assertEquals(gzz.getDataChildByName("leaf-grouping-ZZ"), SchemaNodeUtils.getRootOriginalIfPossible(gu.getDataChildByName("leaf-grouping-ZZ")
+ ));
+
+ // TEST getOriginal from grouping-V
+ assertEquals(gz.getDataChildByName("leaf-grouping-Z"), SchemaNodeUtils.getRootOriginalIfPossible(gv.getDataChildByName("leaf-grouping-Z")));
+ assertEquals(gzz.getDataChildByName("leaf-grouping-ZZ"), SchemaNodeUtils.getRootOriginalIfPossible(gv.getDataChildByName("leaf-grouping-ZZ")
+ ));
+
+ // TEST getOriginal from grouping-X
+ assertEquals(gy.getDataChildByName("leaf-grouping-Y"),SchemaNodeUtils.getRootOriginalIfPossible( gx.getDataChildByName("leaf-grouping-Y")));
}
}
}
} 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());
+ }
+ }
+
}
--- /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;
+ }
+ }
+
+}