// Path: Bindroid/src/com/bindroid/utils/Action.java
// public interface Action<T> {
//   /**
//    * The method to invoke.
//    * 
//    * @param parameter
//    *          the parameter to the action.
//    */
//   void invoke(T parameter);
// }
// 
// Path: Bindroid/src/com/bindroid/utils/Function.java
// public interface Function<T> {
//   /**
//    * The function to evaluate.
//    * 
//    * @return the result of the evaluation.
//    */
//   T evaluate();
// }


import java.util.LinkedList;
import java.util.Stack;
import java.util.concurrent.atomic.AtomicReference;
import com.bindroid.utils.Action;
import com.bindroid.utils.Function;

package com.bindroid.trackable;



/**
 * Provides an object to which {@link Tracker} can subscribe for notifications as well as methods
 * that allow a Tracker to evaluate an {@link Action} or {@link Function} while subscribing to
 * notifications for any trackers used during that evaluation.
 * 
 * Most uses of raw Trackables will be {@link TrackableField}s and {@link TrackableCollection}s. Raw
 * Trackables are primarily useful when manually wrapping the behavior of an object that uses the
 * Listener pattern for its notifications, calling {@link #track()} in the getter for the property
 * and {@link #updateTrackers()} when the Listener notifies of a change to its value.
 * 
 * Trackable instances are meant to be as lightweight as possible in order to minimize their
 * overhead when used in large numbers of objects.
 */
public class Trackable {
  private static ThreadLocal<Stack<Tracker>> trackersInFrame = new ThreadLocal<Stack<Tracker>>() {
    @Override
    protected synchronized Stack<Tracker> initialValue() {
      return new Stack<Tracker>();
    }
  };

  /**
   * Causes a {@link Tracker} to track any Trackables on which {@link #track()} was called while
   * executing the given {@link Action}. {@link Tracker#update()} will be called at most once for
   * all Trackables tracked while executing the action.
   * 
   * @param tracker
   *          The tracker to subscribe.
   * @param action
   *          The action to run.
   */
  public static void track(Tracker tracker, Action<Void> action) {
    Trackable.trackersInFrame.get().push(wrapTracker(tracker));
    try {
      action.invoke(null);
    } finally {
      Trackable.trackersInFrame.get().pop();
    }
  }

  /**
   * Causes a {@link Tracker} to track any Trackables on which {@link #track()} was called while
   * evaluating the given {@link Function}. The result of the function is returned.
   * {@link Tracker#update()} will be called at most once for all Trackables tracked while
   * evaluating the function.
   * 
   * @param tracker
   *          The tracker to subscribe.
   * @param function
   *          The function to evaluate.
   * @return The result of the function.
   */

// Path: Bindroid/src/com/bindroid/utils/Action.java
// public interface Action<T> {
//   /**
//    * The method to invoke.
//    * 
//    * @param parameter
//    *          the parameter to the action.
//    */
//   void invoke(T parameter);
// }
// 
// Path: Bindroid/src/com/bindroid/utils/Function.java
// public interface Function<T> {
//   /**
//    * The function to evaluate.
//    * 
//    * @return the result of the evaluation.
//    */
//   T evaluate();
// }


// Path: Bindroid/src/com/bindroid/trackable/Trackable.java
import java.util.LinkedList;
import java.util.Stack;
import java.util.concurrent.atomic.AtomicReference;
import com.bindroid.utils.Action;
import com.bindroid.utils.Function;

package com.bindroid.trackable;



/**
 * Provides an object to which {@link Tracker} can subscribe for notifications as well as methods
 * that allow a Tracker to evaluate an {@link Action} or {@link Function} while subscribing to
 * notifications for any trackers used during that evaluation.
 * 
 * Most uses of raw Trackables will be {@link TrackableField}s and {@link TrackableCollection}s. Raw
 * Trackables are primarily useful when manually wrapping the behavior of an object that uses the
 * Listener pattern for its notifications, calling {@link #track()} in the getter for the property
 * and {@link #updateTrackers()} when the Listener notifies of a change to its value.
 * 
 * Trackable instances are meant to be as lightweight as possible in order to minimize their
 * overhead when used in large numbers of objects.
 */
public class Trackable {
  private static ThreadLocal<Stack<Tracker>> trackersInFrame = new ThreadLocal<Stack<Tracker>>() {
    @Override
    protected synchronized Stack<Tracker> initialValue() {
      return new Stack<Tracker>();
    }
  };

  /**
   * Causes a {@link Tracker} to track any Trackables on which {@link #track()} was called while
   * executing the given {@link Action}. {@link Tracker#update()} will be called at most once for
   * all Trackables tracked while executing the action.
   * 
   * @param tracker
   *          The tracker to subscribe.
   * @param action
   *          The action to run.
   */
  public static void track(Tracker tracker, Action<Void> action) {
    Trackable.trackersInFrame.get().push(wrapTracker(tracker));
    try {
      action.invoke(null);
    } finally {
      Trackable.trackersInFrame.get().pop();
    }
  }

  /**
   * Causes a {@link Tracker} to track any Trackables on which {@link #track()} was called while
   * evaluating the given {@link Function}. The result of the function is returned.
   * {@link Tracker#update()} will be called at most once for all Trackables tracked while
   * evaluating the function.
   * 
   * @param tracker
   *          The tracker to subscribe.
   * @param function
   *          The function to evaluate.
   * @return The result of the function.
   */

  public static <T> T track(Tracker tracker, Function<T> function) {
