</dependency>
</dependencies>
</plugin>
-
+
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
<version>${osgi.core.version}</version>
- <scope>provided</scope>
+ <scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<groupId>org.eclipse.xtend</groupId>
<artifactId>org.eclipse.xtend.lib</artifactId>
</dependency>
- <dependency>
- <groupId>org.eclipse.xtend</groupId>
- <artifactId>org.eclipse.xtend.standalone</artifactId>
- <version>2.4.3</version>
- <scope>runtime</scope>
- </dependency>
+ <dependency>
+ <groupId>org.eclipse.xtend</groupId>
+ <artifactId>org.eclipse.xtend.standalone</artifactId>
+ <version>2.4.3</version>
+ <scope>runtime</scope>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-binding-config</artifactId>
<version>${slf4j.version}</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.model</groupId>
+ <artifactId>model-flow-statistics</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
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 {
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);
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 {
Identifier<? extends Identifiable<?>> identifier = (Identifier<? extends Identifiable<?>>) key;
return new IdentifiableItem(identifiableType,identifier);
}
-
}
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;
@Override
public void onValueCodecCreated(Class<?> valueClass, Class<?> valueCodec) {
- // TODO Auto-generated method stub
-
}
@Override
public void onCaseCodecCreated(Class<?> choiceClass,
Class<? extends BindingCodec<Map<QName, Object>, Object>> choiceCodec) {
- // TODO Auto-generated method stub
-
}
@Override
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 {
if (transformer !== null) {
return transformer;
}
- return withClassLoaderAndLock(cls.classLoader,lock) [|
+ return withClassLoaderAndLock(cls.classLoader, lock) [ |
val valueTransformer = generateValueTransformer(cls, type);
return valueTransformer;
]
private def generateKeyTransformerFor(Class<? extends Object> 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) [
}
«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;
}
'''
private def Class<? extends BindingCodec<Object, Object>> 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) [
«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;
}
'''
private def dispatch Class<? extends BindingCodec<Map<QName, Object>, 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)
private def Class<? extends BindingCodec<Map<QName, Object>, 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)
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();
}
'''
private def dispatch Class<? extends BindingCodec<Map<QName, Object>, 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");
private def deserializeNodeContainerBodyImpl(GeneratedType type, HashMap<String, Type> 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;
//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);
+ }
}
}
'''
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);
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();
_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")»;
_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»);
}
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<? extends BindingCodec<Map<QName, Object>, Object>> generateValueTransformer(
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)
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 = '''
*/
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;
«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);
}
«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);
}
«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);
}
}
'''
- private def transformDataContainerBody(Type type,Map<String, Type> properties, DataNodeContainer node) {
+ private def transformDataContainerBody(Type type, Map<String, Type> 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);
'''
def Entry<String, Type> getFor(Map<String, Type> 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) {
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();
public class CommitHandlersTransactions {
- private static class AllwaysSuccessfulTransaction<P,D> implements DataCommitTransaction<P, D> {
+ private static class AllwaysSuccessfulTransaction<P extends Path<P>,D> implements DataCommitTransaction<P, D> {
private final DataModification<P, D> modification;
--- /dev/null
+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;
+ }
+}
protected ListeningExecutorService executor;
protected BindingIndependentDataServiceConnector connectorServiceImpl;
protected HashMapDataStore rawDataStore;
- private SchemaAwareDataStoreAdapter schemaAwareDataStore;
+ protected SchemaAwareDataStoreAdapter schemaAwareDataStore;
private DataStoreStatsWrapper dataStoreStats;
protected DataStore dataStore;
@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());
+
import org.junit.Test;
import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
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;
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));
}
flow.setNode(NODE_REF);
InstructionsBuilder instructions = new InstructionsBuilder();
InstructionBuilder instruction = new InstructionBuilder();
+
+ instruction.setOrder(10);
ApplyActionsBuilder applyActions = new ApplyActionsBuilder();
List<Action> 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 );
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<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev130819.flow.Action> 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);
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.*;
return transaction.commit();
}
});
- mappingServiceImpl.onGlobalContextUpdated(getContext(getAllModelFilenames()));
+ SchemaContext ctx = getContext(getAllModelFilenames());
+ schemaAwareDataStore.onGlobalContextUpdated(ctx);
+ mappingServiceImpl.onGlobalContextUpdated(ctx);
RpcResult<TransactionStatus> result = future.get().get();
assertEquals(TransactionStatus.COMMITED, result.getResult());
testAddingNodeConnector();
-
-
-
testNodeRemove();
flow.setNode(NODE_REF);
InstructionsBuilder instructions = new InstructionsBuilder();
InstructionBuilder instruction = new InstructionBuilder();
+ instruction.setOrder(10);
ApplyActionsBuilder applyActions = new ApplyActionsBuilder();
List<Action> 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 );
<groupId>org.eclipse.xtend</groupId>
<artifactId>org.eclipse.xtend.lib</artifactId>
</dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
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<P /* extends Path<P> */, D> implements DataModification<P, D> {
+public abstract class AbstractDataModification<P extends Path<P>, D> implements DataModification<P, D> {
private final ConcurrentMap<P, D> operationalOriginal;
private final ConcurrentMap<P, D> configurationOriginal;
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);
}
@Override
public final void removeOperationalData(P path) {
checkMutable();
- hasOperationalOriginal(path);
+ getOperationalOriginal(path);
operationalUpdate.remove(path);
operationalRemove.put(path, path);
}
@Override
public final void removeConfigurationData(P path) {
checkMutable();
- hasConfigurationOriginal(path);
+ getConfigurationOriginal(path);
configurationUpdate.remove(path);
configurationRemove.put(path, path);
}
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;
}
}
* @param <P>
* @param <D>
*/
-public abstract class AbstractDataReadRouter<P extends Path<?>, D> implements DataReader<P, D> {
+public abstract class AbstractDataReadRouter<P extends Path<P>, D> implements DataReader<P, D> {
Multimap<P, DataReaderRegistration<P, D>> configReaders = HashMultimap.create();
Multimap<P, DataReaderRegistration<P, D>> operationalReaders = HashMultimap.create();
@Override
public boolean apply(Entry<P, DataReaderRegistration<P, D>> 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<P extends Path<?>, D> extends DataReaderRegistration<P, D> {
+ @SuppressWarnings("hiding")
+ private class ConfigurationDataReaderRegistration<P extends Path<P>, D> extends DataReaderRegistration<P, D> {
public ConfigurationDataReaderRegistration(P key, DataReader<P, D> instance) {
super(key, instance);
}
}
- private class OperationalDataReaderRegistration<P extends Path<?>, D> extends DataReaderRegistration<P, D> {
+ @SuppressWarnings("hiding")
+ private class OperationalDataReaderRegistration<P extends Path<P>, D> extends DataReaderRegistration<P, D> {
public OperationalDataReaderRegistration(P key, DataReader<P, D> instance) {
super(key, instance);
}
}
- private abstract static class DataReaderRegistration<P extends Path<?>, D> extends
+ private abstract static class DataReaderRegistration<P extends Path<P>, D> extends
AbstractObjectRegistration<DataReader<P, D>> {
private final P key;
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
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<P extends Path<P>, D, DCL extends DataChangeListener<P, D>> implements DataModificationTransactionFactory<P, D>, //
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<P, D> implements DataChangeEvent<P, D> {
+public class DataChangeEventImpl<P extends Path<P>, D> implements DataChangeEvent<P, D>, Immutable {
private final DataChange<P, D> dataChange;
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<P,D> implements DataChangeEvent<P, D> {
+public class InitialDataChangeEventImpl<P extends Path<P>,D> implements DataChangeEvent<P, D>, Immutable {
- private final D originalOperationalTree;
- private final D originalConfigurationTree;
+ private final D updatedOperationalTree;
+ private final D updatedConfigurationTree;
+ private final Map<P,D> updatedConfigurationData;
+ private final Map<P,D> 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<P, D> updatedCfgData, Map<P, D> updatedOperData) {
+ updatedConfigurationTree = configTree;
+ updatedOperationalTree = operTree;
+ updatedConfigurationData = updatedCfgData;
+ updatedOperationalData = updatedOperData;
}
@Override
}
@Override
public Map<P, D> 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<P, D> getUpdatedOperationalData() {
- return Collections.emptyMap();
+ return updatedOperationalData;
}
<artifactId>sal-common-util</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
-
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-data-impl</artifactId>
- <version>0.5.9-SNAPSHOT</version>
- </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-common-impl</artifactId>
<artifactId>config-api</artifactId>
<version>0.2.3-SNAPSHOT</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-data-impl</artifactId>
+ <version>0.5.9-SNAPSHOT</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-parser-impl</artifactId>
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 {
wrappedStore = new SchemaAwareDataStoreAdapter();
wrappedStore.changeDelegate(store);
wrappedStore.setValidationEnabled(false);
+
+ context.registerService(SchemaServiceListener,wrappedStore,emptyProperties)
dataService.registerConfigurationReader(ROOT, wrappedStore);
dataService.registerCommitHandler(ROOT, wrappedStore);
import static com.google.common.base.Preconditions.*;
public class SchemaServiceImpl implements //
-SchemaService, //
-ServiceTrackerCustomizer<SchemaServiceListener, SchemaServiceListener>, //
-AutoCloseable {
+ SchemaService, //
+ ServiceTrackerCustomizer<SchemaServiceListener, SchemaServiceListener>, //
+ AutoCloseable {
private static final Logger logger = LoggerFactory.getLogger(SchemaServiceImpl.class);
private ListenerRegistry<SchemaServiceListener> listeners;
private BundleTracker<Object> bundleTracker;
private final YangStoreCache cache = new YangStoreCache();
- private ServiceTracker<SchemaServiceListener,SchemaServiceListener> listenerTracker;
+ private ServiceTracker<SchemaServiceListener, SchemaServiceListener> listenerTracker;
public ListenerRegistry<SchemaServiceListener> getListeners() {
return listeners;
if (listeners == null) {
listeners = new ListenerRegistry<>();
}
-
+
listenerTracker = new ServiceTracker<>(context, SchemaServiceListener.class, this);
bundleTracker = new BundleTracker<Object>(context, BundleEvent.RESOLVED | BundleEvent.UNRESOLVED, scanner);
bundleTracker.open();
throw new UnsupportedOperationException();
}
-
@Override
public ListenerRegistration<SchemaServiceListener> registerSchemaServiceListener(SchemaServiceListener listener) {
return listeners.register(listener);
}
-
+
@Override
public void close() throws Exception {
bundleTracker.close();
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);
}
}
}
try {
listener.getInstance().onGlobalContextUpdated(snapshot);
} catch (Exception e) {
- logger.error("Exception occured during invoking listener",e);
+ logger.error("Exception occured during invoking listener", e);
}
}
}
proposedNewState.putAll(inconsistentBundlesToYangURLs);
proposedNewState.putAll(bundle, addedURLs);
boolean adding = true;
-
+
if (tryToUpdateState(addedURLs, proposedNewState, adding) == false) {
inconsistentBundlesToYangURLs.putAll(bundle, addedURLs);
}
this.cachedContextSnapshot = ctx;
}
}
-
+
@Override
public SchemaServiceListener addingService(ServiceReference<SchemaServiceListener> 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<SchemaServiceListener> reference, SchemaServiceListener service) {
// NOOP
}
-
+
@Override
public void removedService(ServiceReference<SchemaServiceListener> reference, SchemaServiceListener service) {
context.ungetService(reference);
} finally {
final long endTime = System.nanoTime();
final long runTime = endTime - startTime;
- cfgReadTimeTotal.addAndGet(runTime);
+ operReadTimeTotal.addAndGet(runTime);
}
}
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;
}
}
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<String> {
+++ /dev/null
-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
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;
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<DataStore> implements //
DataStore, //
private SchemaContext schema = null;
private boolean validationEnabled = false;
- private SchemaAwareDataMerger dataMerger = null;
private DataReader<InstanceIdentifier, CompositeNode> reader = new MergeFirstLevelReader();
@Override
public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<InstanceIdentifier, CompositeNode> requestCommit(
DataModification<InstanceIdentifier, CompositeNode> modification) {
validateAgainstSchema(modification);
- DataModification<InstanceIdentifier, CompositeNode> cleanedUp = prepareMergedTransaction(modification);
+ NormalizedDataModification cleanedUp = prepareMergedTransaction(modification);
+ cleanedUp.status = TransactionStatus.SUBMITED;
return retrieveDelegate().requestCommit(cleanedUp);
}
this.schema = null;
}
- private DataModification<InstanceIdentifier, CompositeNode> 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<InstanceIdentifier, CompositeNode> original) {
// NOOP for now
- return original;
+ NormalizedDataModification normalized = new NormalizedDataModification(original);
+ for (Entry<InstanceIdentifier,CompositeNode> entry : original.getUpdatedConfigurationData().entrySet()) {
+ normalized.putConfigurationData(entry.getKey(), entry.getValue());
+ }
+ for (Entry<InstanceIdentifier,CompositeNode> 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<Entry<InstanceIdentifier, CompositeNode>> preparationComparator = new Comparator<Entry<InstanceIdentifier, CompositeNode>>() {
}
}
}
+
+ private class NormalizedDataModification extends AbstractDataModification<InstanceIdentifier, CompositeNode> {
+
+ private Object identifier;
+ private TransactionStatus status;
+
+ public NormalizedDataModification(DataModification<InstanceIdentifier, CompositeNode> original) {
+ super(getDelegate());
+ identifier = original;
+ status = TransactionStatus.NEW;
+ }
+
+ @Override
+ public Object getIdentifier() {
+ return this.identifier;
+ }
+
+ @Override
+ public TransactionStatus getStatus() {
+ return status;
+ }
+
+ @Override
+ public Future<RpcResult<TransactionStatus>> 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);
+ }
+
+ }
+
}
--- /dev/null
+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<? extends Node<?>> mergeMultiple(LeafSchemaNode node, List<Node<?>> original,
+ List<Node<?>> modified, boolean configurational) {
+ checkArgument(original.size === 1);
+ checkArgument(modified.size === 1);
+ checkConfigurational(node, configurational);
+ return modified;
+ }
+
+ private static dispatch def Iterable<? extends Node<?>> mergeMultiple(LeafListSchemaNode node,
+ List<Node<?>> original, List<Node<?>> modified, boolean configurational) {
+ return modified;
+ }
+
+ private static dispatch def Iterable<? extends Node<?>> mergeMultiple(ContainerSchemaNode node,
+ List<Node<?>> original, List<Node<?>> 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<? extends Node<?>> mergeMultiple(ListSchemaNode node, List<Node<?>> original,
+ List<Node<?>> 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<Node<?>> 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<Node<?>>(stored.children.size + modified.children.size);
+
+ val toProcess = new HashSet<QName>(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);
+ }
+
+}
--- /dev/null
+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<Map<QName,Object>,CompositeNode> toIndexMap(List<CompositeNode> nodes,List<QName> keys) {
+ ConcurrentHashMap<Map<QName,Object>,CompositeNode> ret = new ConcurrentHashMap<>();
+ for(CompositeNode node : nodes) {
+ Map<QName, Object> key = getKeyMap(node,keys);
+ ret.put(key, node);
+ }
+ return ret;
+ }
+
+
+
+ public static Map<QName,Object> getKeyMap(CompositeNode node, List<QName> keys) {
+ Map<QName,Object> 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;
+ }
+}
--- /dev/null
+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<PathArgument, QName> QNAME_FROM_PATH_ARGUMENT = new Function<PathArgument, QName>(){
+
+ @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<QName> 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<QName> 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<DataSchemaNode> 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<ChoiceCaseNode> 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<TypeDefinition<?>> getTypeDefinitions() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Set<DataSchemaNode> getChildNodes() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Set<GroupingDefinition> 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<UsesNode> getUses() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Set<AugmentationSchema> 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<UnknownSchemaNode> getUnknownSchemaNodes() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public boolean isPresenceContainer() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ }
+
+}