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;
11 import java.util.Collections;
12 import java.util.concurrent.Future;
13 import javax.ws.rs.core.Response.Status;
14 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
15 import org.opendaylight.controller.md.sal.common.api.data.DataReader;
16 import org.opendaylight.controller.sal.common.util.Rpcs;
17 import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession;
18 import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
19 import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
20 import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
21 import org.opendaylight.controller.sal.core.api.mount.MountInstance;
22 import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
23 import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
24 import org.opendaylight.controller.sal.streams.listeners.ListenerAdapter;
25 import org.opendaylight.yangtools.concepts.ListenerRegistration;
26 import org.opendaylight.yangtools.yang.common.QName;
27 import org.opendaylight.yangtools.yang.common.RpcError;
28 import org.opendaylight.yangtools.yang.common.RpcResult;
29 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
30 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
34 public class BrokerFacade implements DataReader<InstanceIdentifier, CompositeNode> {
35 private final static Logger LOG = LoggerFactory.getLogger(BrokerFacade.class);
37 private final static BrokerFacade INSTANCE = new BrokerFacade();
39 private volatile DataBrokerService dataService;
40 private volatile ConsumerSession context;
42 private BrokerFacade() {
45 public void setContext(final ConsumerSession context) {
46 this.context = context;
49 public void setDataService(final DataBrokerService dataService) {
50 this.dataService = dataService;
53 public static BrokerFacade getInstance() {
54 return BrokerFacade.INSTANCE;
57 private void checkPreconditions() {
58 if (context == null || dataService == null) {
59 throw new RestconfDocumentedException(Status.SERVICE_UNAVAILABLE);
64 public CompositeNode readConfigurationData(final InstanceIdentifier path) {
65 this.checkPreconditions();
67 LOG.trace("Read Configuration via Restconf: {}", path);
69 return dataService.readConfigurationData(path);
72 public CompositeNode readConfigurationDataBehindMountPoint(final MountInstance mountPoint,
73 final InstanceIdentifier path) {
74 this.checkPreconditions();
76 LOG.trace("Read Configuration via Restconf: {}", path);
78 return mountPoint.readConfigurationData(path);
82 public CompositeNode readOperationalData(final InstanceIdentifier path) {
83 this.checkPreconditions();
85 BrokerFacade.LOG.trace("Read Operational via Restconf: {}", path);
87 return dataService.readOperationalData(path);
90 public CompositeNode readOperationalDataBehindMountPoint(final MountInstance mountPoint,
91 final InstanceIdentifier path) {
92 this.checkPreconditions();
94 BrokerFacade.LOG.trace("Read Operational via Restconf: {}", path);
96 return mountPoint.readOperationalData(path);
99 public Future<RpcResult<CompositeNode>> invokeRpc(final QName type, final CompositeNode payload) {
100 this.checkPreconditions();
102 return context.rpc(type, payload);
105 public Future<RpcResult<TransactionStatus>> commitConfigurationDataPut(final InstanceIdentifier path,
106 final CompositeNode payload) {
107 this.checkPreconditions();
109 final DataModificationTransaction transaction = dataService.beginTransaction();
110 BrokerFacade.LOG.trace("Put Configuration via Restconf: {}", path);
111 transaction.putConfigurationData(path, payload);
112 return transaction.commit();
115 public Future<RpcResult<TransactionStatus>> commitConfigurationDataPutBehindMountPoint(
116 final MountInstance mountPoint, final InstanceIdentifier path, final CompositeNode payload) {
117 this.checkPreconditions();
119 final DataModificationTransaction transaction = mountPoint.beginTransaction();
120 BrokerFacade.LOG.trace("Put Configuration via Restconf: {}", path);
121 transaction.putConfigurationData(path, payload);
122 return transaction.commit();
125 public Future<RpcResult<TransactionStatus>> commitConfigurationDataPost(final InstanceIdentifier path,
126 final CompositeNode payload) {
127 this.checkPreconditions();
129 final DataModificationTransaction transaction = dataService.beginTransaction();
130 /* check for available Node in Configuration DataStore by path */
131 CompositeNode availableNode = transaction.readConfigurationData(path);
132 if (availableNode != null) {
133 String errMsg = "Post Configuration via Restconf was not executed because data already exists";
134 BrokerFacade.LOG.warn((new StringBuilder(errMsg)).append(" : ").append(path).toString());
136 throw new RestconfDocumentedException("Data already exists for path: " + path, ErrorType.PROTOCOL,
137 ErrorTag.DATA_EXISTS);
139 BrokerFacade.LOG.trace("Post Configuration via Restconf: {}", path);
140 transaction.putConfigurationData(path, payload);
141 return transaction.commit();
144 public Future<RpcResult<TransactionStatus>> commitConfigurationDataPostBehindMountPoint(
145 final MountInstance mountPoint, final InstanceIdentifier path, final CompositeNode payload) {
146 this.checkPreconditions();
148 final DataModificationTransaction transaction = mountPoint.beginTransaction();
149 /* check for available Node in Configuration DataStore by path */
150 CompositeNode availableNode = transaction.readConfigurationData(path);
151 if (availableNode != null) {
152 String errMsg = "Post Configuration via Restconf was not executed because data already exists";
153 BrokerFacade.LOG.warn((new StringBuilder(errMsg)).append(" : ").append(path).toString());
155 throw new RestconfDocumentedException("Data already exists for path: " + path, ErrorType.PROTOCOL,
156 ErrorTag.DATA_EXISTS);
158 BrokerFacade.LOG.trace("Post Configuration via Restconf: {}", path);
159 transaction.putConfigurationData(path, payload);
160 return transaction.commit();
163 public Future<RpcResult<TransactionStatus>> commitConfigurationDataDelete(final InstanceIdentifier path) {
164 this.checkPreconditions();
165 return deleteDataAtTarget(path, dataService.beginTransaction());
168 public Future<RpcResult<TransactionStatus>> commitConfigurationDataDeleteBehindMountPoint(
169 final MountInstance mountPoint, final InstanceIdentifier path) {
170 this.checkPreconditions();
171 return deleteDataAtTarget(path, mountPoint.beginTransaction());
174 private Future<RpcResult<TransactionStatus>> deleteDataAtTarget(final InstanceIdentifier path,
175 final DataModificationTransaction transaction) {
176 LOG.info("Delete Configuration via Restconf: {}", path);
177 CompositeNode redDataAtPath = transaction.readConfigurationData(path);
178 if (redDataAtPath == null) {
179 return Futures.immediateFuture(Rpcs.<TransactionStatus> getRpcResult(true, TransactionStatus.COMMITED,
180 Collections.<RpcError> emptyList()));
182 transaction.removeConfigurationData(path);
183 return transaction.commit();
186 public void registerToListenDataChanges(final ListenerAdapter listener) {
187 this.checkPreconditions();
189 if (listener.isListening()) {
193 InstanceIdentifier path = listener.getPath();
194 final ListenerRegistration<DataChangeListener> registration = dataService.registerDataChangeListener(path,
197 listener.setRegistration(registration);