Switch to FutureData; add SegmentedClient
diff --git a/src/main/java/com/intel/jndn/utils/FutureData.java b/src/main/java/com/intel/jndn/utils/FutureData.java
new file mode 100644
index 0000000..5c881ee
--- /dev/null
+++ b/src/main/java/com/intel/jndn/utils/FutureData.java
@@ -0,0 +1,183 @@
+/*
+ * File name: FuturePacket.java
+ *
+ * Purpose: Reference to a Packet that has yet to be returned from the network.
+ *
+ * © Copyright Intel Corporation. All rights reserved.
+ * Intel Corporation, 2200 Mission College Boulevard,
+ * Santa Clara, CA 95052-8119, USA
+ */
+package com.intel.jndn.utils;
+
+import java.io.IOException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import net.named_data.jndn.Data;
+import net.named_data.jndn.Face;
+import net.named_data.jndn.Name;
+import net.named_data.jndn.encoding.EncodingException;
+
+/**
+ * Reference to a Packet that has yet to be returned from the network; see use
+ * in WindowBuffer.java. Usage:
+ * <pre><code>
+ * FuturePacket futurePacket = new FuturePacket(face);
+ * face.expressInterest(interest, new OnData(){
+ * ... futurePacket.resolve(data); ...
+ * }, new OnTimeout(){
+ * ... futurePacket.reject(new TimeoutException());
+ * });
+ * Packet resolvedPacket = futurePacket.get(); // will block and call face.processEvents() until complete
+ * </code></pre>
+ *
+ * @author Andrew Brown <andrew.brown@intel.com>
+ */
+public class FutureData implements Future<Data> {
+
+ private final Face face;
+ private final Name name;
+ private Data data;
+ private boolean cancelled = false;
+ private Throwable error;
+
+ /**
+ * Constructor
+ *
+ * @param face
+ * @param name
+ */
+ public FutureData(Face face, Name name) {
+ this.face = face;
+ this.name = new Name(name);
+ }
+
+ /**
+ * Get the packet interest name
+ *
+ * @return
+ */
+ public Name getName() {
+ return name;
+ }
+
+ /**
+ * Cancel the current request.
+ *
+ * @param mayInterruptIfRunning
+ * @return
+ */
+ @Override
+ public boolean cancel(boolean mayInterruptIfRunning) {
+ cancelled = true;
+ return cancelled;
+ }
+
+ /**
+ * Determine if this request is cancelled.
+ *
+ * @return
+ */
+ @Override
+ public boolean isCancelled() {
+ return cancelled;
+ }
+
+ /**
+ * Determine if the request has completed (successfully or not).
+ *
+ * @return
+ */
+ @Override
+ public boolean isDone() {
+ return data != null || error != null;
+ }
+
+ /**
+ * Set the packet when successfully retrieved; unblocks get().
+ *
+ * @param d
+ */
+ public void resolve(Data d) {
+ data = d;
+ }
+
+ /**
+ * Set the exception when request failed; unblocks get().
+ *
+ * @param e
+ */
+ public void reject(Throwable e) {
+ error = e;
+ }
+
+ /**
+ * Block until packet is retrieved.
+ *
+ * @return
+ * @throws InterruptedException
+ * @throws ExecutionException
+ */
+ @Override
+ public Data get() throws InterruptedException, ExecutionException {
+ while (!isDone() && !isCancelled()) {
+ try {
+ synchronized (face) {
+ face.processEvents();
+ }
+ } catch (EncodingException | IOException e) {
+ throw new ExecutionException("Failed to retrieve packet.", e);
+ }
+ }
+ // case: cancelled
+ if (cancelled) {
+ throw new InterruptedException("Interrupted by user.");
+ }
+ // case: error
+ if (error != null) {
+ throw new ExecutionException("Future rejected with error.", error);
+ }
+ // case: packet
+ return data;
+ }
+
+ /**
+ * Block until packet is retrieved or timeout is reached.
+ *
+ * @param timeout
+ * @param unit
+ * @return
+ * @throws InterruptedException
+ * @throws ExecutionException
+ * @throws TimeoutException
+ */
+ @Override
+ public Data get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
+ long interval = TimeUnit.MILLISECONDS.convert(timeout, unit);
+ long endTime = System.currentTimeMillis() + interval;
+ while (!isDone() && !isCancelled() && System.currentTimeMillis() < endTime) {
+ try {
+ synchronized (face) {
+ face.processEvents();
+ }
+ } catch (EncodingException | IOException e) {
+ throw new ExecutionException("Failed to retrieve packet.", e);
+ }
+ }
+ // case: timed out
+ if (System.currentTimeMillis() < endTime) {
+ throw new TimeoutException("Timed out");
+ }
+ // case: cancelled
+ if (cancelled) {
+ throw new InterruptedException("Interrupted by user.");
+ }
+ // case: error
+ if (error != null) {
+ throw new ExecutionException("Future rejected.", error);
+ }
+ // case: packet
+ return data;
+ }
+}