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 java.util.concurrent.Future;
12 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.core.api.Broker.ConsumerSession;
17 import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
18 import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
19 import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
20 import org.opendaylight.controller.sal.core.api.mount.MountInstance;
21 import org.opendaylight.controller.sal.rest.impl.RestconfProvider;
22 import org.opendaylight.controller.sal.streams.listeners.ListenerAdapter;
23 import org.opendaylight.yangtools.concepts.ListenerRegistration;
24 import org.opendaylight.yangtools.yang.common.QName;
25 import org.opendaylight.yangtools.yang.common.RpcResult;
26 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
27 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
31 public class BrokerFacade implements DataReader<InstanceIdentifier, CompositeNode> {
32 private final static Logger LOG = LoggerFactory.getLogger( BrokerFacade.class );
34 private final static BrokerFacade INSTANCE = new BrokerFacade();
36 private volatile DataBrokerService dataService;
37 private volatile ConsumerSession context;
39 private BrokerFacade() {
42 public void setContext( final ConsumerSession context ) {
43 this.context = context;
46 public void setDataService( final DataBrokerService dataService ) {
47 this.dataService = dataService;
50 public static BrokerFacade getInstance() {
51 return BrokerFacade.INSTANCE;
54 private void checkPreconditions() {
55 if( context == null || dataService == null ) {
56 ResponseException _responseException = new ResponseException( Status.SERVICE_UNAVAILABLE,
57 RestconfProvider.NOT_INITALIZED_MSG );
58 throw _responseException;
63 public CompositeNode readConfigurationData( final InstanceIdentifier path ) {
64 this.checkPreconditions();
66 LOG.trace( "Read Configuration via Restconf: {}", path );
68 return dataService.readConfigurationData( path );
71 public CompositeNode readConfigurationDataBehindMountPoint( final MountInstance mountPoint,
72 final InstanceIdentifier path ) {
73 this.checkPreconditions();
75 LOG.trace( "Read Configuration via Restconf: {}", path );
77 return mountPoint.readConfigurationData( path );
81 public CompositeNode readOperationalData( final InstanceIdentifier path ) {
82 this.checkPreconditions();
84 BrokerFacade.LOG.trace( "Read Operational via Restconf: {}", path );
86 return dataService.readOperationalData( path );
89 public CompositeNode readOperationalDataBehindMountPoint( final MountInstance mountPoint,
90 final InstanceIdentifier path ) {
91 this.checkPreconditions();
93 BrokerFacade.LOG.trace( "Read Operational via Restconf: {}", path );
95 return mountPoint.readOperationalData( path );
98 public RpcResult<CompositeNode> invokeRpc( final QName type, final CompositeNode payload ) {
99 this.checkPreconditions();
101 final Future<RpcResult<CompositeNode>> future = context.rpc( type, payload );
106 catch( Exception e ) {
107 throw new ResponseException( e, "Error invoking RPC " + type );
111 public Future<RpcResult<TransactionStatus>> commitConfigurationDataPut( final InstanceIdentifier path,
112 final CompositeNode payload ) {
113 this.checkPreconditions();
115 final DataModificationTransaction transaction = dataService.beginTransaction();
116 BrokerFacade.LOG.trace( "Put Configuration via Restconf: {}", path );
117 transaction.putConfigurationData( path, payload );
118 return transaction.commit();
121 public Future<RpcResult<TransactionStatus>> commitConfigurationDataPutBehindMountPoint(
122 final MountInstance mountPoint, final InstanceIdentifier path, final CompositeNode payload ) {
123 this.checkPreconditions();
125 final DataModificationTransaction transaction = mountPoint.beginTransaction();
126 BrokerFacade.LOG.trace( "Put Configuration via Restconf: {}", path );
127 transaction.putConfigurationData( path, payload );
128 return transaction.commit();
131 public Future<RpcResult<TransactionStatus>> commitConfigurationDataPost( final InstanceIdentifier path,
132 final CompositeNode payload) {
133 this.checkPreconditions();
135 final DataModificationTransaction transaction = dataService.beginTransaction();
136 /* check for available Node in Configuration DataStore by path */
137 CompositeNode availableNode = transaction.readConfigurationData( path );
138 if (availableNode != null) {
139 String errMsg = "Post Configuration via Restconf was not executed because data already exists";
140 BrokerFacade.LOG.warn((new StringBuilder(errMsg)).append(" : ").append(path).toString());
141 // FIXME: return correct ietf-restconf:errors -> follow specification
142 // (http://tools.ietf.org/html/draft-bierman-netconf-restconf-03#page-48)
143 throw new ResponseException(Status.CONFLICT, errMsg);
145 BrokerFacade.LOG.trace( "Post Configuration via Restconf: {}", path );
146 transaction.putConfigurationData( path, payload );
147 return transaction.commit();
150 public Future<RpcResult<TransactionStatus>> commitConfigurationDataPostBehindMountPoint(
151 final MountInstance mountPoint, final InstanceIdentifier path, final CompositeNode payload ) {
152 this.checkPreconditions();
154 final DataModificationTransaction transaction = mountPoint.beginTransaction();
155 /* check for available Node in Configuration DataStore by path */
156 CompositeNode availableNode = transaction.readConfigurationData( path );
157 if (availableNode != null) {
158 String errMsg = "Post Configuration via Restconf was not executed because data already exists";
159 BrokerFacade.LOG.warn((new StringBuilder(errMsg)).append(" : ").append(path).toString());
160 // FIXME: return correct ietf-restconf:errors -> follow specification
161 // (http://tools.ietf.org/html/draft-bierman-netconf-restconf-03#page-48)
162 throw new ResponseException(Status.CONFLICT, errMsg);
164 BrokerFacade.LOG.trace( "Post Configuration via Restconf: {}", path );
165 transaction.putConfigurationData( path, payload );
166 return transaction.commit();
169 public Future<RpcResult<TransactionStatus>> commitConfigurationDataDelete( final InstanceIdentifier path ) {
170 this.checkPreconditions();
172 final DataModificationTransaction transaction = dataService.beginTransaction();
173 LOG.info( "Delete Configuration via Restconf: {}", path );
174 transaction.removeConfigurationData( path );
175 return transaction.commit();
178 public Future<RpcResult<TransactionStatus>> commitConfigurationDataDeleteBehindMountPoint(
179 final MountInstance mountPoint, final InstanceIdentifier path ) {
180 this.checkPreconditions();
182 final DataModificationTransaction transaction = mountPoint.beginTransaction();
183 LOG.info( "Delete Configuration via Restconf: {}", path );
184 transaction.removeConfigurationData( path );
185 return transaction.commit();
188 public void registerToListenDataChanges( final ListenerAdapter listener ) {
189 this.checkPreconditions();
191 if( listener.isListening() ) {
195 InstanceIdentifier path = listener.getPath();
196 final ListenerRegistration<DataChangeListener> registration =
197 dataService.registerDataChangeListener( path, listener );
199 listener.setRegistration( registration );