From c5aaa057429dbceb764a50c24b2f4d21f05e1fc3 Mon Sep 17 00:00:00 2001 From: Tony Tkacik Date: Sun, 1 Dec 2013 02:39:43 +0100 Subject: [PATCH] Fixed bug in Data store where multiple readers could overwrite other augmentations - Added configuration / operational data validation - Commit with operational data stored in configuration store will fail. - Added initial data change event. Change-Id: I5383cc28286bff98b95b11b63c56cd175ea2c7e9 Signed-off-by: Tony Tkacik --- .../md-sal/sal-binding-broker/pom.xml | 22 +- .../dom/serializer/impl/CodecMapping.java | 3 +- .../dom/serializer/impl/CodecTypeUtils.java | 2 - .../impl/LazyGeneratedCodecRegistry.java | 5 - .../impl/TransformerGenerator.xtend | 94 ++++--- .../dom/CommitHandlersTransactions.java | 2 +- .../binding/impl/util/YangSchemaUtils.java | 44 ++++ .../binding/test/AbstractDataServiceTest.java | 8 +- .../test/bugfix/DOMCodecBug01Test.java | 18 +- .../test/bugfix/DOMCodecBug02Test.java | 5 +- .../test/bugfix/DOMCodecBug03Test.java | 3 - .../dom/ChangeOriginatedInDomBrokerTest.java | 3 +- opendaylight/md-sal/sal-common-impl/pom.xml | 10 + .../common/impl/AbstractDataModification.java | 53 ++-- .../impl/routing/AbstractDataReadRouter.java | 14 +- .../impl/service/AbstractDataBroker.xtend | 3 - .../impl/service/DataChangeEventImpl.java | 4 +- .../service/InitialDataChangeEventImpl.java | 35 ++- opendaylight/md-sal/sal-dom-broker/pom.xml | 11 +- .../dom/broker/BrokerConfigActivator.xtend | 3 + .../sal/dom/broker/SchemaServiceImpl.java | 35 ++- .../broker/impl/DataStoreStatsWrapper.java | 26 +- .../sal/dom/broker/impl/RpcRouterImpl.xtend | 2 +- .../broker/impl/SchemaAwareDataMerger.xtend | 13 - .../impl/SchemaAwareDataStoreAdapter.java | 90 ++++++- .../yang/util/YangDataOperations.xtend | 116 +++++++++ .../yangtools/yang/util/YangDataUtils.java | 44 ++++ .../yangtools/yang/util/YangSchemaUtils.java | 239 ++++++++++++++++++ 28 files changed, 735 insertions(+), 172 deletions(-) create mode 100644 opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/YangSchemaUtils.java delete mode 100644 opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareDataMerger.xtend create mode 100644 opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/yangtools/yang/util/YangDataOperations.xtend create mode 100644 opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/yangtools/yang/util/YangDataUtils.java create mode 100644 opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/yangtools/yang/util/YangSchemaUtils.java diff --git a/opendaylight/md-sal/sal-binding-broker/pom.xml b/opendaylight/md-sal/sal-binding-broker/pom.xml index a5e5c74f4c..51b00845ae 100644 --- a/opendaylight/md-sal/sal-binding-broker/pom.xml +++ b/opendaylight/md-sal/sal-binding-broker/pom.xml @@ -51,7 +51,7 @@ - + org.codehaus.mojo build-helper-maven-plugin @@ -148,7 +148,7 @@ org.osgi org.osgi.core ${osgi.core.version} - provided + provided com.google.guava @@ -200,12 +200,12 @@ org.eclipse.xtend org.eclipse.xtend.lib - - org.eclipse.xtend - org.eclipse.xtend.standalone - 2.4.3 - runtime - + + org.eclipse.xtend + org.eclipse.xtend.standalone + 2.4.3 + runtime + org.opendaylight.controller sal-binding-config @@ -239,6 +239,12 @@ ${slf4j.version} test + + org.opendaylight.controller.model + model-flow-statistics + 1.0-SNAPSHOT + test + org.reflections reflections diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/CodecMapping.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/CodecMapping.java index 35f48745f9..d05967c2c8 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/CodecMapping.java +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/CodecMapping.java @@ -7,7 +7,6 @@ import org.opendaylight.controller.sal.binding.dom.serializer.api.InstanceIdenti import org.opendaylight.yangtools.yang.binding.BindingCodec; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.CompositeNode; -import org.opendaylight.yangtools.yang.data.api.Node; public class CodecMapping { @@ -16,7 +15,7 @@ public class CodecMapping { public static final String COMPOSITE_TO_CASE = "COMPOSITE_TO_CASE"; public static final String AUGMENTATION_CODEC = "AUGMENTATION_CODEC"; - public static void setIdentifierCodec(Class obj,InstanceIdentifierCodec codec) { + public static void setIdentifierCodec(Class obj,InstanceIdentifierCodec codec) { Field instanceIdField; try { instanceIdField = obj.getField(INSTANCE_IDENTIFIER_CODEC); diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/CodecTypeUtils.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/CodecTypeUtils.java index 048dc3ad47..d86d2f461d 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/CodecTypeUtils.java +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/CodecTypeUtils.java @@ -3,7 +3,6 @@ package org.opendaylight.controller.sal.binding.dom.serializer.impl; import org.opendaylight.yangtools.yang.binding.Identifiable; import org.opendaylight.yangtools.yang.binding.Identifier; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument; public class CodecTypeUtils { @@ -13,5 +12,4 @@ public class CodecTypeUtils { Identifier> identifier = (Identifier>) key; return new IdentifiableItem(identifiableType,identifier); } - } diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/LazyGeneratedCodecRegistry.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/LazyGeneratedCodecRegistry.java index b81100836f..a55d4b9276 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/LazyGeneratedCodecRegistry.java +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/LazyGeneratedCodecRegistry.java @@ -2,7 +2,6 @@ package org.opendaylight.controller.sal.binding.dom.serializer.impl; import java.lang.ref.WeakReference; import java.lang.reflect.Field; -import java.util.AbstractMap.SimpleEntry; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -337,15 +336,11 @@ public class LazyGeneratedCodecRegistry implements // @Override public void onValueCodecCreated(Class valueClass, Class valueCodec) { - // TODO Auto-generated method stub - } @Override public void onCaseCodecCreated(Class choiceClass, Class, Object>> choiceCodec) { - // TODO Auto-generated method stub - } @Override diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/TransformerGenerator.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/TransformerGenerator.xtend index 01390d7c41..ab2e96f05c 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/TransformerGenerator.xtend +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/TransformerGenerator.xtend @@ -45,6 +45,7 @@ import org.opendaylight.yangtools.yang.binding.Augmentation import java.util.Iterator import org.opendaylight.yangtools.yang.model.api.AugmentationSchema import java.util.concurrent.ConcurrentHashMap +import static extension org.opendaylight.controller.sal.binding.impl.util.YangSchemaUtils.*; class TransformerGenerator { @@ -214,7 +215,7 @@ class TransformerGenerator { if (transformer !== null) { return transformer; } - return withClassLoaderAndLock(cls.classLoader,lock) [| + return withClassLoaderAndLock(cls.classLoader, lock) [ | val valueTransformer = generateValueTransformer(cls, type); return valueTransformer; ] @@ -222,6 +223,7 @@ class TransformerGenerator { private def generateKeyTransformerFor(Class inputType, GeneratedType typeSpec, ListSchemaNode node) { try { + //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader) val properties = typeSpec.allProperties; val ctCls = createClass(inputType.codecClassName) [ @@ -260,13 +262,15 @@ class TransformerGenerator { } «QName.name» _localQName = $1; java.util.Map _compositeNode = (java.util.Map) $2; + boolean _is_empty = true; «FOR key : node.keyDefinition» «val propertyName = key.getterName» «val keyDef = node.getDataChildByName(key)» «val property = properties.get(propertyName)» «deserializeProperty(keyDef, property, propertyName)»; «ENDFOR» - «inputType.resolvedName» _value = new «inputType.name»(«node.keyDefinition.keyConstructorList»); + «inputType.resolvedName» _value = new «inputType.name»(«node.keyDefinition. + keyConstructorList»); return _value; } ''' @@ -299,11 +303,12 @@ class TransformerGenerator { private def Class> generateCaseCodec(Class inputType, GeneratedType type, ChoiceCaseNode node) { try { + //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(inputType); + staticQNameField(node.QName); staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec) staticField(it, AUGMENTATION_CODEC, BindingCodec) method(Object, "toDomStatic", QName, Object) [ @@ -313,7 +318,7 @@ class TransformerGenerator { «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName()); java.util.List _childNodes = new java.util.ArrayList(); «type.resolvedName» value = («type.resolvedName») $2; - «transformDataContainerBody(type,type.allProperties, node)» + «transformDataContainerBody(type, type.allProperties, node)» return ($r) _childNodes; } ''' @@ -356,10 +361,11 @@ class TransformerGenerator { private def dispatch Class, Object>> generateTransformerFor( Class inputType, GeneratedType typeSpec, SchemaNode node) { try { + //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader) val ctCls = createClass(typeSpec.codecClassName) [ //staticField(Map,"AUGMENTATION_SERIALIZERS"); - staticQNameField(inputType); + staticQNameField(node.QName); staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec) staticField(it, AUGMENTATION_CODEC, BindingCodec) implementsType(BINDING_CODEC) @@ -403,11 +409,12 @@ class TransformerGenerator { private def Class, Object>> generateAugmentationTransformerFor( Class inputType, GeneratedType type, AugmentationSchema node) { try { + //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader) val properties = type.allProperties val ctCls = createClass(type.codecClassName) [ //staticField(Map,"AUGMENTATION_SERIALIZERS"); - staticQNameField(inputType); + staticQNameField(node.augmentationQName); staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec) staticField(it, AUGMENTATION_CODEC, BindingCodec) implementsType(BINDING_CODEC) @@ -453,12 +460,15 @@ class TransformerGenerator { java.util.Map _compositeNode = (java.util.Map) $2; //System.out.println(_localQName + " " + _compositeNode); «type.builderName» _builder = new «type.builderName»(); + boolean _is_empty = true; «FOR child : node.childNodes» «val signature = properties.getFor(child)» «deserializeProperty(child, signature.value, signature.key)» - _builder.«signature.key.toSetter»(«signature.key»); «ENDFOR» + if(_is_empty) { + return null; + } return _builder.build(); } ''' @@ -482,6 +492,7 @@ class TransformerGenerator { private def dispatch Class, Object>> generateTransformerFor( Class inputType, GeneratedType typeSpec, ChoiceNode node) { try { + //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader) val ctCls = createClass(typeSpec.codecClassName) [ //staticField(Map,"AUGMENTATION_SERIALIZERS"); @@ -639,11 +650,13 @@ class TransformerGenerator { private def deserializeNodeContainerBodyImpl(GeneratedType type, HashMap properties, DataNodeContainer node) { val ret = ''' - «FOR child : node.childNodes.filter[!augmenting]» + boolean _is_empty = true; + «FOR child : node.childNodes» «val signature = properties.getFor(child)» - «deserializeProperty(child, signature.value, signature.key)» - - _builder.«signature.key.toSetter»(«signature.key»); + «IF signature !== null» + «deserializeProperty(child, signature.value, signature.key)» + _builder.«signature.key.toSetter»(«signature.key»); + «ENDIF» «ENDFOR» ''' return ret; @@ -658,7 +671,9 @@ class TransformerGenerator { //System.out.println("Aug. key:" + _entry.getKey()); Class _type = (Class) _entry.getKey(); «Augmentation.resolvedName» _value = («Augmentation.name») _entry.getValue(); - _builder.addAugmentation(_type,_value); + if(_value != null) { + _builder.addAugmentation(_type,_value); + } } } ''' @@ -675,6 +690,7 @@ class TransformerGenerator { boolean _hasNext = _iterator.hasNext(); while(_hasNext) { Object _listItem = _iterator.next(); + _is_empty = false; //System.out.println(" item" + _listItem); Object _value = «type.actualTypeArguments.get(0).serializer.resolvedName».fromDomStatic(_localQName,_listItem); //System.out.println(" value" + _value); @@ -696,6 +712,7 @@ class TransformerGenerator { java.util.Iterator _iterator = _dom_«propertyName».iterator(); boolean _hasNext = _iterator.hasNext(); while(_hasNext) { + _is_empty = false; Object _listItem = _iterator.next(); if(_listItem instanceof java.util.Map.Entry) { Object _innerValue = ((java.util.Map.Entry) _listItem).getValue(); @@ -712,6 +729,7 @@ class TransformerGenerator { _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.localName»")); «type.resolvedName» «propertyName» = null; if(_dom_«propertyName»_list != null && _dom_«propertyName»_list.size() > 0) { + _is_empty = false; java.util.Map.Entry _dom_«propertyName» = (java.util.Map.Entry) _dom_«propertyName»_list.get(0); Object _inner_value = _dom_«propertyName».getValue(); «propertyName» = «deserializeValue(type, "_inner_value")»; @@ -724,7 +742,7 @@ class TransformerGenerator { _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.localName»")); «type.resolvedName» «propertyName» = null; if(_dom_«propertyName»_list != null && _dom_«propertyName»_list.size() > 0) { - + _is_empty = false; java.util.Map _dom_«propertyName» = (java.util.Map) _dom_«propertyName»_list.get(0); «propertyName» = «type.serializer.resolvedName».fromDomStatic(_localQName,_dom_«propertyName»); } @@ -732,10 +750,13 @@ class TransformerGenerator { private def dispatch CharSequence deserializeProperty(ChoiceNode schema, Type type, String propertyName) ''' «type.resolvedName» «propertyName» = «type.serializer.resolvedName».fromDomStatic(_localQName,_compositeNode); + if(«propertyName» != null) { + _is_empty = false; + } ''' private def dispatch String deserializeValue(GeneratedTransferObject type, String domParameter) ''' - («type.resolvedName») «type.valueSerializer.resolvedName».fromDomValue(«domParameter»); + («type.resolvedName») «type.valueSerializer.resolvedName».fromDomValue(«domParameter») ''' private def dispatch Class, Object>> generateValueTransformer( @@ -758,7 +779,7 @@ class TransformerGenerator { val hasYangBinding = hasBinding val ctCls = createClass(typeSpec.codecClassName) [ //staticField(Map,"AUGMENTATION_SERIALIZERS"); - if(hasYangBinding) { + if (hasYangBinding) { implementsType(BINDING_CODEC) staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec) implementsType(BindingDeserializer.asCtClass) @@ -865,14 +886,13 @@ class TransformerGenerator { return null; } - private def dispatch Class generateValueTransformer( - Class inputType, Enumeration typeSpec) { + private def dispatch Class generateValueTransformer(Class inputType, Enumeration typeSpec) { try { + //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 body = ''' @@ -981,12 +1001,6 @@ class TransformerGenerator { */ private def getBuilderName(GeneratedType type) '''«type.resolvedName»Builder''' - private def staticQNameField(CtClass it, Class node) { - val field = new CtField(ctQName, "QNAME", it); - field.modifiers = PUBLIC + FINAL + STATIC; - addField(field, '''«node.name».QNAME''') - } - private def staticQNameField(CtClass it, QName node) { val field = new CtField(ctQName, "QNAME", it); field.modifiers = PUBLIC + FINAL + STATIC; @@ -999,7 +1013,7 @@ class TransformerGenerator { «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName()); java.util.List _childNodes = new java.util.ArrayList(); «type.resolvedName» value = («type.resolvedName») $2; - «transformDataContainerBody(type,type.allProperties, node)» + «transformDataContainerBody(type, type.allProperties, node)» «serializeAugmentations» return ($r) java.util.Collections.singletonMap(_resultName,_childNodes); } @@ -1010,7 +1024,7 @@ class TransformerGenerator { «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName()); java.util.List _childNodes = new java.util.ArrayList(); «type.resolvedName» value = («type.resolvedName») $2; - «transformDataContainerBody(type,type.allProperties, node)» + «transformDataContainerBody(type, type.allProperties, node)» «serializeAugmentations» return ($r) java.util.Collections.singletonMap(_resultName,_childNodes); } @@ -1021,7 +1035,7 @@ class TransformerGenerator { «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName()); java.util.List _childNodes = new java.util.ArrayList(); «type.resolvedName» value = («type.resolvedName») $2; - «transformDataContainerBody(type,type.allProperties, node)» + «transformDataContainerBody(type, type.allProperties, node)» «serializeAugmentations» return ($r) java.util.Collections.singletonMap(_resultName,_childNodes); } @@ -1036,18 +1050,20 @@ class TransformerGenerator { } ''' - private def transformDataContainerBody(Type type,Map properties, DataNodeContainer node) { + private def transformDataContainerBody(Type type, Map properties, DataNodeContainer node) { val ret = ''' - «FOR child : node.childNodes.filter[!augmenting]» - «var signature = properties.getFor(child)» - //System.out.println("«type.name»#«signature.key»" + value.«signature.key»()); - «serializeProperty(child, signature.value, signature.key)» + «FOR child : node.childNodes» + «val signature = properties.getFor(child)» + «IF signature !== null» + //System.out.println("«type.name»#«signature.key»" + value.«signature.key»()); + «serializeProperty(child, signature.value, signature.key)» + «ENDIF» «ENDFOR» ''' return ret; } - def serializeAugmentations() ''' + private def serializeAugmentations() ''' java.util.List _augmentations = (java.util.List) «AUGMENTATION_CODEC».serialize(value); if(_augmentations != null) { _childNodes.addAll(_augmentations); @@ -1055,12 +1071,15 @@ class TransformerGenerator { ''' def Entry getFor(Map map, DataSchemaNode node) { - val sig = map.get(node.getterName); - if (sig == null) { - + var sig = map.get(node.getterName); + if (sig != null) { + return new SimpleEntry(node.getterName, sig); + } + sig = map.get(node.booleanGetterName); + if (sig != null) { return new SimpleEntry(node.booleanGetterName, map.get(node.booleanGetterName)); } - return new SimpleEntry(node.getterName, sig); + return null; } private static def String getBooleanGetterName(DataSchemaNode node) { @@ -1078,6 +1097,7 @@ class TransformerGenerator { private def dispatch CharSequence serializeProperty(ListSchemaNode schema, ParameterizedType type, String propertyName) ''' «type.resolvedName» «propertyName» = value.«propertyName»(); + //System.out.println("«propertyName»:" + «propertyName»); if(«propertyName» != null) { java.util.Iterator _iterator = «propertyName».iterator(); boolean _hasNext = _iterator.hasNext(); diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/CommitHandlersTransactions.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/CommitHandlersTransactions.java index ea4837421d..254b8725b9 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/CommitHandlersTransactions.java +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/CommitHandlersTransactions.java @@ -11,7 +11,7 @@ import org.opendaylight.yangtools.yang.common.RpcResult; public class CommitHandlersTransactions { - private static class AllwaysSuccessfulTransaction implements DataCommitTransaction { + private static class AllwaysSuccessfulTransaction

,D> implements DataCommitTransaction { private final DataModification modification; diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/YangSchemaUtils.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/YangSchemaUtils.java new file mode 100644 index 0000000000..b7a21cb022 --- /dev/null +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/YangSchemaUtils.java @@ -0,0 +1,44 @@ +package org.opendaylight.controller.sal.binding.impl.util; + +import java.util.List; + +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode; + +import com.google.common.base.Preconditions; + +public class YangSchemaUtils { + + public static final String AUGMENT_IDENTIFIER = "augment-identifier"; + + + public YangSchemaUtils() { + throw new UnsupportedOperationException("Helper class. Instantiation is prohibited"); + } + + + public static QName getAugmentationQName(AugmentationSchema augmentation) { + Preconditions.checkNotNull(augmentation, "Augmentation must not be null."); + QName identifier = getAugmentationIdentifier(augmentation); + if(identifier != null) { + return identifier; + } + for(DataSchemaNode child : augmentation.getChildNodes()) { + // FIXME: Return true name + return QName.create(child.getQName(), "foo_augment"); + } + // FIXME: Allways return a qname with module namespace. + return null; + } + + public static QName getAugmentationIdentifier(AugmentationSchema augmentation) { + for(UnknownSchemaNode extension : augmentation.getUnknownSchemaNodes()) { + if(AUGMENT_IDENTIFIER.equals(extension.getNodeType().getLocalName())) { + return extension.getQName(); + } + } + return null; + } +} diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/AbstractDataServiceTest.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/AbstractDataServiceTest.java index 9f3a6e8652..c67a0176d2 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/AbstractDataServiceTest.java +++ b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/AbstractDataServiceTest.java @@ -51,7 +51,7 @@ public abstract class AbstractDataServiceTest { protected ListeningExecutorService executor; protected BindingIndependentDataServiceConnector connectorServiceImpl; protected HashMapDataStore rawDataStore; - private SchemaAwareDataStoreAdapter schemaAwareDataStore; + protected SchemaAwareDataStoreAdapter schemaAwareDataStore; private DataStoreStatsWrapper dataStoreStats; protected DataStore dataStore; @@ -137,15 +137,15 @@ public abstract class AbstractDataServiceTest { @After public void afterTest() { - log.info("BIDataStore Statistics: Configuration Read Count: {} TotalTime: {} ns AverageTime (ns): {} ns", + log.info("BIDataStore Statistics: Configuration Read Count: {} TotalTime: {} ms AverageTime (ns): {} ms", dataStoreStats.getConfigurationReadCount(), dataStoreStats.getConfigurationReadTotalTime(), dataStoreStats.getConfigurationReadAverageTime()); - log.info("BIDataStore Statistics: Operational Read Count: {} TotalTime: {} ns AverageTime (ns): {} ns", + log.info("BIDataStore Statistics: Operational Read Count: {} TotalTime: {} ms AverageTime (ns): {} ms", dataStoreStats.getOperationalReadCount(), dataStoreStats.getOperationalReadTotalTime(), dataStoreStats.getOperationalReadAverageTime()); - log.info("BIDataStore Statistics: Request Commit Count: {} TotalTime: {} ns AverageTime (ns): {} ns", + log.info("BIDataStore Statistics: Request Commit Count: {} TotalTime: {} ms AverageTime (ns): {} ms", dataStoreStats.getRequestCommitCount(), dataStoreStats.getRequestCommitTotalTime(), dataStoreStats.getRequestCommitAverageTime()); diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug01Test.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug01Test.java index f60ddb991d..5a98767ff8 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug01Test.java +++ b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug01Test.java @@ -10,6 +10,7 @@ import java.util.concurrent.Executors; + import org.junit.Test; import org.opendaylight.controller.md.sal.common.api.TransactionStatus; import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest; @@ -28,6 +29,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.M import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef; @@ -148,7 +150,7 @@ public class DOMCodecBug01Test extends AbstractDataServiceTest { assertEquals(TransactionStatus.COMMITED, ret2.getResult()); // Data are not in the store. - assertNull(baDataService.readOperationalData(FLOW_INSTANCE_ID_BA)); + assertNull(baDataService.readConfigurationData(FLOW_INSTANCE_ID_BA)); } @@ -169,11 +171,13 @@ public class DOMCodecBug01Test extends AbstractDataServiceTest { flow.setNode(NODE_REF); InstructionsBuilder instructions = new InstructionsBuilder(); InstructionBuilder instruction = new InstructionBuilder(); + + instruction.setOrder(10); ApplyActionsBuilder applyActions = new ApplyActionsBuilder(); List actionList = new ArrayList<>(); PopMplsActionBuilder popMplsAction = new PopMplsActionBuilder(); popMplsAction.setEthernetType(34); - actionList.add(new ActionBuilder().setAction(popMplsAction.build()).build()); + actionList.add(new ActionBuilder().setAction(popMplsAction.build()).setOrder(10).build()); applyActions.setAction(actionList ); @@ -200,17 +204,9 @@ public class DOMCodecBug01Test extends AbstractDataServiceTest { FlowBuilder flow = new FlowBuilder(); flow.setKey(key); MatchBuilder match = new MatchBuilder(); - Ipv4MatchBuilder ipv4Match = new Ipv4MatchBuilder(); - // ipv4Match.setIpv4Destination(new Ipv4Prefix(cliInput.get(4))); match.setLayer4Match(new TcpMatchBuilder().build()); flow.setMatch(match.build()); - DropAction dropAction = new DropActionBuilder().build(); - // ActionBuilder action = new ActionBuilder(); - - // List actions = Collections - // .singletonList(action.build()); - // flow.setAction(actions); - flow.setPriority(2); + System.out.println("Putting the configuration Data................"); path1 = InstanceIdentifier.builder(Flows.class).child(Flow.class, key).toInstance(); // DataObject cls = (DataObject) modification.readConfigurationData(path1); diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug02Test.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug02Test.java index 4df10bc135..85d484a617 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug02Test.java +++ b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug02Test.java @@ -21,6 +21,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.N import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; import static org.junit.Assert.*; @@ -77,8 +78,10 @@ public class DOMCodecBug02Test extends AbstractDataServiceTest { return transaction.commit(); } }); - mappingServiceImpl.onGlobalContextUpdated(getContext(getAllModelFilenames())); + SchemaContext ctx = getContext(getAllModelFilenames()); + schemaAwareDataStore.onGlobalContextUpdated(ctx); + mappingServiceImpl.onGlobalContextUpdated(ctx); RpcResult result = future.get().get(); assertEquals(TransactionStatus.COMMITED, result.getResult()); diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug03Test.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug03Test.java index 2cd396dedc..91163d80f2 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug03Test.java +++ b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug03Test.java @@ -97,9 +97,6 @@ public class DOMCodecBug03Test extends AbstractDataServiceTest implements DataCh testAddingNodeConnector(); - - - testNodeRemove(); diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/ChangeOriginatedInDomBrokerTest.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/ChangeOriginatedInDomBrokerTest.java index 63368bd6c8..7fe5f0c5be 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/ChangeOriginatedInDomBrokerTest.java +++ b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/ChangeOriginatedInDomBrokerTest.java @@ -166,11 +166,12 @@ public class ChangeOriginatedInDomBrokerTest extends AbstractDataServiceTest { flow.setNode(NODE_REF); InstructionsBuilder instructions = new InstructionsBuilder(); InstructionBuilder instruction = new InstructionBuilder(); + instruction.setOrder(10); ApplyActionsBuilder applyActions = new ApplyActionsBuilder(); List actionList = new ArrayList<>(); PopMplsActionBuilder popMplsAction = new PopMplsActionBuilder(); popMplsAction.setEthernetType(34); - actionList.add(new ActionBuilder().setAction(popMplsAction.build()).build()); + actionList.add(new ActionBuilder().setAction(popMplsAction.build()).setOrder(0).build()); applyActions.setAction(actionList ); diff --git a/opendaylight/md-sal/sal-common-impl/pom.xml b/opendaylight/md-sal/sal-common-impl/pom.xml index 7fb05806df..47e9c611d8 100644 --- a/opendaylight/md-sal/sal-common-impl/pom.xml +++ b/opendaylight/md-sal/sal-common-impl/pom.xml @@ -33,6 +33,16 @@ org.eclipse.xtend org.eclipse.xtend.lib + + junit + junit + test + + + org.mockito + mockito-all + test + diff --git a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/AbstractDataModification.java b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/AbstractDataModification.java index bee863321f..fb3e38f44a 100644 --- a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/AbstractDataModification.java +++ b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/AbstractDataModification.java @@ -10,8 +10,9 @@ import java.util.concurrent.ConcurrentMap; import org.opendaylight.controller.md.sal.common.api.data.DataModification; import org.opendaylight.controller.md.sal.common.api.data.DataReader; +import org.opendaylight.yangtools.concepts.Path; -public abstract class AbstractDataModification

*/, D> implements DataModification { +public abstract class AbstractDataModification

, D> implements DataModification { private final ConcurrentMap operationalOriginal; private final ConcurrentMap configurationOriginal; @@ -56,28 +57,28 @@ public abstract class AbstractDataModification

*/, D> imple unmodifiable_operationalUpdate = Collections.unmodifiableMap(operationalUpdate); unmodifiable_configurationRemove = Collections.unmodifiableSet(configurationRemove.keySet()); unmodifiable_OperationalRemove = Collections.unmodifiableSet(operationalRemove.keySet()); - } @Override public final void putConfigurationData(P path, D data) { checkMutable(); - - if (!hasConfigurationOriginal(path)) { + D original = null; + if ((original = getConfigurationOriginal(path)) == null) { configurationCreated.put(path, data); } - configurationUpdate.put(path, data); + configurationUpdate.put(path, mergeConfigurationData(path,original, data)); configurationRemove.remove(path); } @Override public final void putOperationalData(P path, D data) { checkMutable(); - if (!hasOperationalOriginal(path)) { + D original = null; + if ((original = getOperationalOriginal(path)) == null) { operationalCreated.put(path, data); } - operationalUpdate.put(path, data); + operationalUpdate.put(path, mergeOperationalData(path,original,data)); operationalRemove.remove(path); } @@ -89,7 +90,7 @@ public abstract class AbstractDataModification

*/, D> imple @Override public final void removeOperationalData(P path) { checkMutable(); - hasOperationalOriginal(path); + getOperationalOriginal(path); operationalUpdate.remove(path); operationalRemove.put(path, path); } @@ -102,7 +103,7 @@ public abstract class AbstractDataModification

*/, D> imple @Override public final void removeConfigurationData(P path) { checkMutable(); - hasConfigurationOriginal(path); + getConfigurationOriginal(path); configurationUpdate.remove(path); configurationRemove.put(path, path); } @@ -163,27 +164,37 @@ public abstract class AbstractDataModification

*/, D> imple return reader.readConfigurationData(path); } - private boolean hasConfigurationOriginal(P path) { - if (configurationOriginal.containsKey(path)) { - return true; + private D getConfigurationOriginal(P path) { + D data = configurationOriginal.get(path); + if (data != null) { + return data; } - D data = reader.readConfigurationData(path); + data = reader.readConfigurationData(path); if (data != null) { configurationOriginal.putIfAbsent(path, data); - return true; + return data; } - return false; + return null; } - private boolean hasOperationalOriginal(P path) { - if (operationalOriginal.containsKey(path)) { - return true; + private D getOperationalOriginal(P path) { + D data = operationalOriginal.get(path); + if (data != null) { + return data; } - D data = reader.readOperationalData(path); + data = reader.readOperationalData(path); if (data != null) { operationalOriginal.putIfAbsent(path, data); - return true; + return data; } - return false; + return null; + } + + protected D mergeOperationalData(P path,D stored, D modified) { + return modified; + } + + protected D mergeConfigurationData(P path,D stored, D modified) { + return modified; } } diff --git a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/routing/AbstractDataReadRouter.java b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/routing/AbstractDataReadRouter.java index d6b3c5334a..9e6147359d 100644 --- a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/routing/AbstractDataReadRouter.java +++ b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/routing/AbstractDataReadRouter.java @@ -20,7 +20,7 @@ import com.google.common.collect.Multimap; * @param

* @param */ -public abstract class AbstractDataReadRouter

, D> implements DataReader { +public abstract class AbstractDataReadRouter

, D> implements DataReader { Multimap> configReaders = HashMultimap.create(); Multimap> operationalReaders = HashMultimap.create(); @@ -139,14 +139,15 @@ public abstract class AbstractDataReadRouter

, D> implements Da @Override public boolean apply(Entry> input) { - final Path key = input.getKey(); - return key.contains(path) || ((Path) path).contains(key); + final P key = input.getKey(); + return key.contains(path) || ((P) path).contains(key); } }; } - private class ConfigurationDataReaderRegistration

, D> extends DataReaderRegistration { + @SuppressWarnings("hiding") + private class ConfigurationDataReaderRegistration

, D> extends DataReaderRegistration { public ConfigurationDataReaderRegistration(P key, DataReader instance) { super(key, instance); @@ -158,7 +159,8 @@ public abstract class AbstractDataReadRouter

, D> implements Da } } - private class OperationalDataReaderRegistration

, D> extends DataReaderRegistration { + @SuppressWarnings("hiding") + private class OperationalDataReaderRegistration

, D> extends DataReaderRegistration { public OperationalDataReaderRegistration(P key, DataReader instance) { super(key, instance); @@ -170,7 +172,7 @@ public abstract class AbstractDataReadRouter

, D> implements Da } } - private abstract static class DataReaderRegistration

, D> extends + private abstract static class DataReaderRegistration

, D> extends AbstractObjectRegistration> { private final P key; diff --git a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/AbstractDataBroker.xtend b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/AbstractDataBroker.xtend index a18e5a9c82..5f4f815961 100644 --- a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/AbstractDataBroker.xtend +++ b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/AbstractDataBroker.xtend @@ -28,8 +28,6 @@ import org.opendaylight.controller.md.sal.common.impl.routing.AbstractDataReadRo import org.opendaylight.yangtools.concepts.Path import org.slf4j.LoggerFactory import java.util.HashSet -import java.util.Map.Entry -import java.util.Iterator import java.util.Collection import com.google.common.collect.FluentIterable; import java.util.Set @@ -37,7 +35,6 @@ import com.google.common.collect.ImmutableList import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandlerRegistration import org.opendaylight.controller.md.sal.common.api.RegistrationListener import org.opendaylight.yangtools.concepts.util.ListenerRegistry -import java.util.concurrent.atomic.AtomicLong import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent abstract class AbstractDataBroker

, D, DCL extends DataChangeListener> implements DataModificationTransactionFactory, // diff --git a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/DataChangeEventImpl.java b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/DataChangeEventImpl.java index 68f9506c56..83943a1f38 100644 --- a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/DataChangeEventImpl.java +++ b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/DataChangeEventImpl.java @@ -5,8 +5,10 @@ import java.util.Set; import org.opendaylight.controller.md.sal.common.api.data.DataChange; import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent; +import org.opendaylight.yangtools.concepts.Immutable; +import org.opendaylight.yangtools.concepts.Path; -public class DataChangeEventImpl implements DataChangeEvent { +public class DataChangeEventImpl

, D> implements DataChangeEvent, Immutable { private final DataChange dataChange; diff --git a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/InitialDataChangeEventImpl.java b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/InitialDataChangeEventImpl.java index 2764635720..474d4b8811 100644 --- a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/InitialDataChangeEventImpl.java +++ b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/InitialDataChangeEventImpl.java @@ -5,15 +5,28 @@ import java.util.Map; import java.util.Set; import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent; +import org.opendaylight.yangtools.concepts.Immutable; +import org.opendaylight.yangtools.concepts.Path; -public class InitialDataChangeEventImpl implements DataChangeEvent { +public class InitialDataChangeEventImpl

,D> implements DataChangeEvent, Immutable { - private final D originalOperationalTree; - private final D originalConfigurationTree; + private final D updatedOperationalTree; + private final D updatedConfigurationTree; + private final Map updatedConfigurationData; + private final Map updatedOperationalData; public InitialDataChangeEventImpl(D configTree, D operTree) { - originalConfigurationTree = configTree; - originalOperationalTree = operTree; + updatedConfigurationTree = configTree; + updatedOperationalTree = operTree; + updatedConfigurationData = Collections.emptyMap(); + updatedOperationalData = Collections.emptyMap(); + } + + public InitialDataChangeEventImpl(D configTree, D operTree, Map updatedCfgData, Map updatedOperData) { + updatedConfigurationTree = configTree; + updatedOperationalTree = operTree; + updatedConfigurationData = updatedCfgData; + updatedOperationalData = updatedOperData; } @Override @@ -44,31 +57,31 @@ public class InitialDataChangeEventImpl implements DataChangeEvent { } @Override public Map getUpdatedConfigurationData() { - return Collections.emptyMap(); + return updatedConfigurationData; } @Override public D getUpdatedConfigurationSubtree() { - return originalConfigurationTree; + return updatedConfigurationTree; } @Override public D getUpdatedOperationalSubtree() { - return originalOperationalTree; + return updatedOperationalTree; } @Override public D getOriginalConfigurationSubtree() { - return originalConfigurationTree; + return updatedConfigurationTree; } @Override public D getOriginalOperationalSubtree() { - return originalOperationalTree; + return updatedOperationalTree; } @Override public Map getUpdatedOperationalData() { - return Collections.emptyMap(); + return updatedOperationalData; } diff --git a/opendaylight/md-sal/sal-dom-broker/pom.xml b/opendaylight/md-sal/sal-dom-broker/pom.xml index 14ab057398..a6601cef21 100644 --- a/opendaylight/md-sal/sal-dom-broker/pom.xml +++ b/opendaylight/md-sal/sal-dom-broker/pom.xml @@ -25,12 +25,6 @@ sal-common-util 1.0-SNAPSHOT - - - org.opendaylight.yangtools - yang-data-impl - 0.5.9-SNAPSHOT - org.opendaylight.controller sal-common-impl @@ -63,6 +57,11 @@ config-api 0.2.3-SNAPSHOT + + org.opendaylight.yangtools + yang-data-impl + 0.5.9-SNAPSHOT + org.opendaylight.yangtools yang-parser-impl diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerConfigActivator.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerConfigActivator.xtend index 54c94dca9f..da7cccb156 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerConfigActivator.xtend +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerConfigActivator.xtend @@ -13,6 +13,7 @@ import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier import org.opendaylight.controller.sal.core.api.data.DataStore import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareDataStoreAdapter +import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener class BrokerConfigActivator implements AutoCloseable { @@ -51,6 +52,8 @@ class BrokerConfigActivator implements AutoCloseable { wrappedStore = new SchemaAwareDataStoreAdapter(); wrappedStore.changeDelegate(store); wrappedStore.setValidationEnabled(false); + + context.registerService(SchemaServiceListener,wrappedStore,emptyProperties) dataService.registerConfigurationReader(ROOT, wrappedStore); dataService.registerCommitHandler(ROOT, wrappedStore); diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/SchemaServiceImpl.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/SchemaServiceImpl.java index 531f9e86c2..efbd81c615 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/SchemaServiceImpl.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/SchemaServiceImpl.java @@ -41,9 +41,9 @@ import com.google.common.collect.Sets; import static com.google.common.base.Preconditions.*; public class SchemaServiceImpl implements // -SchemaService, // -ServiceTrackerCustomizer, // -AutoCloseable { + SchemaService, // + ServiceTrackerCustomizer, // + AutoCloseable { private static final Logger logger = LoggerFactory.getLogger(SchemaServiceImpl.class); private ListenerRegistry listeners; @@ -61,7 +61,7 @@ AutoCloseable { private BundleTracker bundleTracker; private final YangStoreCache cache = new YangStoreCache(); - private ServiceTracker listenerTracker; + private ServiceTracker listenerTracker; public ListenerRegistry getListeners() { return listeners; @@ -93,7 +93,7 @@ AutoCloseable { if (listeners == null) { listeners = new ListenerRegistry<>(); } - + listenerTracker = new ServiceTracker<>(context, SchemaServiceListener.class, this); bundleTracker = new BundleTracker(context, BundleEvent.RESOLVED | BundleEvent.UNRESOLVED, scanner); bundleTracker.open(); @@ -132,12 +132,11 @@ AutoCloseable { throw new UnsupportedOperationException(); } - @Override public ListenerRegistration registerSchemaServiceListener(SchemaServiceListener listener) { return listeners.register(listener); } - + @Override public void close() throws Exception { bundleTracker.close(); @@ -196,15 +195,15 @@ AutoCloseable { private void updateCache(SchemaContext snapshot) { cache.cacheYangStore(consistentBundlesToYangURLs, snapshot); - + Object[] services = listenerTracker.getServices(); - if(services != null) { - for(Object rawListener : services) { + if (services != null) { + for (Object rawListener : services) { SchemaServiceListener listener = (SchemaServiceListener) rawListener; try { listener.onGlobalContextUpdated(snapshot); } catch (Exception e) { - logger.error("Exception occured during invoking listener",e); + logger.error("Exception occured during invoking listener", e); } } } @@ -212,7 +211,7 @@ AutoCloseable { try { listener.getInstance().onGlobalContextUpdated(snapshot); } catch (Exception e) { - logger.error("Exception occured during invoking listener",e); + logger.error("Exception occured during invoking listener", e); } } } @@ -243,7 +242,7 @@ AutoCloseable { proposedNewState.putAll(inconsistentBundlesToYangURLs); proposedNewState.putAll(bundle, addedURLs); boolean adding = true; - + if (tryToUpdateState(addedURLs, proposedNewState, adding) == false) { inconsistentBundlesToYangURLs.putAll(bundle, addedURLs); } @@ -301,23 +300,23 @@ AutoCloseable { this.cachedContextSnapshot = ctx; } } - + @Override public SchemaServiceListener addingService(ServiceReference reference) { - + SchemaServiceListener listener = context.getService(reference); SchemaContext _ctxContext = getGlobalContext(); - if(getContext() != null) { + if (getContext() != null) { listener.onGlobalContextUpdated(_ctxContext); } return listener; } - + @Override public void modifiedService(ServiceReference reference, SchemaServiceListener service) { // NOOP } - + @Override public void removedService(ServiceReference reference, SchemaServiceListener service) { context.ungetService(reference); diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataStoreStatsWrapper.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataStoreStatsWrapper.java index 9116d50d9c..0d2d1c8751 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataStoreStatsWrapper.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataStoreStatsWrapper.java @@ -52,7 +52,7 @@ public class DataStoreStatsWrapper implements Delegator, DataStore { } finally { final long endTime = System.nanoTime(); final long runTime = endTime - startTime; - cfgReadTimeTotal.addAndGet(runTime); + operReadTimeTotal.addAndGet(runTime); } } @@ -98,40 +98,40 @@ public class DataStoreStatsWrapper implements Delegator, DataStore { return requestCommitCount.get(); } - public final long getConfigurationReadTotalTime() { - return cfgReadTimeTotal.get(); + public final double getConfigurationReadTotalTime() { + return cfgReadTimeTotal.get() / 1000.0d; } - public final long getOperationalReadTotalTime() { - return operReadTimeTotal.get(); + public final double getOperationalReadTotalTime() { + return operReadTimeTotal.get() / 1000.0d; } - public final long getRequestCommitTotalTime() { - return requestCommitTimeTotal.get(); + public final double getRequestCommitTotalTime() { + return requestCommitTimeTotal.get() / 1000.0d; } - public final long getConfigurationReadAverageTime() { + public final double getConfigurationReadAverageTime() { long readCount = cfgReadCount.get(); if(readCount == 0) { return 0; } - return cfgReadTimeTotal.get() / readCount; + return getConfigurationReadTotalTime() / readCount; } - public final long getOperationalReadAverageTime() { + public final double getOperationalReadAverageTime() { long readCount = operReadCount.get(); if(readCount == 0) { return 0; } - return operReadTimeTotal.get() / readCount; + return getOperationalReadTotalTime() / readCount; } - public final long getRequestCommitAverageTime() { + public final double getRequestCommitAverageTime() { long count = requestCommitCount.get(); if(count == 0) { return 0; } - return requestCommitTimeTotal.get() / count; + return getRequestCommitTotalTime() / count; } } diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/RpcRouterImpl.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/RpcRouterImpl.xtend index d67697f849..d8680ce3b4 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/RpcRouterImpl.xtend +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/RpcRouterImpl.xtend @@ -12,9 +12,9 @@ import java.util.concurrent.ConcurrentHashMap import java.util.Set import java.util.Collections import org.opendaylight.yangtools.concepts.AbstractObjectRegistration -import org.opendaylight.controller.md.sal.common.impl.ListenerRegistry import org.opendaylight.controller.sal.core.api.RpcRegistrationListener import org.slf4j.LoggerFactory +import org.opendaylight.yangtools.concepts.util.ListenerRegistry class RpcRouterImpl implements RpcRouter, Identifiable { diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareDataMerger.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareDataMerger.xtend deleted file mode 100644 index 8cdbf9225d..0000000000 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareDataMerger.xtend +++ /dev/null @@ -1,13 +0,0 @@ -package org.opendaylight.controller.sal.dom.broker.impl - -import org.opendaylight.yangtools.yang.model.api.SchemaContext -import org.opendaylight.yangtools.yang.data.api.CompositeNode - -class SchemaAwareDataMerger { - - private SchemaContext schema; - - - - -} \ No newline at end of file diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareDataStoreAdapter.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareDataStoreAdapter.java index 1f908140b0..4f4fadcc44 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareDataStoreAdapter.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareDataStoreAdapter.java @@ -5,23 +5,35 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicLong; +import org.opendaylight.controller.md.sal.common.api.TransactionStatus; import org.opendaylight.controller.md.sal.common.api.data.DataModification; import org.opendaylight.controller.md.sal.common.api.data.DataReader; +import org.opendaylight.controller.md.sal.common.impl.AbstractDataModification; import org.opendaylight.controller.md.sal.common.impl.util.AbstractLockableDelegator; import org.opendaylight.controller.sal.core.api.data.DataStore; import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener; import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.data.api.CompositeNode; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.data.api.Node; import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl; +import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.Module; import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.model.api.SchemaNode; +import org.opendaylight.yangtools.yang.util.YangDataOperations; +import org.opendaylight.yangtools.yang.util.YangSchemaUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -29,6 +41,7 @@ import com.google.common.base.Predicate; import com.google.common.collect.FluentIterable; import static com.google.common.base.Preconditions.*; +import org.opendaylight.yangtools.yang.util.YangDataOperations; public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator implements // DataStore, // @@ -39,7 +52,6 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator reader = new MergeFirstLevelReader(); @Override @@ -100,7 +112,8 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator requestCommit( DataModification modification) { validateAgainstSchema(modification); - DataModification cleanedUp = prepareMergedTransaction(modification); + NormalizedDataModification cleanedUp = prepareMergedTransaction(modification); + cleanedUp.status = TransactionStatus.SUBMITED; return retrieveDelegate().requestCommit(cleanedUp); } @@ -138,10 +151,39 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator prepareMergedTransaction( + protected CompositeNode mergeData(InstanceIdentifier path, CompositeNode stored, CompositeNode modified, boolean config) { + long startTime = System.nanoTime(); + try { + DataSchemaNode node = schemaNodeFor(path); + return YangDataOperations.merge(node,stored,modified,config); + } finally { + //System.out.println("Merge time: " + ((System.nanoTime() - startTime) / 1000.0d)); + } + } + + + private DataSchemaNode schemaNodeFor(InstanceIdentifier path) { + checkState(schema != null,"YANG Schema is not available"); + return YangSchemaUtils.getSchemaNode(schema, path); + } + + private NormalizedDataModification prepareMergedTransaction( DataModification original) { // NOOP for now - return original; + NormalizedDataModification normalized = new NormalizedDataModification(original); + for (Entry entry : original.getUpdatedConfigurationData().entrySet()) { + normalized.putConfigurationData(entry.getKey(), entry.getValue()); + } + for (Entry entry : original.getUpdatedOperationalData().entrySet()) { + normalized.putOperationalData(entry.getKey(), entry.getValue()); + } + for (InstanceIdentifier entry : original.getRemovedConfigurationData()) { + normalized.removeConfigurationData(entry); + } + for(InstanceIdentifier entry : original.getRemovedOperationalData()) { + normalized.removeOperationalData(entry); + } + return normalized; } private final Comparator> preparationComparator = new Comparator>() { @@ -242,4 +284,44 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator { + + private Object identifier; + private TransactionStatus status; + + public NormalizedDataModification(DataModification original) { + super(getDelegate()); + identifier = original; + status = TransactionStatus.NEW; + } + + @Override + public Object getIdentifier() { + return this.identifier; + } + + @Override + public TransactionStatus getStatus() { + return status; + } + + @Override + public Future> commit() { + throw new UnsupportedOperationException("Commit should not be invoked on this"); + } + + @Override + protected CompositeNode mergeConfigurationData(InstanceIdentifier path,CompositeNode stored, CompositeNode modified) { + return mergeData(path,stored, modified,true); + } + + @Override + protected CompositeNode mergeOperationalData(InstanceIdentifier path,CompositeNode stored, CompositeNode modified) { + // TODO Auto-generated method stub + return mergeData(path,stored,modified,false); + } + + } + } diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/yangtools/yang/util/YangDataOperations.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/yangtools/yang/util/YangDataOperations.xtend new file mode 100644 index 0000000000..f69e00aa3a --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/yangtools/yang/util/YangDataOperations.xtend @@ -0,0 +1,116 @@ +package org.opendaylight.yangtools.yang.util + +import org.opendaylight.yangtools.yang.data.api.CompositeNode +import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode +import static com.google.common.base.Preconditions.*; +import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl +import java.util.ArrayList + +import org.opendaylight.yangtools.yang.model.api.DataNodeContainer +import org.opendaylight.yangtools.yang.model.api.ListSchemaNode +import org.opendaylight.yangtools.yang.data.api.Node +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode +import java.util.List +import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode +import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode +import java.util.Collections +import static extension org.opendaylight.yangtools.yang.util.YangDataUtils.*; +import java.util.HashSet +import org.opendaylight.yangtools.yang.common.QName + +class YangDataOperations { + + static def CompositeNode merge(DataSchemaNode schema, CompositeNode stored, CompositeNode modified, boolean config) { + checkConfigurational(schema, config); + if (stored === null) { + return modified; + } + + if (schema instanceof ListSchemaNode || schema instanceof ContainerSchemaNode) { + return mergeContainer(schema as DataNodeContainer, stored, modified, config); + } + throw new IllegalArgumentException("Supplied node is not data node container."); + } + + private def static checkConfigurational(DataSchemaNode node, boolean config) { + if (config) { + checkArgument(node.configuration, "Supplied composite node is not configurational."); + } + } + + private static dispatch def Iterable> mergeMultiple(LeafSchemaNode node, List> original, + List> modified, boolean configurational) { + checkArgument(original.size === 1); + checkArgument(modified.size === 1); + checkConfigurational(node, configurational); + return modified; + } + + private static dispatch def Iterable> mergeMultiple(LeafListSchemaNode node, + List> original, List> modified, boolean configurational) { + return modified; + } + + private static dispatch def Iterable> mergeMultiple(ContainerSchemaNode node, + List> original, List> modified, boolean configurational) { + checkArgument(original.size === 1); + checkArgument(modified.size === 1); + return Collections.singletonList( + merge(node, original.get(0) as CompositeNode, modified.get(0) as CompositeNode, configurational)); + } + + private static dispatch def Iterable> mergeMultiple(ListSchemaNode node, List> original, + List> modified, boolean configurational) { + checkConfigurational(node,configurational); + if(node.keyDefinition === null || node.keyDefinition.empty) { + return modified; + } + val originalMap = (original as List).toIndexMap(node.keyDefinition); + val modifiedMap = (modified as List).toIndexMap(node.keyDefinition); + + val List> mergedNodes = new ArrayList(original.size + modified.size); + for(entry : modifiedMap.entrySet) { + val originalEntry = originalMap.get(entry.key); + if(originalEntry != null) { + originalMap.remove(entry.key); + mergedNodes.add(merge(node,originalEntry,entry.value,configurational)); + + } + } + mergedNodes.addAll(originalMap.values); + return mergedNodes; + } + + static private def CompositeNode mergeContainer(DataNodeContainer schema, CompositeNode stored, + CompositeNode modified, boolean config) { + if (stored == null) { + return modified; + } + checkNotNull(stored) + checkNotNull(modified) + checkArgument(stored.nodeType == modified.nodeType); + + val mergedChildNodes = new ArrayList>(stored.children.size + modified.children.size); + + val toProcess = new HashSet(stored.keySet); + toProcess.addAll(modified.keySet); + + for (qname : toProcess) { + val schemaChild = schema.getDataChildByName(qname); + val storedChildren = stored.get(qname); + val modifiedChildren = modified.get(qname); + + if (modifiedChildren !== null && !modifiedChildren.empty) { + if (storedChildren === null || storedChildren.empty || schemaChild === null) { + mergedChildNodes.addAll(modifiedChildren); + } else { + mergedChildNodes.addAll(mergeMultiple(schemaChild, storedChildren, modifiedChildren, config)); + } + } else if (storedChildren !== null && !storedChildren.empty) { + mergedChildNodes.addAll(storedChildren); + } + } + return new CompositeNodeTOImpl(stored.nodeType, null, mergedChildNodes); + } + +} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/yangtools/yang/util/YangDataUtils.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/yangtools/yang/util/YangDataUtils.java new file mode 100644 index 0000000000..687e4d9bf0 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/yangtools/yang/util/YangDataUtils.java @@ -0,0 +1,44 @@ +package org.opendaylight.yangtools.yang.util; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; +import org.opendaylight.yangtools.yang.data.api.SimpleNode; + +import static com.google.common.base.Preconditions.*; + +public class YangDataUtils { + + public YangDataUtils() { + // TODO Auto-generated constructor stub + } + + + + public static Map,CompositeNode> toIndexMap(List nodes,List keys) { + ConcurrentHashMap,CompositeNode> ret = new ConcurrentHashMap<>(); + for(CompositeNode node : nodes) { + Map key = getKeyMap(node,keys); + ret.put(key, node); + } + return ret; + } + + + + public static Map getKeyMap(CompositeNode node, List keys) { + Map map = new HashMap<>(); + for(QName key : keys) { + SimpleNode keyNode = node.getFirstSimpleByName(QName.create(node.getNodeType(), key.getLocalName())); + checkArgument(keyNode != null,"Node must contains all keys."); + Object value = keyNode.getValue(); + map.put(key, value); + + } + return map; + } +} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/yangtools/yang/util/YangSchemaUtils.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/yangtools/yang/util/YangSchemaUtils.java new file mode 100644 index 0000000000..44ee2a31b0 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/yangtools/yang/util/YangSchemaUtils.java @@ -0,0 +1,239 @@ +package org.opendaylight.yangtools.yang.util; + + +import java.util.Iterator; +import java.util.List; +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.InstanceIdentifier.PathArgument; +import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; +import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode; +import org.opendaylight.yangtools.yang.model.api.ChoiceNode; +import org.opendaylight.yangtools.yang.model.api.ConstraintDefinition; +import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; +import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.GroupingDefinition; +import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode; +import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.model.api.SchemaPath; +import org.opendaylight.yangtools.yang.model.api.Status; +import org.opendaylight.yangtools.yang.model.api.TypeDefinition; +import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode; +import org.opendaylight.yangtools.yang.model.api.UsesNode; +import org.opendaylight.yangtools.yang.model.api.YangNode; + +import static com.google.common.base.Preconditions.*; + +import com.google.common.base.Function; +import com.google.common.collect.FluentIterable; + +public class YangSchemaUtils { + + private static final Function QNAME_FROM_PATH_ARGUMENT = new Function(){ + + @Override + public QName apply(PathArgument input) { + if(input == null) { + return null; + } + return input.getNodeType(); + } + }; + + private YangSchemaUtils() { + throw new UnsupportedOperationException("Utility class."); + } + + + public static DataSchemaNode getSchemaNode(SchemaContext schema,InstanceIdentifier path) { + checkArgument(schema != null,"YANG Schema must not be null."); + checkArgument(path != null,"Path must not be null."); + return getSchemaNode(schema, FluentIterable.from(path.getPath()).transform(QNAME_FROM_PATH_ARGUMENT)); + } + + public static DataSchemaNode getSchemaNode(SchemaContext schema,Iterable path) { + checkArgument(schema != null,"YANG Schema must not be null."); + checkArgument(path != null,"Path must not be null."); + if(!path.iterator().hasNext()){ + return toRootDataNode(schema); + } + + QName firstNode = path.iterator().next(); + DataNodeContainer previous = schema.findModuleByNamespaceAndRevision(firstNode.getNamespace(), + firstNode.getRevision()); + Iterator iterator = path.iterator(); + + while (iterator.hasNext()) { + checkArgument(previous!= null, "Supplied path does not resolve into valid schema node."); + QName arg = iterator.next(); + DataSchemaNode currentNode = previous.getDataChildByName(arg); + if (currentNode == null && previous instanceof DataNodeContainer) { + currentNode = searchInChoices(previous, arg); + } + if (currentNode instanceof DataNodeContainer) { + previous = (DataNodeContainer) currentNode; + } else if (currentNode instanceof LeafSchemaNode || currentNode instanceof LeafListSchemaNode) { + checkArgument(!iterator.hasNext(), "Path nests inside leaf node, which is not allowed."); + return currentNode; + } + } + return (DataSchemaNode) previous; + } + + + private static DataSchemaNode searchInChoices(DataNodeContainer node, QName arg) { + Set children = node.getChildNodes(); + for (DataSchemaNode child : children) { + if (child instanceof ChoiceNode) { + ChoiceNode choiceNode = (ChoiceNode) child; + DataSchemaNode potential = searchInCases(choiceNode, arg); + if (potential != null) { + return potential; + } + } + } + return null; + } + + private static DataSchemaNode searchInCases(ChoiceNode choiceNode, QName arg) { + Set cases = choiceNode.getCases(); + for (ChoiceCaseNode caseNode : cases) { + DataSchemaNode node = caseNode.getDataChildByName(arg); + if (node != null) { + return node; + } + } + return null; + } + + private static ContainerSchemaNode toRootDataNode(SchemaContext schema) { + return new NetconfDataRootNode(schema); + } + + private static final class NetconfDataRootNode implements ContainerSchemaNode { + + public NetconfDataRootNode(SchemaContext schema) { + // TODO Auto-generated constructor stub + } + + @Override + public YangNode getParent() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Set> getTypeDefinitions() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Set getChildNodes() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Set getGroupings() { + // TODO Auto-generated method stub + return null; + } + + @Override + public DataSchemaNode getDataChildByName(QName name) { + // TODO Auto-generated method stub + return null; + } + + @Override + public DataSchemaNode getDataChildByName(String name) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Set getUses() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Set getAvailableAugmentations() { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isAugmenting() { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isAddedByUses() { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isConfiguration() { + // TODO Auto-generated method stub + return false; + } + + @Override + public ConstraintDefinition getConstraints() { + // TODO Auto-generated method stub + return null; + } + + @Override + public QName getQName() { + // TODO Auto-generated method stub + return null; + } + + @Override + public SchemaPath getPath() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getDescription() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getReference() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Status getStatus() { + // TODO Auto-generated method stub + return null; + } + + @Override + public List getUnknownSchemaNodes() { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isPresenceContainer() { + // TODO Auto-generated method stub + return false; + } + + } + +} -- 2.36.6