2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.controller.sal.restconf.impl;
10 import com.google.common.util.concurrent.Futures;
12 import java.util.concurrent.Future;
14 import javax.ws.rs.core.Response.Status;
16 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
17 import org.opendaylight.controller.md.sal.common.api.data.DataReader;
18 import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession;
19 import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
20 import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
21 import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
22 import org.opendaylight.controller.sal.core.api.mount.MountInstance;
23 import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
24 import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
25 import org.opendaylight.controller.sal.streams.listeners.ListenerAdapter;
26 import org.opendaylight.yangtools.concepts.ListenerRegistration;
27 import org.opendaylight.yangtools.yang.common.QName;
28 import org.opendaylight.yangtools.yang.common.RpcResult;
29 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
30 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
31 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
35 public class BrokerFacade implements DataReader<InstanceIdentifier, CompositeNode> {
36 private final static Logger LOG = LoggerFactory.getLogger(BrokerFacade.class);
38 private final static BrokerFacade INSTANCE = new BrokerFacade();
40 private volatile DataBrokerService dataService;
41 private volatile ConsumerSession context;
43 private BrokerFacade() {
46 public void setContext(final ConsumerSession context) {
47 this.context = context;
50 public void setDataService(final DataBrokerService dataService) {
51 this.dataService = dataService;
54 public static BrokerFacade getInstance() {
55 return BrokerFacade.INSTANCE;
58 private void checkPreconditions() {
59 if (context == null || dataService == null) {
60 throw new RestconfDocumentedException(Status.SERVICE_UNAVAILABLE);
65 public CompositeNode readConfigurationData(final InstanceIdentifier path) {
66 this.checkPreconditions();
68 LOG.trace("Read Configuration via Restconf: {}", path);
70 return dataService.readConfigurationData(path);
73 public CompositeNode readConfigurationDataBehindMountPoint(final MountInstance mountPoint,
74 final InstanceIdentifier path) {
75 this.checkPreconditions();
77 LOG.trace("Read Configuration via Restconf: {}", path);
79 return mountPoint.readConfigurationData(path);
83 public CompositeNode readOperationalData(final InstanceIdentifier path) {
84 this.checkPreconditions();
86 BrokerFacade.LOG.trace("Read Operational via Restconf: {}", path);
88 return dataService.readOperationalData(path);
91 public CompositeNode readOperationalDataBehindMountPoint(final MountInstance mountPoint,
92 final InstanceIdentifier path) {
93 this.checkPreconditions();
95 BrokerFacade.LOG.trace("Read Operational via Restconf: {}", path);
97 return mountPoint.readOperationalData(path);
100 public Future<RpcResult<CompositeNode>> invokeRpc(final QName type, final CompositeNode payload) {
101 this.checkPreconditions();
103 return context.rpc(type, payload);
106 public Future<RpcResult<TransactionStatus>> commitConfigurationDataPut(final InstanceIdentifier path,
107 final CompositeNode payload) {
108 this.checkPreconditions();
110 final DataModificationTransaction transaction = dataService.beginTransaction();
111 BrokerFacade.LOG.trace("Put Configuration via Restconf: {}", path);
112 transaction.putConfigurationData(path, payload);
113 return transaction.commit();
116 public Future<RpcResult<TransactionStatus>> commitConfigurationDataPutBehindMountPoint(
117 final MountInstance mountPoint, final InstanceIdentifier path, final CompositeNode payload) {
118 this.checkPreconditions();
120 final DataModificationTransaction transaction = mountPoint.beginTransaction();
121 BrokerFacade.LOG.trace("Put Configuration via Restconf: {}", path);
122 transaction.putConfigurationData(path, payload);
123 return transaction.commit();
126 public Future<RpcResult<TransactionStatus>> commitConfigurationDataPost(final InstanceIdentifier path,
127 final CompositeNode payload) {
128 this.checkPreconditions();
130 final DataModificationTransaction transaction = dataService.beginTransaction();
131 /* check for available Node in Configuration DataStore by path */
132 CompositeNode availableNode = transaction.readConfigurationData(path);
133 if (availableNode != null) {
134 String errMsg = "Post Configuration via Restconf was not executed because data already exists";
135 BrokerFacade.LOG.warn((new StringBuilder(errMsg)).append(" : ").append(path).toString());
137 throw new RestconfDocumentedException("Data already exists for path: " + path, ErrorType.PROTOCOL,
138 ErrorTag.DATA_EXISTS);
140 BrokerFacade.LOG.trace("Post Configuration via Restconf: {}", path);
141 transaction.putConfigurationData(path, payload);
142 return transaction.commit();
145 public Future<RpcResult<TransactionStatus>> commitConfigurationDataPostBehindMountPoint(
146 final MountInstance mountPoint, final InstanceIdentifier path, final CompositeNode payload) {
147 this.checkPreconditions();
149 final DataModificationTransaction transaction = mountPoint.beginTransaction();
150 /* check for available Node in Configuration DataStore by path */
151 CompositeNode availableNode = transaction.readConfigurationData(path);
152 if (availableNode != null) {
153 String errMsg = "Post Configuration via Restconf was not executed because data already exists";
154 BrokerFacade.LOG.warn((new StringBuilder(errMsg)).append(" : ").append(path).toString());
156 throw new RestconfDocumentedException("Data already exists for path: " + path, ErrorType.PROTOCOL,
157 ErrorTag.DATA_EXISTS);
159 BrokerFacade.LOG.trace("Post Configuration via Restconf: {}", path);
160 transaction.putConfigurationData(path, payload);
161 return transaction.commit();
164 public Future<RpcResult<TransactionStatus>> commitConfigurationDataDelete(final InstanceIdentifier path) {
165 this.checkPreconditions();
166 return deleteDataAtTarget(path, dataService.beginTransaction());
169 public Future<RpcResult<TransactionStatus>> commitConfigurationDataDeleteBehindMountPoint(
170 final MountInstance mountPoint, final InstanceIdentifier path) {
171 this.checkPreconditions();
172 return deleteDataAtTarget(path, mountPoint.beginTransaction());
175 private Future<RpcResult<TransactionStatus>> deleteDataAtTarget(final InstanceIdentifier path,
176 final DataModificationTransaction transaction) {
177 LOG.info("Delete Configuration via Restconf: {}", path);
178 CompositeNode redDataAtPath = transaction.readConfigurationData(path);
179 if (redDataAtPath == null) {
180 return Futures.immediateFuture(RpcResultBuilder.<TransactionStatus>
181 success(TransactionStatus.COMMITED).build());
183 transaction.removeConfigurationData(path);
184 return transaction.commit();
187 public void registerToListenDataChanges(final ListenerAdapter listener) {
188 this.checkPreconditions();
190 if (listener.isListening()) {
194 InstanceIdentifier path = listener.getPath();
195 final ListenerRegistration<DataChangeListener> registration = dataService.registerDataChangeListener(path,
198 listener.setRegistration(registration);