}
protected Map<InstanceIdentifier<?>, DataObject> toBinding(
+ InstanceIdentifier<?> path,
final Map<YangInstanceIdentifier, ? extends NormalizedNode<?, ?>> normalized) {
Map<InstanceIdentifier<?>, DataObject> newMap = new HashMap<>();
if (potential.isPresent()) {
Entry<InstanceIdentifier<? extends DataObject>, DataObject> binding = potential.get();
newMap.put(binding.getKey(), binding.getValue());
+ } else if (entry.getKey().getLastPathArgument() instanceof YangInstanceIdentifier.AugmentationIdentifier) {
+ DataObject bindingDataObject = getCodec().toBinding(path, entry.getValue());
+ if (bindingDataObject != null) {
+ newMap.put(path, bindingDataObject);
+ }
}
} catch (DeserializationException e) {
LOG.warn("Failed to transform {}, omitting it", entry, e);
}
}
- protected Set<InstanceIdentifier<?>> toBinding(
+ protected Set<InstanceIdentifier<?>> toBinding(InstanceIdentifier<?> path,
final Set<YangInstanceIdentifier> normalized) {
Set<InstanceIdentifier<?>> hashSet = new HashSet<>();
for (YangInstanceIdentifier normalizedPath : normalized) {
if (potential.isPresent()) {
InstanceIdentifier<? extends DataObject> binding = potential.get();
hashSet.add(binding);
+ } else if (normalizedPath.getLastPathArgument() instanceof YangInstanceIdentifier.AugmentationIdentifier) {
+ hashSet.add(path);
}
} catch (DeserializationException e) {
LOG.warn("Failed to transform {}, omitting it", normalizedPath, e);
@Override
public Map<InstanceIdentifier<?>, DataObject> getCreatedData() {
if (createdCache == null) {
- createdCache = Collections.unmodifiableMap(toBinding(domEvent.getCreatedData()));
+ createdCache = Collections.unmodifiableMap(toBinding(path, domEvent.getCreatedData()));
}
return createdCache;
}
@Override
public Map<InstanceIdentifier<?>, DataObject> getUpdatedData() {
if (updatedCache == null) {
- updatedCache = Collections.unmodifiableMap(toBinding(domEvent.getUpdatedData()));
+ updatedCache = Collections.unmodifiableMap(toBinding(path, domEvent.getUpdatedData()));
}
return updatedCache;
@Override
public Set<InstanceIdentifier<?>> getRemovedPaths() {
if (removedCache == null) {
- removedCache = Collections.unmodifiableSet(toBinding(domEvent.getRemovedPaths()));
+ removedCache = Collections.unmodifiableSet(toBinding(path, domEvent.getRemovedPaths()));
}
return removedCache;
}
@Override
public Map<InstanceIdentifier<?>, DataObject> getOriginalData() {
if (originalCache == null) {
- originalCache = Collections.unmodifiableMap(toBinding(domEvent.getOriginalData()));
+ originalCache = Collections.unmodifiableMap(toBinding(path, domEvent.getOriginalData()));
}
return originalCache;
--- /dev/null
+package org.opendaylight.controller.md.sal.binding.impl.test;
+
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.binding.test.AbstractDataChangeListenerTest;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeLeafOnlyUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ListViaUses;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ListViaUsesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import static org.junit.Assert.assertTrue;
+import static org.opendaylight.controller.md.sal.binding.test.AssertCollections.assertContains;
+import static org.opendaylight.controller.md.sal.binding.test.AssertCollections.assertEmpty;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.top;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.TOP_FOO_KEY;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.topLevelList;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.leafOnlyUsesAugment;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.complexUsesAugment;
+
+public class Bug1418AugmentationTest extends AbstractDataChangeListenerTest{
+ private static final InstanceIdentifier<Top> TOP = InstanceIdentifier.create(Top.class);
+ private static final InstanceIdentifier<TopLevelList> TOP_FOO = TOP.child(TopLevelList.class, TOP_FOO_KEY);
+ private static final InstanceIdentifier<TreeLeafOnlyUsesAugment> SIMPLE_AUGMENT =
+ TOP.child(TopLevelList.class, TOP_FOO_KEY).augmentation(TreeLeafOnlyUsesAugment.class);
+ private static final InstanceIdentifier<TreeComplexUsesAugment> COMPLEX_AUGMENT =
+ TOP.child(TopLevelList.class, TOP_FOO_KEY).augmentation(TreeComplexUsesAugment.class);
+ private static final ListViaUsesKey LIST_VIA_USES_KEY =
+ new ListViaUsesKey("list key");
+ private static final ListViaUsesKey LIST_VIA_USES_KEY_MOD =
+ new ListViaUsesKey("list key modified");
+
+ @Test
+ public void leafOnlyAugmentationCreatedTest() {
+ TestListener listener = createListener(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT,
+ AsyncDataBroker.DataChangeScope.SUBTREE);
+ WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP, top());
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT, leafOnlyUsesAugment("test leaf"));
+ assertCommit(writeTx.submit());
+ assertTrue(listener.hasEvent());
+ AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
+ assertContains(event.getCreatedData(), SIMPLE_AUGMENT);
+ assertEmpty(event.getUpdatedData());
+ assertEmpty(event.getOriginalData());
+ assertEmpty(event.getRemovedPaths());
+ }
+
+ @Test
+ public void leafOnlyAugmentationUpdatedTest() {
+ WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP, top());
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT, leafOnlyUsesAugment("test leaf"));
+ assertCommit(writeTx.submit());
+ TestListener listener = createListener(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT,
+ AsyncDataBroker.DataChangeScope.SUBTREE);
+ writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT, leafOnlyUsesAugment("test leaf changed"));
+ assertCommit(writeTx.submit());
+ assertTrue(listener.hasEvent());
+ AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
+ assertContains(event.getUpdatedData(), SIMPLE_AUGMENT);
+ assertContains(event.getOriginalData(), SIMPLE_AUGMENT);
+ assertEmpty(event.getCreatedData());
+ assertEmpty(event.getRemovedPaths());
+ }
+
+ @Test
+ public void leafOnlyAugmentationDeletedTest() {
+ WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP, top());
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT, leafOnlyUsesAugment("test leaf"));
+ assertCommit(writeTx.submit());
+ TestListener listener = createListener(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT,
+ AsyncDataBroker.DataChangeScope.SUBTREE);
+ writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.delete(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT);
+ assertCommit(writeTx.submit());
+ assertTrue(listener.hasEvent());
+ AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
+ assertContains(event.getRemovedPaths(), SIMPLE_AUGMENT);
+ assertContains(event.getOriginalData(), SIMPLE_AUGMENT);
+ assertEmpty(event.getCreatedData());
+ assertEmpty(event.getUpdatedData());
+ }
+
+ @Test
+ public void complexAugmentationCreatedTest() {
+ TestListener listener = createListener(LogicalDatastoreType.CONFIGURATION, COMPLEX_AUGMENT,
+ AsyncDataBroker.DataChangeScope.SUBTREE);
+ WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP, top());
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, COMPLEX_AUGMENT, complexUsesAugment(LIST_VIA_USES_KEY));
+ assertCommit(writeTx.submit());
+ assertTrue(listener.hasEvent());
+ AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
+ assertContains(event.getCreatedData(), COMPLEX_AUGMENT);
+ assertContains(event.getCreatedData(), COMPLEX_AUGMENT.child(ListViaUses.class, LIST_VIA_USES_KEY));
+ assertEmpty(event.getUpdatedData());
+ assertEmpty(event.getOriginalData());
+ assertEmpty(event.getRemovedPaths());
+ }
+
+ @Test
+ public void complexAugmentationUpdatedTest() {
+ WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP, top());
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, COMPLEX_AUGMENT, complexUsesAugment(LIST_VIA_USES_KEY));
+ assertCommit(writeTx.submit());
+ TestListener listener = createListener(LogicalDatastoreType.CONFIGURATION, COMPLEX_AUGMENT,
+ AsyncDataBroker.DataChangeScope.SUBTREE);
+ writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, COMPLEX_AUGMENT, complexUsesAugment(LIST_VIA_USES_KEY_MOD));
+ assertCommit(writeTx.submit());
+ assertTrue(listener.hasEvent());
+ AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
+ assertContains(event.getUpdatedData(), COMPLEX_AUGMENT);
+ assertContains(event.getCreatedData(), COMPLEX_AUGMENT.child(ListViaUses.class, LIST_VIA_USES_KEY_MOD));
+ assertContains(event.getRemovedPaths(), COMPLEX_AUGMENT.child(ListViaUses.class, LIST_VIA_USES_KEY));
+ assertContains(event.getOriginalData(), COMPLEX_AUGMENT);
+ assertContains(event.getOriginalData(), COMPLEX_AUGMENT.child(ListViaUses.class, LIST_VIA_USES_KEY));
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Brocade Communications Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.md.sal.common.api.data;
+
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
+
+import com.google.common.base.Function;
+
+/**
+ * A type of TransactionCommitFailedException that indicates a situation that would result in a
+ * threading deadlock. This can occur if a caller that submits a write transaction tries to perform
+ * a blocking call via one of the <code>get</code> methods on the returned ListenableFuture. Callers
+ * should process the commit result asynchronously (via Futures#addCallback) to ensure deadlock
+ * won't occur.
+ *
+ * @author Thomas Pantelis
+ */
+public class TransactionCommitDeadlockException extends TransactionCommitFailedException {
+
+ private static final long serialVersionUID = 1L;
+
+ private static final String DEADLOCK_MESSAGE =
+ "An attempt to block on a ListenableFuture via a get method from a write " +
+ "transaction submit was detected that would result in deadlock. The commit " +
+ "result must be obtained asynchronously, e.g. via Futures#addCallback, to avoid deadlock.";
+
+ public static Function<Void, Exception> DEADLOCK_EXECUTOR_FUNCTION = new Function<Void, Exception>() {
+ @Override
+ public Exception apply(Void notUsed) {
+ return new TransactionCommitDeadlockException( DEADLOCK_MESSAGE,
+ RpcResultBuilder.newError(ErrorType.APPLICATION, "lock-denied", DEADLOCK_MESSAGE));
+ }
+ };
+
+ public TransactionCommitDeadlockException(String message, final RpcError... errors) {
+ super(message, errors);
+ }
+}
import java.util.concurrent.Executors;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitDeadlockException;
import org.opendaylight.controller.md.sal.dom.broker.impl.DOMDataBrokerImpl;
import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
import org.opendaylight.controller.sal.core.spi.data.DOMStore;
+import org.opendaylight.yangtools.util.concurrent.DeadlockDetectingListeningExecutorService;
import com.google.common.collect.ImmutableMap;
import com.google.common.util.concurrent.ListeningExecutorService;
.<LogicalDatastoreType, DOMStore> builder().put(LogicalDatastoreType.OPERATIONAL, operStore)
.put(LogicalDatastoreType.CONFIGURATION, configStore).build();
- DOMDataBrokerImpl newDataBroker = new DOMDataBrokerImpl(datastores, MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor()));
+ DOMDataBrokerImpl newDataBroker = new DOMDataBrokerImpl(datastores,
+ new DeadlockDetectingListeningExecutorService(Executors.newSingleThreadExecutor(),
+ TransactionCommitDeadlockException.DEADLOCK_EXECUTOR_FUNCTION));
return newDataBroker;
}
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION;
import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.OPERATIONAL;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitDeadlockException;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener;
import org.opendaylight.controller.md.sal.dom.api.DOMDataReadTransaction;
import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
import org.opendaylight.controller.md.sal.dom.store.impl.TestModel;
import org.opendaylight.controller.sal.core.spi.data.DOMStore;
+import org.opendaylight.yangtools.util.concurrent.DeadlockDetectingListeningExecutorService;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableMap;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
private SchemaContext schemaContext;
private DOMDataBrokerImpl domBroker;
+ private ListeningExecutorService executor;
@Before
public void setupStore() {
.put(OPERATIONAL, operStore) //
.build();
- ListeningExecutorService executor = MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor());
+ executor = new DeadlockDetectingListeningExecutorService(Executors.newSingleThreadExecutor(),
+ TransactionCommitDeadlockException.DEADLOCK_EXECUTOR_FUNCTION);
domBroker = new DOMDataBrokerImpl(stores, executor);
}
- @Test
+ @After
+ public void tearDown() {
+ if( executor != null ) {
+ executor.shutdownNow();
+ }
+ }
+
+ @Test(timeout=10000)
public void testTransactionIsolation() throws InterruptedException, ExecutionException {
assertNotNull(domBroker);
assertFalse(readTxContainer.get().isPresent());
}
- @Test
+ @Test(timeout=10000)
public void testTransactionCommit() throws InterruptedException, ExecutionException {
DOMDataReadWriteTransaction writeTx = domBroker.newReadWriteTransaction();
assertTrue(afterCommitRead.isPresent());
}
+ /**
+ * Tests a simple DataChangeListener notification after a write.
+ */
+ @Test
+ public void testDataChangeListener() throws Throwable {
+
+ final NormalizedNode<?, ?> testNode = ImmutableNodes.containerNode( TestModel.TEST_QNAME );
+
+ TestDOMDataChangeListener dcListener = new TestDOMDataChangeListener();
+
+ domBroker.registerDataChangeListener( OPERATIONAL, TestModel.TEST_PATH,
+ dcListener, DataChangeScope.BASE );
+
+ final DOMDataWriteTransaction writeTx = domBroker.newWriteOnlyTransaction();
+ assertNotNull( writeTx );
+
+ writeTx.put( OPERATIONAL, TestModel.TEST_PATH, testNode );
+
+ AtomicReference<Throwable> caughtEx = submitTxAsync( writeTx );
+
+ dcListener.waitForChange();
+
+ if( caughtEx.get() != null ) {
+ throw caughtEx.get();
+ }
+
+ NormalizedNode<?, ?> actualNode = dcListener.change.getCreatedData().get( TestModel.TEST_PATH );
+ assertEquals( "Created node", testNode, actualNode );
+ }
+
+ /**
+ * Tests a DataChangeListener that does an async submit of a write Tx in its onDataChanged method.
+ * This should succeed without deadlock.
+ */
+ @Test
+ public void testDataChangeListenerDoingAsyncWriteTxSubmit() throws Throwable {
+
+ final AtomicReference<Throwable> caughtCommitEx = new AtomicReference<>();
+ final CountDownLatch commitCompletedLatch = new CountDownLatch( 1 );
+
+ TestDOMDataChangeListener dcListener = new TestDOMDataChangeListener() {
+ @Override
+ public void onDataChanged( AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change ) {
+
+ DOMDataWriteTransaction writeTx = domBroker.newWriteOnlyTransaction();
+ writeTx.put( OPERATIONAL, TestModel.TEST2_PATH,
+ ImmutableNodes.containerNode( TestModel.TEST2_QNAME ) );
+ Futures.addCallback( writeTx.submit(), new FutureCallback<Void>() {
+ @Override
+ public void onSuccess( Void result ) {
+ commitCompletedLatch.countDown();
+ }
+
+ @Override
+ public void onFailure( Throwable t ) {
+ caughtCommitEx.set( t );
+ commitCompletedLatch.countDown();
+ }
+ } );
+
+ super.onDataChanged( change );
+ }
+ };
+
+ domBroker.registerDataChangeListener( OPERATIONAL, TestModel.TEST_PATH,
+ dcListener, DataChangeScope.BASE );
+
+ final DOMDataWriteTransaction writeTx = domBroker.newWriteOnlyTransaction();
+ assertNotNull( writeTx );
+
+ writeTx.put( OPERATIONAL, TestModel.TEST_PATH, ImmutableNodes.containerNode( TestModel.TEST_QNAME ) );
+
+ AtomicReference<Throwable> caughtEx = submitTxAsync( writeTx );
+
+ dcListener.waitForChange();
+
+ if( caughtEx.get() != null ) {
+ throw caughtEx.get();
+ }
+
+ assertTrue( "Commit Future was not invoked", commitCompletedLatch.await( 5, TimeUnit.SECONDS ) );
+
+ if( caughtCommitEx.get() != null ) {
+ throw caughtCommitEx.get();
+ }
+ }
+
+ /**
+ * Tests a DataChangeListener that does a blocking submit of a write Tx in its onDataChanged method.
+ * This should throw an exception and not deadlock.
+ */
+ @Test(expected=TransactionCommitDeadlockException.class)
+ public void testDataChangeListenerDoingBlockingWriteTxSubmit() throws Throwable {
+
+ final AtomicReference<Throwable> caughtCommitEx = new AtomicReference<>();
+
+ TestDOMDataChangeListener dcListener = new TestDOMDataChangeListener() {
+ @Override
+ public void onDataChanged( AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change ) {
+ DOMDataWriteTransaction writeTx = domBroker.newWriteOnlyTransaction();
+ writeTx.put( OPERATIONAL, TestModel.TEST2_PATH,
+ ImmutableNodes.containerNode( TestModel.TEST2_QNAME ) );
+ try {
+ writeTx.submit().get();
+ } catch( ExecutionException e ) {
+ caughtCommitEx.set( e.getCause() );
+ } catch( Exception e ) {
+ caughtCommitEx.set( e );
+ }
+ finally {
+ super.onDataChanged( change );
+ }
+ }
+ };
+
+ domBroker.registerDataChangeListener( OPERATIONAL, TestModel.TEST_PATH,
+ dcListener, DataChangeScope.BASE );
+
+ final DOMDataWriteTransaction writeTx = domBroker.newWriteOnlyTransaction();
+ assertNotNull( writeTx );
+
+ writeTx.put( OPERATIONAL, TestModel.TEST_PATH, ImmutableNodes.containerNode( TestModel.TEST_QNAME ) );
+
+ AtomicReference<Throwable> caughtEx = submitTxAsync( writeTx );
+ dcListener.waitForChange();
+ if( caughtEx.get() != null ) {
+ throw caughtEx.get();
+ }
+
+ if( caughtCommitEx.get() != null ) {
+ throw caughtCommitEx.get();
+ }
+ }
+
+ AtomicReference<Throwable> submitTxAsync( final DOMDataWriteTransaction writeTx ) {
+ final AtomicReference<Throwable> caughtEx = new AtomicReference<>();
+ new Thread() {
+ @Override
+ public void run() {
+
+ try {
+ writeTx.submit();
+ } catch( Throwable e ) {
+ caughtEx.set( e );
+ }
+ }
+
+ }.start();
+
+ return caughtEx;
+ }
+
+ static class TestDOMDataChangeListener implements DOMDataChangeListener {
+
+ volatile AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change;
+ private final CountDownLatch latch = new CountDownLatch( 1 );
+
+ @Override
+ public void onDataChanged( AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change ) {
+ this.change = change;
+ latch.countDown();
+ }
+
+ void waitForChange() throws InterruptedException {
+ assertTrue( "onDataChanged was not called", latch.await( 5, TimeUnit.SECONDS ) );
+ }
+ }
}
public static final QName TEST_QNAME = QName.create("urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test", "2014-03-13",
"test");
+ public static final QName TEST2_QNAME = QName.create("urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test", "2014-03-13",
+ "test2");
public static final QName OUTER_LIST_QNAME = QName.create(TEST_QNAME, "outer-list");
public static final QName INNER_LIST_QNAME = QName.create(TEST_QNAME, "inner-list");
public static final QName OUTER_CHOICE_QNAME = QName.create(TEST_QNAME, "outer-choice");
private static final String DATASTORE_TEST_YANG = "/odl-datastore-test.yang";
public static final YangInstanceIdentifier TEST_PATH = YangInstanceIdentifier.of(TEST_QNAME);
+ public static final YangInstanceIdentifier TEST2_PATH = YangInstanceIdentifier.of(TEST2_QNAME);
public static final YangInstanceIdentifier OUTER_LIST_PATH = YangInstanceIdentifier.builder(TEST_PATH).node(OUTER_LIST_QNAME).build();
public static final QName TWO_QNAME = QName.create(TEST_QNAME,"two");
public static final QName THREE_QNAME = QName.create(TEST_QNAME,"three");
}
}
}
+
+ container test2 {
+ }
}
\ No newline at end of file
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
-import com.google.common.collect.BiMap;
-import com.google.common.collect.HashBiMap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import java.io.UnsupportedEncodingException;
private static final Splitter SLASH_SPLITTER = Splitter.on('/');
- private final BiMap<URI, String> uriToModuleName = HashBiMap.<URI, String> create();
-
- private final Map<String, URI> moduleNameToUri = uriToModuleName.inverse();
-
private final AtomicReference<Map<QName, RpcDefinition>> qnameToRpc =
new AtomicReference<>(Collections.<QName, RpcDefinition>emptyMap());
public String findModuleNameByNamespace(final URI namespace) {
this.checkPreconditions();
- String moduleName = this.uriToModuleName.get(namespace);
- if (moduleName == null) {
- final Module module = this.findModuleByNamespace(namespace);
- if (module != null) {
- moduleName = module.getName();
- this.uriToModuleName.put(namespace, moduleName);
- }
- }
-
- return moduleName;
+ final Module module = this.findModuleByNamespace(namespace);
+ return module == null ? null : module.getName();
}
public String findModuleNameByNamespace(final DOMMountPoint mountPoint, final URI namespace) {
}
public URI findNamespaceByModuleName(final String moduleName) {
- URI namespace = this.moduleNameToUri.get(moduleName);
- if (namespace == null) {
- Module module = this.findModuleByName(moduleName);
- if (module != null) {
- URI _namespace = module.getNamespace();
- namespace = _namespace;
- this.uriToModuleName.put(namespace, moduleName);
- }
- }
- return namespace;
+ final Module module = this.findModuleByName(moduleName);
+ return module == null ? null : module.getNamespace();
}
public URI findNamespaceByModuleName(final DOMMountPoint mountPoint, final String moduleName) {
return globalSchema.getModules();
}
+ private static final CharSequence toRestconfIdentifier(final SchemaContext context, final QName qname) {
+ final Module schema = context.findModuleByNamespaceAndRevision(qname.getNamespace(), qname.getRevision());
+ return schema == null ? null : schema.getName() + ':' + qname.getLocalName();
+ }
+
public CharSequence toRestconfIdentifier(final QName qname) {
this.checkPreconditions();
- String module = this.uriToModuleName.get(qname.getNamespace());
- if (module == null) {
- final Module moduleSchema = globalSchema.findModuleByNamespaceAndRevision(qname.getNamespace(),
- qname.getRevision());
- if (moduleSchema == null) {
- return null;
- }
-
- this.uriToModuleName.put(qname.getNamespace(), moduleSchema.getName());
- module = moduleSchema.getName();
- }
-
- StringBuilder builder = new StringBuilder();
- builder.append(module);
- builder.append(":");
- builder.append(qname.getLocalName());
- return builder.toString();
+ return toRestconfIdentifier(globalSchema, qname);
}
public CharSequence toRestconfIdentifier(final DOMMountPoint mountPoint, final QName qname) {
return null;
}
- SchemaContext schemaContext = mountPoint.getSchemaContext();
-
- final Module moduleSchema = schemaContext.findModuleByNamespaceAndRevision(qname.getNamespace(),
- qname.getRevision());
- if (moduleSchema == null) {
- return null;
- }
-
- StringBuilder builder = new StringBuilder();
- builder.append(moduleSchema.getName());
- builder.append(":");
- builder.append(qname.getLocalName());
- return builder.toString();
+ return toRestconfIdentifier(mountPoint.getSchemaContext(), qname);
}
public Module getRestconfModule() {
final GroupingDefinition restconfGrouping = Iterables.getFirst(filteredGroups, null);
- List<DataSchemaNode> instanceDataChildrenByName = this.findInstanceDataChildrenByName(restconfGrouping,
+ List<DataSchemaNode> instanceDataChildrenByName = findInstanceDataChildrenByName(restconfGrouping,
Draft02.RestConfModule.ERRORS_CONTAINER_SCHEMA_NODE);
return Iterables.getFirst(instanceDataChildrenByName, null);
}
Iterable<GroupingDefinition> filteredGroups = Iterables.filter(groupings, GROUPING_FILTER);
final GroupingDefinition restconfGrouping = Iterables.getFirst(filteredGroups, null);
- List<DataSchemaNode> instanceDataChildrenByName = this.findInstanceDataChildrenByName(restconfGrouping,
+ List<DataSchemaNode> instanceDataChildrenByName = findInstanceDataChildrenByName(restconfGrouping,
Draft02.RestConfModule.RESTCONF_CONTAINER_SCHEMA_NODE);
final DataSchemaNode restconfContainer = Iterables.getFirst(instanceDataChildrenByName, null);
if (Objects.equal(schemaNodeName, Draft02.RestConfModule.OPERATIONS_CONTAINER_SCHEMA_NODE)) {
- List<DataSchemaNode> instances = this.findInstanceDataChildrenByName(
+ List<DataSchemaNode> instances = findInstanceDataChildrenByName(
((DataNodeContainer) restconfContainer), Draft02.RestConfModule.OPERATIONS_CONTAINER_SCHEMA_NODE);
return Iterables.getFirst(instances, null);
} else if (Objects.equal(schemaNodeName, Draft02.RestConfModule.STREAMS_CONTAINER_SCHEMA_NODE)) {
- List<DataSchemaNode> instances = this.findInstanceDataChildrenByName(
+ List<DataSchemaNode> instances = findInstanceDataChildrenByName(
((DataNodeContainer) restconfContainer), Draft02.RestConfModule.STREAMS_CONTAINER_SCHEMA_NODE);
return Iterables.getFirst(instances, null);
} else if (Objects.equal(schemaNodeName, Draft02.RestConfModule.STREAM_LIST_SCHEMA_NODE)) {
- List<DataSchemaNode> instances = this.findInstanceDataChildrenByName(
+ List<DataSchemaNode> instances = findInstanceDataChildrenByName(
((DataNodeContainer) restconfContainer), Draft02.RestConfModule.STREAMS_CONTAINER_SCHEMA_NODE);
final DataSchemaNode modules = Iterables.getFirst(instances, null);
- instances = this.findInstanceDataChildrenByName(((DataNodeContainer) modules),
+ instances = findInstanceDataChildrenByName(((DataNodeContainer) modules),
Draft02.RestConfModule.STREAM_LIST_SCHEMA_NODE);
return Iterables.getFirst(instances, null);
} else if (Objects.equal(schemaNodeName, Draft02.RestConfModule.MODULES_CONTAINER_SCHEMA_NODE)) {
- List<DataSchemaNode> instances = this.findInstanceDataChildrenByName(
+ List<DataSchemaNode> instances = findInstanceDataChildrenByName(
((DataNodeContainer) restconfContainer), Draft02.RestConfModule.MODULES_CONTAINER_SCHEMA_NODE);
return Iterables.getFirst(instances, null);
} else if (Objects.equal(schemaNodeName, Draft02.RestConfModule.MODULE_LIST_SCHEMA_NODE)) {
- List<DataSchemaNode> instances = this.findInstanceDataChildrenByName(
+ List<DataSchemaNode> instances = findInstanceDataChildrenByName(
((DataNodeContainer) restconfContainer), Draft02.RestConfModule.MODULES_CONTAINER_SCHEMA_NODE);
final DataSchemaNode modules = Iterables.getFirst(instances, null);
- instances = this.findInstanceDataChildrenByName(((DataNodeContainer) modules),
+ instances = findInstanceDataChildrenByName(((DataNodeContainer) modules),
Draft02.RestConfModule.MODULE_LIST_SCHEMA_NODE);
return Iterables.getFirst(instances, null);
} else if (Objects.equal(schemaNodeName, Draft02.RestConfModule.STREAMS_CONTAINER_SCHEMA_NODE)) {
- List<DataSchemaNode> instances = this.findInstanceDataChildrenByName(
+ List<DataSchemaNode> instances = findInstanceDataChildrenByName(
((DataNodeContainer) restconfContainer), Draft02.RestConfModule.STREAMS_CONTAINER_SCHEMA_NODE);
return Iterables.getFirst(instances, null);
}
}
}
- targetNode = this.findInstanceDataChildByNameAndNamespace(parentNode, nodeName, module.getNamespace());
+ targetNode = findInstanceDataChildByNameAndNamespace(parentNode, nodeName, module.getNamespace());
if (targetNode == null) {
throw new RestconfDocumentedException("URI has bad format. Possible reasons:\n" + " 1. \"" + head
+ "\" was not found in parent data node.\n" + " 2. \"" + head
ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE);
}
} else {
- final List<DataSchemaNode> potentialSchemaNodes = this.findInstanceDataChildrenByName(parentNode, nodeName);
+ final List<DataSchemaNode> potentialSchemaNodes = findInstanceDataChildrenByName(parentNode, nodeName);
if (potentialSchemaNodes.size() > 1) {
final StringBuilder strBuilder = new StringBuilder();
for (final DataSchemaNode potentialNodeSchema : potentialSchemaNodes) {
return new InstanceIdWithSchemaNode(builder.toInstance(), targetNode, mountPoint);
}
- public DataSchemaNode findInstanceDataChildByNameAndNamespace(final DataNodeContainer container, final String name,
+ public static DataSchemaNode findInstanceDataChildByNameAndNamespace(final DataNodeContainer container, final String name,
final URI namespace) {
Preconditions.<URI> checkNotNull(namespace);
- final List<DataSchemaNode> potentialSchemaNodes = this.findInstanceDataChildrenByName(container, name);
+ final List<DataSchemaNode> potentialSchemaNodes = findInstanceDataChildrenByName(container, name);
Predicate<DataSchemaNode> filter = new Predicate<DataSchemaNode>() {
@Override
return Iterables.getFirst(result, null);
}
- public List<DataSchemaNode> findInstanceDataChildrenByName(final DataNodeContainer container, final String name) {
+ public static List<DataSchemaNode> findInstanceDataChildrenByName(final DataNodeContainer container, final String name) {
Preconditions.<DataNodeContainer> checkNotNull(container);
Preconditions.<String> checkNotNull(name);
List<DataSchemaNode> instantiatedDataNodeContainers = new ArrayList<DataSchemaNode>();
- this.collectInstanceDataNodeContainers(instantiatedDataNodeContainers, container, name);
+ collectInstanceDataNodeContainers(instantiatedDataNodeContainers, container, name);
return instantiatedDataNodeContainers;
}
}
};
- private void collectInstanceDataNodeContainers(final List<DataSchemaNode> potentialSchemaNodes,
+ private static void collectInstanceDataNodeContainers(final List<DataSchemaNode> potentialSchemaNodes,
final DataNodeContainer container, final String name) {
Predicate<DataSchemaNode> filter = new Predicate<DataSchemaNode>() {
// Can't combine this loop with the filter above because the filter is
// lazily-applied by Iterables.filter.
for (final DataSchemaNode potentialNode : nodes) {
- if (this.isInstantiatedDataSchema(potentialNode)) {
+ if (isInstantiatedDataSchema(potentialNode)) {
potentialSchemaNodes.add(potentialNode);
}
}
final Iterable<ChoiceCaseNode> allCases = Iterables.<ChoiceCaseNode> concat(map);
for (final ChoiceCaseNode caze : allCases) {
- this.collectInstanceDataNodeContainers(potentialSchemaNodes, caze, name);
+ collectInstanceDataNodeContainers(potentialSchemaNodes, caze, name);
}
}
- public boolean isInstantiatedDataSchema(final DataSchemaNode node) {
+ public static boolean isInstantiatedDataSchema(final DataSchemaNode node) {
return node instanceof LeafSchemaNode || node instanceof LeafListSchemaNode
|| node instanceof ContainerSchemaNode || node instanceof ListSchemaNode
|| node instanceof AnyXmlSchemaNode;
}
private CharSequence convertToRestconfIdentifier(final NodeIdentifier argument, final ContainerSchemaNode node) {
- StringBuilder builder = new StringBuilder();
- builder.append("/");
- QName nodeType = argument.getNodeType();
- builder.append(this.toRestconfIdentifier(nodeType));
- return builder.toString();
+ return "/" + this.toRestconfIdentifier(argument.getNodeType());
}
private CharSequence convertToRestconfIdentifier(final NodeIdentifierWithPredicates argument,
final Map<QName, Object> keyValues = argument.getKeyValues();
StringBuilder builder = new StringBuilder();
- builder.append("/");
+ builder.append('/');
builder.append(nodeIdentifier);
- builder.append("/");
+ builder.append('/');
List<QName> keyDefinition = node.getKeyDefinition();
boolean hasElements = false;
if (!hasElements) {
hasElements = true;
} else {
- builder.append("/");
+ builder.append('/');
}
try {
for (int i = 0; i < identities.size(); i++) {
IdentityValue identityValue = identities.get(i);
URI validNamespace = resolveValidNamespace(identityValue.getNamespace(), mountPoint);
- DataSchemaNode node = ControllerContext.getInstance().findInstanceDataChildByNameAndNamespace(
+ DataSchemaNode node = ControllerContext.findInstanceDataChildByNameAndNamespace(
parentContainer, identityValue.getValue(), validNamespace);
if (node == null) {
logger.info("'{}' node was not found in {}", identityValue, parentContainer.getChildNodes());
Map<QName, Object> predicatesMap = new HashMap<>();
for (Predicate predicate : identityValue.getPredicates()) {
validNamespace = resolveValidNamespace(predicate.getName().getNamespace(), mountPoint);
- DataSchemaNode listKey = ControllerContext.getInstance()
+ DataSchemaNode listKey = ControllerContext
.findInstanceDataChildByNameAndNamespace(listNode, predicate.getName().getValue(),
validNamespace);
predicatesMap.put(listKey.getQName(), predicate.getValue());
}
result.add(pathArgument);
if (i < identities.size() - 1) { // last element in instance-identifier can be other than
- // DataNodeContainer
+ // DataNodeContainer
if (node instanceof DataNodeContainer) {
parentContainer = (DataNodeContainer) node;
} else {
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
+
import java.net.URI;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
+
import org.apache.commons.lang3.StringUtils;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.InstanceIdentifierBuilder;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.composite.node.schema.cnsn.parser.CnSnToNormalizedNodeParserFactory;
-import org.opendaylight.yangtools.yang.data.composite.node.schema.cnsn.serializer.CnSnFromNormalizedNodeSerializerFactory;
import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
private CompositeNode toStreamCompositeNode(final String streamName, final DataSchemaNode streamSchemaNode) {
final List<Node<?>> streamNodeValues = new ArrayList<Node<?>>();
- List<DataSchemaNode> instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+ List<DataSchemaNode> instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
((DataNodeContainer) streamSchemaNode), "name");
final DataSchemaNode nameSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
streamNodeValues
- .add(NodeFactory.<String> createImmutableSimpleNode(nameSchemaNode.getQName(), null, streamName));
+ .add(NodeFactory.<String> createImmutableSimpleNode(nameSchemaNode.getQName(), null, streamName));
- instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+ instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
((DataNodeContainer) streamSchemaNode), "description");
final DataSchemaNode descriptionSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
streamNodeValues.add(NodeFactory.<String> createImmutableSimpleNode(descriptionSchemaNode.getQName(), null,
"DESCRIPTION_PLACEHOLDER"));
- instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+ instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
((DataNodeContainer) streamSchemaNode), "replay-support");
final DataSchemaNode replaySupportSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
streamNodeValues.add(NodeFactory.<Boolean> createImmutableSimpleNode(replaySupportSchemaNode.getQName(), null,
Boolean.valueOf(true)));
- instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+ instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
((DataNodeContainer) streamSchemaNode), "replay-log-creation-time");
final DataSchemaNode replayLogCreationTimeSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
streamNodeValues.add(NodeFactory.<String> createImmutableSimpleNode(replayLogCreationTimeSchemaNode.getQName(),
null, ""));
- instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+ instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
((DataNodeContainer) streamSchemaNode), "events");
final DataSchemaNode eventsSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
streamNodeValues.add(NodeFactory.<String> createImmutableSimpleNode(eventsSchemaNode.getQName(), null, ""));
private CompositeNode toModuleCompositeNode(final Module module, final DataSchemaNode moduleSchemaNode) {
final List<Node<?>> moduleNodeValues = new ArrayList<Node<?>>();
- List<DataSchemaNode> instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+ List<DataSchemaNode> instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
((DataNodeContainer) moduleSchemaNode), "name");
final DataSchemaNode nameSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
moduleNodeValues.add(NodeFactory.<String> createImmutableSimpleNode(nameSchemaNode.getQName(), null,
module.getName()));
- instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+ instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
((DataNodeContainer) moduleSchemaNode), "revision");
final DataSchemaNode revisionSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
Date _revision = module.getRevision();
moduleNodeValues.add(NodeFactory.<String> createImmutableSimpleNode(revisionSchemaNode.getQName(), null,
REVISION_FORMAT.format(_revision)));
- instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+ instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
((DataNodeContainer) moduleSchemaNode), "namespace");
final DataSchemaNode namespaceSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
moduleNodeValues.add(NodeFactory.<String> createImmutableSimpleNode(namespaceSchemaNode.getQName(), null,
module.getNamespace().toString()));
- instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+ instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
((DataNodeContainer) moduleSchemaNode), "feature");
final DataSchemaNode featureSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
for (final FeatureDefinition feature : module.getFeatures()) {
}
String payloadName = this.getName(payload);
- final DataSchemaNode schemaNode = this.controllerContext.findInstanceDataChildByNameAndNamespace(
+ final DataSchemaNode schemaNode = ControllerContext.findInstanceDataChildByNameAndNamespace(
parentSchema, payloadName, module.getNamespace());
value = this.normalizeNode(payload, schemaNode, mountPoint);
}
String payloadName = this.getName(payload);
- final DataSchemaNode schemaNode = this.controllerContext.findInstanceDataChildByNameAndNamespace(module,
+ final DataSchemaNode schemaNode = ControllerContext.findInstanceDataChildByNameAndNamespace(module,
payloadName, module.getNamespace());
final CompositeNode value = this.normalizeNode(payload, schemaNode, null);
final InstanceIdWithSchemaNode iiWithData = this.addLastIdentifierFromData(null, value, schemaNode);
private boolean representsMountPointRootData(final Node<?> data) {
URI namespace = this.namespace(data);
return (SchemaContext.NAME.getNamespace().equals(namespace) /*
- * || MOUNT_POINT_MODULE_NAME .equals( namespace .
- * toString( ) )
- */)
- && SchemaContext.NAME.getLocalName().equals(this.localName(data));
+ * || MOUNT_POINT_MODULE_NAME .equals( namespace .
+ * toString( ) )
+ */)
+ && SchemaContext.NAME.getLocalName().equals(this.localName(data));
}
private String addMountPointIdentifier(final String identifier) {
final List<NodeWrapper<?>> children = compositeNodeBuilder.getValues();
checkNodeMultiplicityAccordingToSchema(schema, children);
for (final NodeWrapper<? extends Object> child : children) {
- final List<DataSchemaNode> potentialSchemaNodes = this.controllerContext.findInstanceDataChildrenByName(
+ final List<DataSchemaNode> potentialSchemaNodes = ControllerContext.findInstanceDataChildrenByName(
schema, child.getLocalName());
if (potentialSchemaNodes.size() > 1 && child.getNamespace() == null) {
}
if (nodeBuilder.getNamespace() == null || Objects.equal(nodeBuilder.getNamespace(), validQName.getNamespace())
- || Objects.equal(nodeBuilder.getNamespace().toString(), moduleName) /*
- * || Note : this check is wrong -
- * can never be true as it compares
- * a URI with a String not sure what
- * the intention is so commented out
- * ... Objects . equal ( nodeBuilder
- * . getNamespace ( ) ,
- * MOUNT_POINT_MODULE_NAME )
- */) {
+ || Objects.equal(nodeBuilder.getNamespace().toString(), moduleName)) {
+ /*
+ * || Note : this check is wrong -
+ * can never be true as it compares
+ * a URI with a String not sure what
+ * the intention is so commented out
+ * ... Objects . equal ( nodeBuilder
+ * . getNamespace ( ) ,
+ * MOUNT_POINT_MODULE_NAME )
+ */
nodeBuilder.setQname(validQName);
}
}
private CompositeNode datastoreNormalizedNodeToCompositeNode(final NormalizedNode<?, ?> dataNode, final DataSchemaNode schema) {
- Iterable<Node<?>> nodes = null;
+ Node<?> nodes = null;
if (dataNode == null) {
throw new RestconfDocumentedException(new RestconfError(ErrorType.APPLICATION, ErrorTag.DATA_MISSING,
"No data was found."));
}
- if (schema instanceof ContainerSchemaNode && dataNode instanceof ContainerNode) {
- nodes = CnSnFromNormalizedNodeSerializerFactory.getInstance().getContainerNodeSerializer()
- .serialize((ContainerSchemaNode) schema, (ContainerNode) dataNode);
- } else if (schema instanceof ListSchemaNode && dataNode instanceof MapNode) {
- nodes = CnSnFromNormalizedNodeSerializerFactory.getInstance().getMapNodeSerializer()
- .serialize((ListSchemaNode) schema, (MapNode) dataNode);
- } else if (schema instanceof ListSchemaNode && dataNode instanceof MapEntryNode) {
- nodes = CnSnFromNormalizedNodeSerializerFactory.getInstance().getMapEntryNodeSerializer()
- .serialize((ListSchemaNode) schema, (MapEntryNode) dataNode);
- }
+ nodes = DataNormalizer.toLegacy(dataNode);
if (nodes != null) {
- if (nodes.iterator().hasNext()) {
- Node<?> nodeOldStruct = nodes.iterator().next();
- return (CompositeNode) nodeOldStruct;
+ if (nodes instanceof CompositeNode) {
+ return (CompositeNode) nodes;
} else {
LOG.error("The node " + dataNode.getNodeType() + " couldn't be transformed to compositenode.");
}
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
}
private NormalizedNode prepareCnDataForSlashesBehindMountPointTest() throws ParseException {
- CollectionNodeBuilder<MapEntryNode, MapNode> lst1 = ImmutableMapNodeBuilder.create();
- lst1.withNodeIdentifier(TestUtils.getNodeIdentifier("lst1", "test:module", "2014-01-09"));
- lst1.withChild(ImmutableMapEntryNodeBuilder
+ return ImmutableMapEntryNodeBuilder
.create()
.withNodeIdentifier(
TestUtils.getNodeIdentifierPredicate("lst1", "test:module", "2014-01-09", "lf11",
.withChild(
ImmutableLeafNodeBuilder.create()
.withNodeIdentifier(TestUtils.getNodeIdentifier("lf11", "test:module", "2014-01-09"))
- .withValue("GigabitEthernet0/0/0/0").build()).build());
+ .withValue("GigabitEthernet0/0/0/0").build()).build();
- return lst1.build();
}
/**
expectLeaf("depth3-leaf1", "depth3-leaf1-value")));
}
+ /**
+ * Tests behavior when invalid value of depth URI parameter
+ */
@Test
public void getDataWithInvalidDepthParameterTest() {
private void getDataWithInvalidDepthParameterTest(final UriInfo uriInfo) {
try {
+ QName qNameDepth1Cont = QName.create("urn:nested:module", "2014-06-3", "depth1-cont");
+ YangInstanceIdentifier ii = YangInstanceIdentifier.builder().node(qNameDepth1Cont).build();
+ NormalizedNode value = (NormalizedNode<?,?>)(Builders.containerBuilder().withNodeIdentifier(new NodeIdentifier(qNameDepth1Cont)).build());
+ when(brokerFacade.readConfigurationData(eq(ii))).thenReturn(value);
restconfImpl.readConfigurationData("nested-module:depth1-cont", uriInfo);
fail("Expected RestconfDocumentedException");
} catch (RestconfDocumentedException e) {
import org.opendaylight.yangtools.yang.data.api.Node;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.composite.node.schema.cnsn.parser.CnSnToNormalizedNodeParserFactory;
import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
static NormalizedNode prepareNormalizedNodeWithIetfInterfacesInterfacesData() throws ParseException {
String ietfInterfacesDate = "2013-07-04";
- CollectionNodeBuilder<MapEntryNode, MapNode> intface = ImmutableMapNodeBuilder.create();
String namespace = "urn:ietf:params:xml:ns:yang:ietf-interfaces";
- intface.withNodeIdentifier(getNodeIdentifier("interface", namespace, ietfInterfacesDate));
DataContainerNodeAttrBuilder<YangInstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> mapEntryNode = ImmutableMapEntryNodeBuilder.create();
Map<String, Object> predicates = new HashMap<>();
.withNodeIdentifier(getNodeIdentifier("description", namespace, ietfInterfacesDate))
.withValue("some interface").build());
- intface.withChild(mapEntryNode.build());
-
- return intface.build();
+ return mapEntryNode.build();
}
}
*/
package org.opendaylight.controller.md.sal.test.model.util;
-import java.util.Arrays;
-
+import com.google.common.collect.ImmutableList;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeComplexUsesAugment;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeComplexUsesAugmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeLeafOnlyUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeLeafOnlyUsesAugmentBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ListViaUses;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ListViaUsesBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ListViaUsesKey;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import com.google.common.collect.ImmutableList;
+import java.util.Arrays;
public class ListsBindingUtils {
return new TreeComplexUsesAugmentBuilder().setListViaUses(listViaUses.build()).build();
}
+ public static TreeLeafOnlyUsesAugment leafOnlyUsesAugment(String leafFromGroupingValue) {
+
+ return new TreeLeafOnlyUsesAugmentBuilder().setLeafFromGrouping(leafFromGroupingValue).build();
+ }
+
}
LinkedHashMap<ConfigSnapshotHolder, EditAndCommitResponse> result = new LinkedHashMap<>();
// start pushing snapshots:
for (ConfigSnapshotHolder configSnapshotHolder : configs) {
- EditAndCommitResponse editAndCommitResponseWithRetries = pushConfigWithConflictingVersionRetries(configSnapshotHolder);
- logger.debug("Config snapshot pushed successfully: {}, result: {}", configSnapshotHolder, result);
- result.put(configSnapshotHolder, editAndCommitResponseWithRetries);
+ if(configSnapshotHolder != null) {
+ EditAndCommitResponse editAndCommitResponseWithRetries = pushConfigWithConflictingVersionRetries(configSnapshotHolder);
+ logger.debug("Config snapshot pushed successfully: {}, result: {}", configSnapshotHolder, result);
+ result.put(configSnapshotHolder, editAndCommitResponseWithRetries);
+ }
}
logger.debug("All configuration snapshots have been pushed successfully.");
return result;