1 package org.onap.sdc.dcae.catalog.commons;
4 import java.util.LinkedList;
5 import java.util.ArrayList;
6 import java.util.Collections;
7 import java.util.concurrent.CountDownLatch;
9 import org.onap.sdc.common.onaplog.OnapLoggerDebug;
10 import org.onap.sdc.common.onaplog.OnapLoggerError;
11 import org.onap.sdc.common.onaplog.Enums.LogLevel;
12 import org.onap.sdc.dcae.catalog.commons.Action;
13 import org.onap.sdc.dcae.catalog.commons.Future;
14 import org.onap.sdc.dcae.catalog.commons.FutureHandler;
15 import org.onap.sdc.dcae.catalog.commons.Futures;
19 public interface Actions {
22 public static interface CompoundAction<T> extends Action<List<T>> {
24 public CompoundAction<T> addAction(Action<T> theAction);
26 public List<Action<T>> actions();
28 public Future<List<T>> execute();
32 public static class BasicCompoundAction<T> implements CompoundAction<T> {
34 private LinkedList<Action<T>> actions = new LinkedList<Action<T>>();
38 public CompoundAction<T> addAction(Action<T> theAction) {
39 this.actions.add(theAction);
43 public List<Action<T>> actions() {
47 public Future<List<T>> execute() {
48 CompoundFuture<T> cf = new CompoundFuture<T>(this.actions.size());
49 for (Action a: this.actions)
50 cf.addFuture(a.execute());
56 public static class CompoundFuture<T> extends Futures.BasicFuture<List<T>> {
58 private static OnapLoggerError errLogger = OnapLoggerError.getInstance();
59 private static OnapLoggerDebug debugLogger = OnapLoggerDebug.getInstance();
61 private LinkedList<Future<T>> futures = new LinkedList<Future<T>>();
62 private FutureHandler<T> hnd;
64 CompoundFuture(int theActionCount) {
66 hnd = new Futures.BasicHandler<T>(new CountDownLatch(theActionCount)) {
68 private List<T> results = new ArrayList<T>(Collections.nCopies(theActionCount, null));
70 protected void process(Future<T> theResult) {
71 synchronized(CompoundFuture.this) {
72 if (theResult.failed()) {
73 CompoundFuture.this.cause(theResult.cause());
74 //and stop processing of other results
79 if (this.results != null)
80 this.results.set(futures.indexOf(theResult), theResult.result());
81 debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Got result for action {}. Count at {}", futures.indexOf(theResult), this.latch.getCount());
83 if (this.latch.getCount() == 1) {//this was the last result
84 debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Got all results: {}", this.results);
85 CompoundFuture.this.result(this.results);
92 CompoundFuture<T> addFuture(Future<T> theFuture) {
94 futures.add(theFuture);
95 theFuture.setHandler(this.hnd);
103 public static class CompoundFutureHandler<T> implements FutureHandler<T> {
105 protected List<T> result = null;
106 protected List<Throwable> error = null;
107 protected CountDownLatch latch = null;
109 CompoundFutureHandler(int theResultCount) {
110 this(new CountDownLatch(theResultCount));
113 public void handle(Future<T> theResult) {
114 if (this.latch != null) {
115 this.latch.countDown();
120 throws InterruptedException, RuntimeException {
124 public BasicHandler<T> waitForCompletion() throws InterruptedException {
132 public static class Sequence<T> implements Action<List<T>> {
134 private static OnapLoggerError errLogger = OnapLoggerError.getInstance();
135 private static OnapLoggerDebug debugLogger = OnapLoggerDebug.getInstance();
137 private List<Action<T>> actions = new LinkedList<Action<T>>();
138 private int current = 0;
139 private SequenceFuture<T> future = new SequenceFuture<T>();
141 public Sequence<T> add(Action<T> theAction) {
142 if (this.current > 0)
143 throw new IllegalStateException("In execution");
144 this.actions.add(theAction);
148 /* we allow 'early' access to the future so that a client can pass its reference while
149 * it still builds the sequence, for example.
151 public Future<List<T>> future() {
155 //need to add protection when for the 'no action' case
156 public Future<List<T>> execute() {
157 debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Starting serialized execution of {}", actions);
159 next().execute().setHandler(future.hnd);
163 protected boolean hasNext() {
164 return this.current < actions.size();
167 protected Action next() {
168 return actions.get(this.current++);
171 private class SequenceFuture<T> extends Futures.BasicFuture<List<T>> {
173 private List<T> results = new LinkedList<T>();
174 private FutureHandler<T> hnd = new Futures.BasicHandler<T>() {
176 protected void process(Future<T> theResult) {
178 if (theResult.failed()) {
179 SequenceFuture.this.cause(theResult.cause());
180 //and stop processing of other results
183 SequenceFuture.this.results.add(theResult.result());
184 if (Sequence.this.hasNext()) {
185 Sequence.this.next().execute().setHandler(this);
188 SequenceFuture.this.result(SequenceFuture.this.results);