Added resolve() 

Adapted from
org.apache.taverna.platform.execution.impl.local.T2ReferenceConverter
diff --git a/taverna-databundle/src/main/java/org/apache/taverna/databundle/DataBundles.java b/taverna-databundle/src/main/java/org/apache/taverna/databundle/DataBundles.java
index c491d13..0598e10 100644
--- a/taverna-databundle/src/main/java/org/apache/taverna/databundle/DataBundles.java
+++ b/taverna-databundle/src/main/java/org/apache/taverna/databundle/DataBundles.java
@@ -1,6 +1,4 @@
-package org.apache.taverna.databundle;
 /*
- *
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
  * distributed with this work for additional information
@@ -18,8 +16,8 @@
  * specific language governing permissions and limitations
  * under the License.
  *
-*/
-
+ */
+package org.apache.taverna.databundle;
 
 import static java.nio.file.Files.createDirectories;
 import static java.nio.file.Files.delete;
@@ -33,10 +31,12 @@
 import static java.nio.file.StandardOpenOption.CREATE;
 import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
 
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.URI;
+import java.net.URL;
 import java.nio.charset.Charset;
 import java.nio.file.DirectoryIteratorException;
 import java.nio.file.DirectoryStream;
@@ -49,15 +49,15 @@
 import java.util.NavigableMap;
 import java.util.TreeMap;
 import java.util.UUID;
-import java.util.logging.Logger;
 import java.util.logging.Level;
+import java.util.logging.Logger;
 
+import org.apache.taverna.robundle.Bundle;
+import org.apache.taverna.robundle.Bundles;
 import org.apache.taverna.scufl2.api.container.WorkflowBundle;
 import org.apache.taverna.scufl2.api.io.ReaderException;
 import org.apache.taverna.scufl2.api.io.WorkflowBundleIO;
 import org.apache.taverna.scufl2.api.io.WriterException;
-import org.apache.taverna.robundle.Bundle;
-import org.apache.taverna.robundle.Bundles;
 
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
@@ -68,7 +68,6 @@
  * The style of using this class is similar to that of {@link Files}. In fact, a
  * data bundle is implemented as a set of {@link Path}s.
  * 
- * @author Stian Soiland-Reyes
  */
 public class DataBundles extends Bundles {
 	private static final class OBJECT_MAPPER {
@@ -440,6 +439,73 @@
 			throw ex.getCause();
 		}
 	}
