--- /dev/null
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.mdsal.binding.javav2.dom.adapter.impl.data;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ClassToInstanceMap;
+import com.google.common.collect.ImmutableSet;
+import java.util.Collection;
+import java.util.Set;
+import javax.annotation.Nonnull;
+import org.opendaylight.mdsal.binding.javav2.api.BindingTransactionChain;
+import org.opendaylight.mdsal.binding.javav2.api.DataBroker;
+import org.opendaylight.mdsal.binding.javav2.api.DataTreeIdentifier;
+import org.opendaylight.mdsal.binding.javav2.api.DataTreeListener;
+import org.opendaylight.mdsal.binding.javav2.api.DataTreeLoopException;
+import org.opendaylight.mdsal.binding.javav2.api.DataTreeProducer;
+import org.opendaylight.mdsal.binding.javav2.api.DataTreeService;
+import org.opendaylight.mdsal.binding.javav2.api.ReadTransaction;
+import org.opendaylight.mdsal.binding.javav2.api.WriteTransaction;
+import org.opendaylight.mdsal.binding.javav2.dom.adapter.impl.data.tree.BindingDOMDataTreeServiceAdapter;
+import org.opendaylight.mdsal.binding.javav2.dom.adapter.impl.transaction.BindingDOMReadTransactionAdapter;
+import org.opendaylight.mdsal.binding.javav2.dom.adapter.impl.transaction.BindingDOMTransactionChainAdapter;
+import org.opendaylight.mdsal.binding.javav2.dom.adapter.impl.transaction.BindingDOMWriteTransactionAdapter;
+import org.opendaylight.mdsal.binding.javav2.dom.adapter.spi.AbstractForwardedDataBroker;
+import org.opendaylight.mdsal.binding.javav2.dom.adapter.spi.builder.BindingDOMAdapterBuilder;
+import org.opendaylight.mdsal.binding.javav2.dom.adapter.spi.builder.BindingDOMAdapterBuilder.Factory;
+import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.BindingToNormalizedNodeCodec;
+import org.opendaylight.mdsal.common.api.TransactionChainListener;
+import org.opendaylight.mdsal.dom.api.DOMDataBroker;
+import org.opendaylight.mdsal.dom.api.DOMDataTreeService;
+import org.opendaylight.mdsal.dom.api.DOMService;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+
+/**
+ * The DataBrokerImpl simply defers to the DOMDataBroker for all its operations. All transactions and listener
+ * registrations are wrapped by the DataBrokerImpl to allow binding aware components to use the DataBroker
+ * transparently.
+ *
+ * <p>
+ * Besides this the DataBrokerImpl and it's collaborators also cache data that is already transformed from the
+ * binding independent to binding aware format
+ *
+ */
+@Beta
+public class BindingDOMDataBrokerAdapter extends AbstractForwardedDataBroker implements DataBroker, DataTreeService {
+
+ public static final Factory<DataBroker> BUILDER_FACTORY = Builder::new;
+
+ private final DataTreeService treeService;
+
+ public BindingDOMDataBrokerAdapter(final DOMDataBroker domDataBroker, final BindingToNormalizedNodeCodec codec) {
+ super(domDataBroker, codec);
+ final DOMDataTreeService domTreeChange =
+ (DOMDataTreeService) domDataBroker.getSupportedExtensions().get(DOMDataTreeService.class);
+ if (domTreeChange != null) {
+ treeService = BindingDOMDataTreeServiceAdapter.create(domTreeChange, codec);
+ } else {
+ treeService = null;
+ }
+ }
+
+ @Override
+ public ReadTransaction newReadOnlyTransaction() {
+ return new BindingDOMReadTransactionAdapter(getDelegate().newReadOnlyTransaction(), getCodec());
+ }
+
+ @Override
+ public WriteTransaction newWriteOnlyTransaction() {
+ return new BindingDOMWriteTransactionAdapter<>(getDelegate().newWriteOnlyTransaction(), getCodec());
+ }
+
+ @Override
+ public BindingTransactionChain createTransactionChain(final TransactionChainListener listener) {
+ return new BindingDOMTransactionChainAdapter(getDelegate(), getCodec(), listener);
+ }
+
+ private static class Builder extends BindingDOMAdapterBuilder<DataBroker> {
+
+ @Override
+ public Set<? extends Class<? extends DOMService>> getRequiredDelegates() {
+ return ImmutableSet.of(DOMDataBroker.class);
+ }
+
+ @Override
+ protected DataBroker createInstance(final BindingToNormalizedNodeCodec codec,
+ final ClassToInstanceMap<DOMService> delegates) {
+ final DOMDataBroker domDataBroker = delegates.getInstance(DOMDataBroker.class);
+ return new BindingDOMDataBrokerAdapter(domDataBroker, codec);
+ }
+
+ }
+
+ @Nonnull
+ @Override
+ public <T extends DataTreeListener> ListenerRegistration<T> registerListener(@Nonnull final T listener,
+ @Nonnull final Collection<DataTreeIdentifier<?>> subtrees, final boolean allowRxMerges,
+ @Nonnull final Collection<DataTreeProducer> producers) throws DataTreeLoopException {
+ if (treeService == null) {
+ throw new UnsupportedOperationException("Underlying data broker does not expose DOMDataTreeChangeService.");
+ }
+ return treeService.registerListener(listener, subtrees, allowRxMerges, producers);
+ }
+
+ @Override
+ public DataTreeProducer createProducer(final Collection<DataTreeIdentifier<?>> subtrees) {
+ return treeService.createProducer(subtrees);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.mdsal.binding.javav2.dom.adapter.impl.transaction;
+
+import com.google.common.annotations.Beta;
+import java.util.function.BiConsumer;
+import org.opendaylight.mdsal.binding.javav2.api.ReadTransaction;
+import org.opendaylight.mdsal.binding.javav2.dom.adapter.spi.AbstractForwardedTransaction;
+import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.BindingToNormalizedNodeCodec;
+import org.opendaylight.mdsal.binding.javav2.spec.base.InstanceIdentifier;
+import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.mdsal.common.api.ReadFailedException;
+import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
+
+/**
+ * Read transaction adapter.
+ */
+@Beta
+public class BindingDOMReadTransactionAdapter extends AbstractForwardedTransaction<DOMDataTreeReadTransaction>
+ implements ReadTransaction {
+
+ public BindingDOMReadTransactionAdapter(final DOMDataTreeReadTransaction delegate,
+ final BindingToNormalizedNodeCodec codec) {
+ super(delegate, codec);
+ }
+
+ @Override
+ public <T extends TreeNode> void read(final LogicalDatastoreType store, final InstanceIdentifier<T> path,
+ final BiConsumer<ReadFailedException, T> callback) {
+ doRead(getDelegate(), store, path);
+ }
+
+ @Override
+ public void close() {
+ getDelegate().close();
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.mdsal.binding.javav2.dom.adapter.impl.transaction;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import javax.annotation.Nonnull;
+import org.opendaylight.mdsal.binding.javav2.api.BindingTransactionChain;
+import org.opendaylight.mdsal.binding.javav2.api.ReadTransaction;
+import org.opendaylight.mdsal.binding.javav2.api.WriteTransaction;
+import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.BindingToNormalizedNodeCodec;
+import org.opendaylight.mdsal.common.api.AsyncTransaction;
+import org.opendaylight.mdsal.common.api.TransactionChain;
+import org.opendaylight.mdsal.common.api.TransactionChainListener;
+import org.opendaylight.mdsal.common.api.TransactionCommitFailedException;
+import org.opendaylight.mdsal.dom.api.DOMDataBroker;
+import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
+import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
+import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
+import org.opendaylight.yangtools.concepts.Delegator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Transaction chain adapter.
+ */
+@Beta
+public final class BindingDOMTransactionChainAdapter
+ implements BindingTransactionChain, Delegator<DOMTransactionChain> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(BindingDOMTransactionChainAdapter.class);
+
+ private final DOMTransactionChain delegate;
+ private final BindingToNormalizedNodeCodec codec;
+ private final TransactionChainListener bindingListener;
+
+ public BindingDOMTransactionChainAdapter(final DOMDataBroker chainFactory, final BindingToNormalizedNodeCodec codec,
+ final TransactionChainListener listener) {
+ Preconditions.checkNotNull(chainFactory, "DOM Transaction chain factory must not be null");
+ this.bindingListener = listener;
+ this.delegate = chainFactory.createTransactionChain(new DelegateChainListener());
+ this.codec = codec;
+ }
+
+ @Override
+ public DOMTransactionChain getDelegate() {
+ return delegate;
+ }
+
+ @Override
+ public ReadTransaction newReadOnlyTransaction() {
+ final DOMDataTreeReadTransaction delegateTx = delegate.newReadOnlyTransaction();
+ return new BindingDOMReadTransactionAdapter(delegateTx, codec);
+ }
+
+ @Override
+ public WriteTransaction newWriteOnlyTransaction() {
+ final DOMDataTreeWriteTransaction delegateTx = delegate.newWriteOnlyTransaction();
+ return new BindingDOMWriteTransactionAdapter<DOMDataTreeWriteTransaction>(delegateTx, codec) {
+
+ @Override
+ public CheckedFuture<Void, TransactionCommitFailedException> submit() {
+ return listenForFailure(this, super.submit());
+ }
+
+ };
+ }
+
+ private CheckedFuture<Void, TransactionCommitFailedException> listenForFailure(final WriteTransaction tx,
+ final CheckedFuture<Void, TransactionCommitFailedException> future) {
+ Futures.addCallback(future, new FutureCallback<Void>() {
+ @Override
+ public void onFailure(@Nonnull final Throwable throwable) {
+ failTransactionChain(tx, throwable);
+ }
+
+ @Override
+ public void onSuccess(final Void result) {
+ // Intentionally NOOP
+ }
+ });
+
+ return future;
+ }
+
+ private void failTransactionChain(final WriteTransaction tx, final Throwable throwable) {
+ /*
+ * We assume correct state change for underlying transaction
+ *
+ * chain, so we are not changing any of our internal state to mark that we failed.
+ */
+ this.bindingListener.onTransactionChainFailed(this, tx, throwable);
+ }
+
+ @Override
+ public void close() {
+ delegate.close();
+ }
+
+ private final class DelegateChainListener implements TransactionChainListener {
+
+ @Override
+ public void onTransactionChainFailed(final TransactionChain<?, ?> chain,
+ final AsyncTransaction<?, ?> transaction, final Throwable cause) {
+ Preconditions.checkState(delegate.equals(chain),
+ "Illegal state - listener for %s was invoked for incorrect chain %s.", delegate, chain);
+ /*
+ * Intentionally NOOP, callback for failure, since we are also listening on each transaction
+ * future for failure, in order to have reference to Binding Transaction (which was seen by client
+ * of this transaction chain), instead of DOM transaction which is known only to this chain,
+ * binding transaction implementation and underlying transaction chain.
+ *
+ */
+ LOG.debug("Transaction chain {} failed. Failed DOM Transaction {}", this, transaction, cause);
+ }
+
+ @Override
+ public void onTransactionChainSuccessful(final TransactionChain<?, ?> chain) {
+ Preconditions.checkState(delegate.equals(chain),
+ "Illegal state - listener for %s was invoked for incorrect chain %s.", delegate, chain);
+ bindingListener.onTransactionChainSuccessful(BindingDOMTransactionChainAdapter.this);
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.mdsal.binding.javav2.dom.adapter.impl.transaction;
+
+import com.google.common.annotations.Beta;
+import com.google.common.util.concurrent.CheckedFuture;
+import org.opendaylight.mdsal.binding.javav2.api.WriteTransaction;
+import org.opendaylight.mdsal.binding.javav2.dom.adapter.spi.AbstractWriteTransaction;
+import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.BindingToNormalizedNodeCodec;
+import org.opendaylight.mdsal.binding.javav2.spec.base.InstanceIdentifier;
+import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.mdsal.common.api.TransactionCommitFailedException;
+import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
+
+/**
+ * Write transaction adapter.
+ *
+ * @param <T>
+ * - {@link DOMDataTreeWriteTransaction} type
+ */
+@Beta
+public class BindingDOMWriteTransactionAdapter<T extends DOMDataTreeWriteTransaction>
+ extends AbstractWriteTransaction<T>
+ implements WriteTransaction {
+
+ public BindingDOMWriteTransactionAdapter(final T delegateTx, final BindingToNormalizedNodeCodec codec) {
+ super(delegateTx, codec);
+ }
+
+ @Override
+ public <U extends TreeNode> void put(final LogicalDatastoreType store, final InstanceIdentifier<U> path,
+ final U data) {
+ put(store, path, data, false);
+ }
+
+ @Override
+ public <U extends TreeNode> void merge(final LogicalDatastoreType store, final InstanceIdentifier<U> path,
+ final U data) {
+ merge(store, path, data, false);
+ }
+
+ @Override
+ public void delete(final LogicalDatastoreType store, final InstanceIdentifier<?> path) {
+ doDelete(store, path);
+ }
+
+ @Override
+ public CheckedFuture<Void, TransactionCommitFailedException> submit() {
+ return doSubmit();
+ }
+
+ @Override
+ public boolean cancel() {
+ return doCancel();
+ }
+}
\ No newline at end of file
import java.util.Map;
import javax.annotation.Nonnull;
import org.opendaylight.mdsal.binding.javav2.api.BindingService;
+import org.opendaylight.mdsal.binding.javav2.api.DataBroker;
+import org.opendaylight.mdsal.binding.javav2.dom.adapter.impl.data.BindingDOMDataBrokerAdapter;
import org.opendaylight.mdsal.binding.javav2.dom.adapter.spi.builder.AdapterBuilder;
import org.opendaylight.mdsal.binding.javav2.dom.adapter.spi.builder.BindingDOMAdapterBuilder;
import org.opendaylight.mdsal.binding.javav2.dom.adapter.spi.builder.BindingDOMAdapterBuilder.Factory;
// TODO add all factory of services
@SuppressWarnings("checkstyle:GenericWhitespace")
private static final Map<Class<?>, BindingDOMAdapterBuilder.Factory<?>> FACTORIES =
- ImmutableMap.<Class<?>, BindingDOMAdapterBuilder.Factory<?>> builder().build();
+ ImmutableMap.<Class<?>, BindingDOMAdapterBuilder.Factory<?>> builder()
+ .put(DataBroker.class, BindingDOMDataBrokerAdapter.BUILDER_FACTORY)
+ .build();
private final BindingToNormalizedNodeCodec codec;