From 58dacb97a466883894b752422781311bfaac5890 Mon Sep 17 00:00:00 2001 From: Vaclav Demcak Date: Mon, 24 Feb 2014 22:52:44 +0100 Subject: [PATCH] fix bug 431 Change-Id: Ifd972d7e8acfbc8ed2b9d64391f156b09617d304 Signed-off-by: Vaclav Demcak --- .../test/bugfix/WriteParentReadChildTest.java | 113 ++++++++++++++++++ .../impl/SchemaAwareDataStoreAdapter.java | 95 ++++++++++++++- 2 files changed, 205 insertions(+), 3 deletions(-) create mode 100644 opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/WriteParentReadChildTest.java diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/WriteParentReadChildTest.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/WriteParentReadChildTest.java new file mode 100644 index 0000000000..35b4e92db4 --- /dev/null +++ b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/WriteParentReadChildTest.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.sal.binding.test.bugfix; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.opendaylight.controller.md.sal.common.api.TransactionStatus; +import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction; +import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.common.RpcResult; + +import com.google.common.collect.ImmutableList; + +public class WriteParentReadChildTest extends AbstractDataServiceTest { + + private static final String FLOW_ID = "1234"; + private static final short TABLE_ID = (short) 0; + private static final String NODE_ID = "node:1"; + + private static final NodeKey NODE_KEY = new NodeKey(new NodeId(NODE_ID)); + private static final FlowKey FLOW_KEY = new FlowKey(new FlowId(FLOW_ID)); + private static final TableKey TABLE_KEY = new TableKey(TABLE_ID); + + private static final InstanceIdentifier NODE_INSTANCE_ID_BA = InstanceIdentifier.builder(Nodes.class) // + .child(Node.class, NODE_KEY).toInstance(); + + private static final InstanceIdentifier TABLE_INSTANCE_ID_BA = // + InstanceIdentifier.builder(NODE_INSTANCE_ID_BA) // + .augmentation(FlowCapableNode.class).child(Table.class, TABLE_KEY).build(); + + private static final InstanceIdentifier FLOW_INSTANCE_ID_BA = // + InstanceIdentifier.builder(TABLE_INSTANCE_ID_BA) // + .child(Flow.class, FLOW_KEY) // + .toInstance(); + /** + * + * The scenario tests writing parent node, which also contains child items + * and then reading child directly, by specifying path to the child. + * + * Expected behaviour is child is returned. + * + * @throws Exception + */ + @Test + public void writeTableReadFlow() throws Exception { + + DataModificationTransaction modification = baDataService.beginTransaction(); + + Flow flow = new FlowBuilder() // + .setKey(FLOW_KEY) // + .setMatch(new MatchBuilder() // + .setVlanMatch(new VlanMatchBuilder() // + .setVlanId(new VlanIdBuilder() // + .setVlanId(new VlanId(10)) // + .build()) // + .build()) // + .build()) // + .setInstructions(new InstructionsBuilder() // + .setInstruction(ImmutableList.builder() // + .build()) // + .build()) // + .build(); + + Table table = new TableBuilder() + .setKey(TABLE_KEY) + .setFlow(ImmutableList.of(flow)) + .build(); + + modification.putConfigurationData(TABLE_INSTANCE_ID_BA, table); + RpcResult ret = modification.commit().get(); + assertNotNull(ret); + assertEquals(TransactionStatus.COMMITED, ret.getResult()); + + DataObject readedTable = baDataService.readConfigurationData(TABLE_INSTANCE_ID_BA); + assertNotNull("Readed table should not be nul.", readedTable); + assertTrue(readedTable instanceof Table); + + DataObject readedFlow = baDataService.readConfigurationData(FLOW_INSTANCE_ID_BA); + assertNotNull("Readed flow should not be null.",readedFlow); + assertTrue(readedFlow instanceof Flow); + assertEquals(flow, readedFlow); + + } +} \ 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 602afd7c0c..abf822087e 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 @@ -9,11 +9,19 @@ package org.opendaylight.controller.sal.dom.broker.impl; import static com.google.common.base.Preconditions.checkState; +import java.io.Console; import java.util.ArrayList; import java.util.Comparator; +import java.util.HashMap; +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 javax.activation.UnsupportedDataTypeException; + 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; @@ -26,15 +34,23 @@ 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.InstanceIdentifierBuilder; import org.opendaylight.yangtools.yang.data.api.Node; +import org.opendaylight.yangtools.yang.data.api.SimpleNode; import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl; +import org.opendaylight.yangtools.yang.model.api.ConstraintDefinition; +import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang.model.api.SchemaContextListener; import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener; +import org.opendaylight.yangtools.yang.model.api.TypeDefinition; +import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.common.base.Optional; import com.google.common.base.Predicate; import com.google.common.collect.FluentIterable; import com.google.common.collect.ImmutableSet; @@ -169,10 +185,10 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator original) { NormalizedDataModification normalized = new NormalizedDataModification(original); for (Entry entry : original.getUpdatedConfigurationData().entrySet()) { - normalized.putConfigurationData(entry.getKey(), entry.getValue()); + normalized.putDeepConfigurationData(entry.getKey(), entry.getValue()); } for (Entry entry : original.getUpdatedOperationalData().entrySet()) { - normalized.putOperationalData(entry.getKey(), entry.getValue()); + normalized.putDeepOperationalData(entry.getKey(), entry.getValue()); } for (InstanceIdentifier entry : original.getRemovedConfigurationData()) { normalized.deepRemoveConfigurationData(entry); @@ -310,6 +326,8 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator { + private final String CONFIGURATIONAL_DATA_STORE_MARKER = "configurational"; + private final String OPERATIONAL_DATA_STORE_MARKER = "operational"; private final Object identifier; private TransactionStatus status; @@ -342,6 +360,14 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator child : entryData.getChildren()) { + InstanceIdentifier subEntryId = InstanceIdentifier.builder(entryKey).node(child.getNodeType()).toInstance(); + if (child instanceof CompositeNode) { + DataSchemaNode subSchema = schemaNodeFor(subEntryId); + CompositeNode compNode = (CompositeNode) child; + InstanceIdentifier instanceId = null; + + if (subSchema instanceof ListSchemaNode) { + ListSchemaNode listSubSchema = (ListSchemaNode) subSchema; + Map mapOfSubValues = this.getValuesFromListSchema(listSubSchema, (CompositeNode) child); + if (mapOfSubValues != null) { + instanceId = InstanceIdentifier.builder(entryKey).nodeWithKey(listSubSchema.getQName(), mapOfSubValues).toInstance(); + } + } + else if (subSchema instanceof ContainerSchemaNode) { + ContainerSchemaNode containerSchema = (ContainerSchemaNode) subSchema; + instanceId = InstanceIdentifier.builder(entryKey).node(subSchema.getQName()).toInstance(); + } + if (instanceId != null) { + this.putCompositeNodeData(instanceId, compNode, dataStoreIdentifier); + } + } + } + } + + private Map getValuesFromListSchema (ListSchemaNode listSchema, CompositeNode entryData) { + List keyDef = listSchema.getKeyDefinition(); + if (keyDef != null && ! keyDef.isEmpty()) { + Map map = new HashMap(); + for (QName key : keyDef) { + List> data = entryData.get(key); + if (data != null && ! data.isEmpty()) { + for (Node nodeData : data) { + if (nodeData instanceof SimpleNode) { + map.put(key, data.get(0).getValue()); + } + } + } + } + return map; + } + return null; + } + } } -- 2.36.6