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(
137 "Data already exists for path: " + path, ErrorType.PROTOCOL, 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(
156 "Data already exists for path: " + path, ErrorType.PROTOCOL, 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 =
195 dataService.registerDataChangeListener( path, listener );
197 listener.setRegistration( registration );