package com.datasift.client;

import org.cliffc.high_scale_lib.NonBlockingHashSet;

/**
 * @author Courtney Robinson <courtney.robinson@datasift.com>
 */
public class FutureData<T> {
    protected NonBlockingHashSet<FutureResponse<T>> listeners = new NonBlockingHashSet<FutureResponse<T>>();
    private T data;

    /**
     * Invoked when a response is received and this future data is now available for use/processing
     *
     * @param data the data received or an object wrapping said data
     */
    public void received(T data) {
        this.data = data;
        notifyListeners();
        doNotify();
    }

    /**
     * Adds an event listener that is notified when data is received
     *
     * @param response the future which should listen for a response
     * @return this to enable chaining
     */
    public FutureData<T> onData(FutureResponse<T> response) {
        this.listeners.add(response);
        //if we already received a response then notify straight away
        if (this.data != null) {
            response.apply(this.data);
            doNotify();
        }
        return this;
    }

    protected void notifyListeners() {
        for (FutureResponse<T> res : listeners) {
            res.apply(data);
        }
    }

    protected void doNotify() {
        synchronized (this) {
            notify();
        }
    }

    /**
     * Forces the client to wait until a response is received before returning
     *
     * @return a result instance
     * @throws InterruptedException if an interrupt is thrown it is possible that a response isn't available yet
     *                              the user must check to ensure null isn't returned
     */
    public T sync() throws InterruptedException {
        synchronized (this) {
            wait();
        }
        return data;
    }
}

@@ -306,16 +306,719 @@
  data;%0A%0A
+    /**%0A     * Wraps any object in a %7B@link FutureData%7D instance%0A     * %3Cp/%3E%0A     * Intended use is to enable any object obtained without a future to be passed to API methods.%0A     * This allows API methods to accept FutureData objects and alleviates the need for a user to add%0A     * many callbacks and instead just pass futures around as if they were already obtained values%0A     *%0A     * @param obj the object to wrap%0A     * @param %3CA%3E the type of the object%0A     * @return a future that will fire onData events for the given object%0A     */%0A    public static %3CA%3E FutureData%3CA%3E wrap(A obj) %7B%0A        FutureData%3CA%3E future = new FutureData%3CA%3E();%0A        future.data = obj;%0A        return future;%0A    %7D%0A%0A
     /**%0A

Make it possible to simplify the API by allowing futures to be passed around * Intended use is to enable any object obtained without a future to be passed to API methods. * This allows API methods to accept FutureData objects and alleviates the need for a user to add * many callbacks and instead just pass futures around as if they were already obtained values