package org.uma.jmetal.util.measurement.impl;

import java.lang.ref.WeakReference;

import org.uma.jmetal.util.measurement.Measure;
import org.uma.jmetal.util.measurement.MeasureListener;
import org.uma.jmetal.util.measurement.PullMeasure;
import org.uma.jmetal.util.measurement.PushMeasure;

/**
 * The {@link MeasureFactory} provides some useful methods to build specific
 * {@link Measure}s.
 * 
 * @author Matthieu Vergne <matthieu.vergne@gmail.com>
 * 
 */
public class MeasureFactory {

	/**
	 * Create a {@link PullMeasure} to backup the last {@link Value} of a
	 * {@link PushMeasure}. When the {@link PushMeasure} send a notification
	 * with a given {@link Value}, this {@link Value} is stored into a variable
	 * so that it can be retrieved at any time through the method
	 * {@link PullMeasure#get()}.
	 * 
	 * @param push
	 *            a {@link PushMeasure} to backup
	 * @param initialValue
	 *            the {@link Value} to return before the next notification of
	 *            the {@link PushMeasure} is sent
	 * @return a {@link PullMeasure} allowing to retrieve the last value sent by
	 *         the {@link PushMeasure}, or the initial value if it did not send
	 *         any
	 */
	public <Value> PullMeasure<Value> createPullFromPush(
			final PushMeasure<Value> push, Value initialValue) {
		final Object[] cache = { initialValue };
		final MeasureListener<Value> listener = new MeasureListener<Value>() {

			@Override
			public void measureGenerated(Value value) {
				cache[0] = value;
			}
		};
		push.register(listener);
		return new PullMeasure<Value>() {

			@Override
			public String getName() {
				return push.getName();
			}

			@Override
			public String getDescription() {
				return push.getDescription();
			}

			@SuppressWarnings("unchecked")
			@Override
			public Value get() {
				return (Value) cache[0];
			}

			@Override
			protected void finalize() throws Throwable {
				push.unregister(listener);
				super.finalize();
			}
		};
	}

	/**
	 * Create a {@link PushMeasure} which checks at regular intervals the value
	 * of a {@link PullMeasure}. If the value have changed since the last check
	 * (or since the creation of the {@link PushMeasure}), a notification will
	 * be generated by the {@link PushMeasure} with the new {@link Value}.<br/>
	 * <br/>
	 * Notice that if the period is two small, the checking process could have a
	 * significant impact on performances, because a {@link Thread} is run in
	 * parallel to check regularly the {@link Value} modifications. If the
	 * period is too big, you could miss relevant notifications, especially if
	 * the {@link PullMeasure} change to a new {@link Value} and change back to
	 * its previous {@link Value} between two consecutive checks. In such a
	 * case, no notification will be sent because the {@link Value} during the
	 * two checks is equal.
	 * 
	 * @param pull
	 *            the {@link PullMeasure} to cover
	 * @param period
	 *            the number of milliseconds between each check
	 * @return a {@link PushMeasure} which will notify any change occurred on
	 *         the {@link PullMeasure} at the given frequency
	 */
	public <Value> PushMeasure<Value> createPushFromPull(
			PullMeasure<Value> pull, final long period) {
		final SimplePushMeasure<Value> push = new SimplePushMeasure<>(
				pull.getName(), pull.getDescription());
		final WeakReference<PullMeasure<Value>> weakPull = new WeakReference<PullMeasure<Value>>(
				pull);
		final Value initialValue = pull.get();
		Thread thread = new Thread(new Runnable() {
			private Value lastValue = initialValue;

			@Override
			public void run() {
				PullMeasure<Value> pull = null;
				while ((pull = weakPull.get()) != null) {
					Value value = pull.get();
					pull = null;
					if (value == lastValue || value != null
							&& value.equals(lastValue)) {
						// still the same, don't notify
					} else {
						lastValue = value;
						push.push(value);
					}

					try {
						Thread.sleep(period);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		});
		thread.setDaemon(true);
		thread.start();
		return push;
	}
}

@@ -3497,16 +3497,167 @@
 .get();%0A
+%09%09/*%0A%09%09 * TODO Use a static thread to run the checks of all the measures%0A%09%09 * created that way. Using a WeakHashMap could probably do the trick.%0A%09%09 */%0A
 %09%09Thread

Add a todo.