+	
+	/**
+	 * Deeply resolve a {@link Path} to JVM objects.
+	 * <p>
+	 * This method is intended for use with a particular input/output port from 
+	 * {@link #getPorts(Path)} or {@link #getPort(Path, String)}.
+	 * <p>
+	 * If the path is <code>null</code> or {@link #isMissing(Path)},
+	 * <code>null</code> is returned.
+	 * <p>
+	 * If the path {@link #isValue(Path)}, its {@link #getStringValue(Path)} is
+	 * returned (assuming an UTF-8 encoding). NOTE: Binary formats (e.g. PNG)
+	 * will NOT be represented correctly as such a String and should be read
+	 * directly with
+	 * {@link Files#newInputStream(Path, java.nio.file.OpenOption...)}.
+	 * <p>
+	 * If the path {@link #isError(Path)}, the corresponding
+	 * {@link ErrorDocument} is returned.
+	 * <p>
+	 * If the path {@link #isReference(Path)}, either a {@link File} or a
+	 * {@link URL} is returned, depending on its protocol.
+	 * <p>
+	 * If the path {@link #isList(Path)}, a {@link List} is returned
+	 * corresponding to resolving the paths from {@link #getList(Path)}. using
+	 * this method. Thus a depth 2 path which elements are lists of values will
+	 * effectively be returned as a <code>List&lt;List&lt;String&gt;&gt;</code>,
+	 * assuming no references, errors or empty slots.
+	 * <p>
+	 * If the path is neither of the above, the {@link Path} itself is returned.
+	 * 
+	 * @param path Data bundle path to resolve
+	 * @return <code>null</code>, a {@link String}, {@link ErrorDocument},
+	 *         {@link URL}, {@link File}, {@link Path} or {@link List}
+	 *         (containing any of these).
+	 * @throws IOException
+	 *             If the path (or any of the path in a contained list) can't be
+	 *             accessed
+	 */
+	public static Object resolve(Path path) throws IOException {
+		if (path == null) { 
+			return null;
+		}
+		if (isMissing(path)) { 
+			return null;
+		} else if (isValue(path)) {
+			return getStringValue(path);
+		} else if (isReference(path)) {
+			URI reference = getReference(path);
+			String scheme = reference.getScheme();
+			if ("file".equals(scheme)) {
+				return new File(reference);
+			} else {
+				return reference.toURL();
+			}
+		} else if (isList(path)) {			
+			List<Path> list = getList(path);
+			List<Object> objectList = new ArrayList<Object>(list.size());
+			for (Path pathElement : list) {
+				objectList.add(resolve(pathElement));
+			}
+			return objectList;
+		} else if (isError(path)) {
+			return getError(path);
+		} else {
+			return path;
+		}
+	}
 
 	public static WorkflowBundleIO getWfBundleIO() {
 		if (wfBundleIO == null)
diff --git a/taverna-databundle/src/test/java/org/apache/taverna/databundle/TestDataBundles.java b/taverna-databundle/src/test/java/org/apache/taverna/databundle/TestDataBundles.java
index c5d692d..ed87bc7 100644
--- a/taverna-databundle/src/test/java/org/apache/taverna/databundle/TestDataBundles.java
+++ b/taverna-databundle/src/test/java/org/apache/taverna/databundle/TestDataBundles.java
@@ -23,9 +23,11 @@
 
 import static org.junit.Assert.*;
 
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URI;
+import java.net.URL;
 import java.nio.charset.Charset;
 import java.nio.file.DirectoryStream;
 import java.nio.file.FileAlreadyExistsException;
@@ -185,7 +187,7 @@
 	public void getInputs() throws Exception {
 		Path inputs = DataBundles.getInputs(dataBundle);
 		assertTrue(Files.isDirectory(inputs));
-		// Second time should not fail because it already exists
+		// Second time should not fail because it alreadresolvy exists
 		inputs = DataBundles.getInputs(dataBundle);
 		assertTrue(Files.isDirectory(inputs));
 		assertEquals(dataBundle.getRoot(), inputs.getParent());
@@ -523,6 +525,55 @@
 	}
     
     @Test
+    public void resolve() throws Exception {
+		Path inputs = DataBundles.getInputs(dataBundle);
+		Path list = DataBundles.getPort(inputs, "in1");
+		DataBundles.createList(list);
+		// 0 string value
+		DataBundles.setStringValue(DataBundles.newListItem(list), "test0");
+		// 1 http:// reference
+		URI reference = URI.create("http://example.com/");
+		DataBundles.setReference(DataBundles.newListItem(list), reference);
+		// 2 file:/// reference
+		Path tmpFile = Files.createTempFile("test", ".txt");
+		URI fileRef = tmpFile.toUri();
+		assertEquals("file", fileRef.getScheme());
+		DataBundles.setReference(DataBundles.newListItem(list), fileRef);
+		// 3 empty (null)
+		// 4 error
+		DataBundles.setError(DataBundles.getListItem(list,  4), "Example error", "1. Tried it\n2. Didn't work");
+		
+		
+		
+		
+		Object resolved = DataBundles.resolve(list);
+		assertTrue("Didn't resolve to a list", resolved instanceof List);
+		
+		List resolvedList = (List) resolved;
+		assertEquals("Unexpected list size", 5, resolvedList.size());
+		
+		assertTrue(resolvedList.get(0) instanceof String);
+		assertEquals("test0", resolvedList.get(0));
+		
+		assertTrue(resolvedList.get(1) instanceof URL);
+		assertEquals(reference, ((URL)resolvedList.get(1)).toURI());
+		
+		assertTrue(resolvedList.get(2) instanceof File);
+		assertEquals(tmpFile.toFile(), resolvedList.get(2));
+		
+		assertNull(resolvedList.get(3));
+		assertTrue(resolvedList.get(4) instanceof ErrorDocument);
+		assertEquals("Example error", ((ErrorDocument)resolvedList.get(4)).getMessage());
+		
+    }    
+    
+    @Test
+    public void resolveBreaksOnBinaries() throws Exception {
+    	Path inputs = DataBundles.getInputs(dataBundle);
+		Path list = DataBundles.getPort(inputs, "in1");
+    }
+    
+    @Test
 	public void setErrorArgs() throws Exception {
 		Path inputs = DataBundles.getInputs(dataBundle);
 		Path portIn1 = DataBundles.getPort(inputs, "in1");
@@ -765,6 +816,7 @@
                 Files.probeContentType(wf));
     }
 
+    // TODO: Why was this ignored? Check with taverna-language-0.15.x RC emails
     @Ignore
     @Test
     public void getWorkflowBundle() throws Exception {