Added range type to subject-feature-definition/parameter
[groupbasedpolicy.git] / groupbasedpolicy / src / main / java / org / opendaylight / groupbasedpolicy / renderer / opflex / EprContext.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.groupbasedpolicy.renderer.opflex;
10
11 import java.util.ArrayList;
12 import java.util.List;
13 import java.util.concurrent.ScheduledExecutorService;
14 import java.util.concurrent.atomic.AtomicReference;
15
16 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
17 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
18 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
19 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
20 import org.opendaylight.groupbasedpolicy.jsonrpc.JsonRpcEndpoint;
21 import org.opendaylight.groupbasedpolicy.jsonrpc.RpcMessage;
22
23 import com.google.common.util.concurrent.CheckedFuture;
24
25 /**
26  * A context for managing a related set of operations to the Endpoint Registry's
27  * lists of Endpoints. It also keeps state from messaging that initiated the
28  * Endpoint Registry interaction, so that notifications from the registry can be
29  * used to send responses
30  *
31  * @author tbachman
32  *
33  */
34 public class EprContext implements Runnable, EprOperation.EprOpCallback {
35     private EprCtxCallback cb;
36     private final DataBroker dataProvider;
37     private final ScheduledExecutorService executor;
38     private final JsonRpcEndpoint peer;
39     private final RpcMessage request;
40     private List<EprOperation> operations;
41     private AtomicReference<Integer> completedOperations;
42     private CheckedFuture<Void, TransactionCommitFailedException> f;
43
44     public EprContext(JsonRpcEndpoint peer, RpcMessage request,
45             DataBroker dataProvider, ScheduledExecutorService executor) {
46         this.dataProvider = dataProvider;
47         this.executor = executor;
48         this.peer = peer;
49         this.request = request;
50         operations = new ArrayList<EprOperation>();
51     }
52
53     /**
54      * Add an operation to this context. This is not thread-safe.
55      *
56      * @param operation
57      */
58     public void addOperation(EprOperation operation) {
59         if (operation != null) {
60             operations.add(operation);
61         }
62     }
63
64     public List<EprOperation> getOperations() {
65         return this.operations;
66     }
67
68     public JsonRpcEndpoint getPeer() {
69         return this.peer;
70     }
71
72     /**
73      * Provides a callback that is invoked in response to a transaction with the
74      * EPR.
75      *
76      * @author tbachman
77      *
78      */
79     public static interface EprCtxCallback {
80         public void callback(EprContext ctx);
81     }
82
83     public void setCallback(EprCtxCallback callback) {
84         this.cb = callback;
85     }
86
87     public RpcMessage getRequest() {
88         return this.request;
89     }
90
91     /**
92      * Create an Endpoint in the Endopint Registry. This can only be called in
93      * response to an {@link EndpointDeclareRequest} message
94      *
95      */
96     public void createEp() {
97
98         WriteTransaction wt = dataProvider.newWriteOnlyTransaction();
99
100         /*
101          * Add each of the create/update operations to a single transaction
102          */
103         if (operations != null) {
104             for (EprOperation eo : operations) {
105                 eo.put(wt);
106             }
107         }
108         f = wt.submit();
109         f.addListener(this, executor);
110
111     }
112
113     /**
114      * Delete an Endpoint in the Endpoint Registry. This can only be called in
115      * response to an {@link EndpointUndeclareRequest} message
116      *
117      */
118     public void deleteEp() {
119
120         WriteTransaction wt = dataProvider.newWriteOnlyTransaction();
121
122         /*
123          * Add each of the delete operations to a single transaction
124          */
125         if (operations != null) {
126             for (EprOperation eo : operations) {
127                 eo.delete(wt);
128             }
129         }
130         f = wt.submit();
131         f.addListener(this, executor);
132     }
133
134     /**
135      * Look up an endpoint in the Endpoint Registry. This can only be called in
136      * response to an {@link EndpointResolveRequest} message. It initiates all
137      * of the reads, one by one, and invokes the callback when all of them have
138      * completed.
139      *
140      */
141     public void lookupEndpoint() {
142
143         /*
144          * Each read operation requires it's own transaction. We add a callback
145          * for each operation, so we can determine when all of the read
146          * operations have completed.
147          */
148         this.completedOperations = new AtomicReference<Integer>(
149                 Integer.valueOf(0));
150         if (operations != null) {
151             for (EprOperation eo : operations) {
152                 ReadOnlyTransaction rot = dataProvider.newReadOnlyTransaction();
153
154                 eo.setCallback(this);
155                 eo.read(rot, executor);
156             }
157         }
158     }
159
160     /**
161      * This implements the callback for the create and delete operations, from
162      * the CheckedFuture.
163      */
164     @Override
165     public void run() {
166         try {
167             f.get();
168         } catch (Exception e) {
169             // TODO: Don't use Exception
170         }
171         cb.callback(this);
172     }
173
174     /**
175      * This implements the callback for the lookup operation.
176      *
177      */
178     @Override
179     public void callback(EprOperation op) {
180         /*
181          * Add this to the list of operations that have completed, and if
182          * finished, invoke our callback
183          */
184         completedOperations.set(completedOperations.get().intValue() + 1);
185         if (completedOperations.get() >= operations.size()) {
186             cb.callback(this);
187             // TODO: way to ensure it doesn't get invoked multiple times
188         }
189     }
190 }