From 8e39faea546d348fa7d5930f9ceeb258cf073e31 Mon Sep 17 00:00:00 2001
From: Thorsten Vitt <thorsten.vitt@uni-wuerzburg.de>
Date: Mon, 27 May 2013 12:02:16 +0000
Subject: [PATCH] Actually return a ZIP.

This version does not have any fancy features yet, i.e. neither link
rewriting nor cool file names

git-svn-id: https://develop.sub.uni-goettingen.de/repos/textgrid/trunk/services/aggregator@14098 7c539038-3410-0410-b1ec-0f2a7bf1c452
---
 .../aggregator/tree/AggregationEntry.java     | 17 ++--
 .../textgrid/services/aggregator/zip/ZIP.java | 28 ++++---
 .../services/aggregator/zip/ZipResult.java    | 78 +++++++++++++++++++
 3 files changed, 109 insertions(+), 14 deletions(-)
 create mode 100644 src/main/java/info/textgrid/services/aggregator/zip/ZipResult.java

diff --git a/src/main/java/info/textgrid/services/aggregator/tree/AggregationEntry.java b/src/main/java/info/textgrid/services/aggregator/tree/AggregationEntry.java
index d545aa1..de94117 100644
--- a/src/main/java/info/textgrid/services/aggregator/tree/AggregationEntry.java
+++ b/src/main/java/info/textgrid/services/aggregator/tree/AggregationEntry.java
@@ -16,6 +16,8 @@
 public class AggregationEntry {
 	
 	private static Logger logger = Logger.getLogger("info.textgrid.services.aggregator.tree");
+	
+	private static URI baseURI = new File(".").toURI().normalize();
 
 	private final ObjectType metadata;
 
@@ -70,10 +72,10 @@ protected String getSimpleFileName(final boolean withExtension) {
 	 *            if true, append a content type specific extension to the last
 	 *            component of the path.
 	 */
-	protected File getFileName(final boolean withExtension) {
+	protected File getFile(final boolean withExtension) {
 		Optional<Aggregation> parent = getParent();
 		if (parent.isPresent())
-			return new File(parent.get().getFileName(false),
+			return new File(parent.get().getFile(false),
 					getSimpleFileName(withExtension));
 		else
 			return new File(getSimpleFileName(withExtension));
@@ -82,10 +84,11 @@ protected File getFileName(final boolean withExtension) {
 	/**
 	 * Returns a {@link File} representing the abstract file name for this
 	 * aggregation entry from the root of the aggregation tree. Equivalent to
-	 * {@code {@linkplain #getFileName(boolean) getFileName(true)}}.
+	 * {@code {@linkplain #getFile(boolean) getFileName(true)}}.
+	 * @param withExtension TODO
 	 */
-	public File getFileName() {
-		return getFileName(true);
+	public String getFileName(boolean withExtension) {
+		return baseURI.relativize(getFile(true).toURI()).toString();
 	}
 
 	@Override
@@ -100,4 +103,8 @@ public String toString() {
 		}
 	}
 
+	public URI getTextGridURI() {
+		return URI.create(getMetadata().getGeneric().getGenerated().getTextgridUri().getValue());
+	}
+
 }
diff --git a/src/main/java/info/textgrid/services/aggregator/zip/ZIP.java b/src/main/java/info/textgrid/services/aggregator/zip/ZIP.java
index 4bbc49d..cf68add 100644
--- a/src/main/java/info/textgrid/services/aggregator/zip/ZIP.java
+++ b/src/main/java/info/textgrid/services/aggregator/zip/ZIP.java
@@ -13,6 +13,8 @@
 import info.textgrid.services.aggregator.tree.AggregationTreeFactory;
 
 import java.net.URI;
+import java.text.MessageFormat;
+import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import javax.servlet.ServletContext;
@@ -21,8 +23,11 @@
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
+import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.core.StreamingOutput;
 
 import org.apache.cxf.jaxrs.model.wadl.Description;
 
@@ -40,8 +45,8 @@ public ZIP(final ITextGridRep repository) {
 	
 	@GET
 	@Path(value = "/{object}")
-	@Produces(value = "text/html")
-	public Response get(
+	@Produces(value = "application/zip")
+	public StreamingOutput get(
 			@Description("The TextGrid URI of the TEI document or aggregation to transform")
 			@PathParam("object") final URI uri,
 			@Description("Session ID to access protected resources")
@@ -51,21 +56,26 @@ public Response get(
 		final MetadataContainerType container = crud.readMetadata(sid, null, uri.toString());
 		final ObjectType rootObject = container.getObject();
 		
-		Aggregation tree = AggregationTreeFactory.create(rootObject, repository, sid);
+		final String format = rootObject.getGeneric().getProvided().getFormat();
+		if (!format.contains("aggregation")) {
+			logger.log(Level.SEVERE, "The requested object {0} is a {1}, not an aggregation, and thus cannot be aggregated.", new Object[] {uri,format});
+			throw new WebApplicationException(javax.ws.rs.core.Response
+					.status(Status.BAD_REQUEST)
+					.entity(MessageFormat.format(
+							"The requested object {0} is a {1}, not an aggregation, and thus cannot be aggregated.", uri,
+							format)).build());
+		}
 		
-		StringBuilder output = new StringBuilder("Following stuff (+meta) would be zipped:\n\n");
-		appendLS(tree, output);
-		
-		return Response.ok().entity(output.toString()).type("text/plain").build();
+		return new ZipResult(rootObject, repository, sid);
 	}
 
 	private void appendLS(Aggregation aggregation, StringBuilder output) {
-		output.append(aggregation.getFileName()).append(":\n");
+		output.append(aggregation.getFileName(true)).append(":\n");
 		for(AggregationEntry child : aggregation.getChildren()) 
 			if (child instanceof Aggregation) 
 				appendLS((Aggregation) child, output);
 			 else 
-				output.append(' ').append(child.getFileName()).append('\n');
+				output.append(' ').append(child.getFileName(true)).append('\n');
 	}
 
 }
diff --git a/src/main/java/info/textgrid/services/aggregator/zip/ZipResult.java b/src/main/java/info/textgrid/services/aggregator/zip/ZipResult.java
new file mode 100644
index 0000000..c42dcba
--- /dev/null
+++ b/src/main/java/info/textgrid/services/aggregator/zip/ZipResult.java
@@ -0,0 +1,78 @@
+package info.textgrid.services.aggregator.zip;
+
+import info.textgrid.namespaces.metadata.core._2010.ObjectType;
+import info.textgrid.services.aggregator.ITextGridRep;
+import info.textgrid.services.aggregator.tree.Aggregation;
+import info.textgrid.services.aggregator.tree.AggregationEntry;
+import info.textgrid.services.aggregator.tree.AggregationTreeFactory;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.text.MessageFormat;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.StreamingOutput;
+import javax.xml.bind.JAXB;
+
+import com.google.common.base.Throwables;
+import com.google.common.io.ByteStreams;
+
+public class ZipResult implements StreamingOutput {
+
+	private final ObjectType rootMetadata;
+	private final ITextGridRep repository;
+	private final String sid;
+
+	public ZipResult(ObjectType rootObject, ITextGridRep repository, String sid) {
+		this.rootMetadata = rootObject;
+		this.repository = repository;
+		this.sid = sid;
+	}
+
+	@Override
+	public void write(OutputStream output) throws IOException,
+			WebApplicationException {
+		ZipOutputStream zip = new ZipOutputStream(output);
+		zip.setComment(MessageFormat.format("# Exported from TextGrid -- www.textgrid.de\nRoot aggregation: {0}", rootMetadata.getGeneric().getGenerated().getTextgridUri().getValue()));
+		
+		Aggregation root = AggregationTreeFactory.create(rootMetadata, repository, sid);
+		writeAggregation(zip, root);
+		zip.close();
+	}
+
+	private void writeAggregation(ZipOutputStream zip, Aggregation root) throws IOException {
+		writeFile(zip, root);
+		zip.putNextEntry(new ZipEntry(root.getFileName(false).concat("/")));
+		zip.closeEntry();
+		
+		for (AggregationEntry child : root.getChildren()) {
+			if (child instanceof Aggregation)
+				writeAggregation(zip, (Aggregation) child);
+			else
+				writeFile(zip, child);
+		}
+	}
+
+	private void writeFile(ZipOutputStream zip, AggregationEntry aggregationEntry) throws IOException {
+		writeMetadata(zip, aggregationEntry);
+		zip.putNextEntry(new ZipEntry(aggregationEntry.getFileName(true)));
+		try {
+			InputStream content = repository.getContent(aggregationEntry.getTextGridURI(), sid);
+			ByteStreams.copy(content, zip);
+			zip.closeEntry();
+		} catch (Exception e) {
+			Throwables.propagateIfPossible(e, IOException.class);
+			throw new WebApplicationException(e);
+		} 
+	}
+
+	private void writeMetadata(ZipOutputStream zip, AggregationEntry aggregationEntry) throws IOException {
+		zip.putNextEntry(new ZipEntry(aggregationEntry.getFileName(true).concat(".meta")));
+		JAXB.marshal(aggregationEntry.getMetadata(), zip);
+		zip.closeEntry();
+	}
+
+}
-- 
GitLab