diff --git a/src/main/java/info/textgrid/services/aggregator/AbstractExporter.java b/src/main/java/info/textgrid/services/aggregator/AbstractExporter.java index ded89fc1aeb794caf9ea70033517450f16654a9e..132c91bf44d62c4bbc5439895c3ec1f885dccc39 100644 --- a/src/main/java/info/textgrid/services/aggregator/AbstractExporter.java +++ b/src/main/java/info/textgrid/services/aggregator/AbstractExporter.java @@ -1,5 +1,6 @@ package info.textgrid.services.aggregator; +import info.textgrid.namespaces.metadata.core._2010.MetadataContainerType; import info.textgrid.namespaces.metadata.core._2010.ObjectType; import info.textgrid.namespaces.middleware.tgcrud.services.tgcrudservice.AuthFault; import info.textgrid.namespaces.middleware.tgcrud.services.tgcrudservice.IoFault; @@ -7,6 +8,7 @@ import info.textgrid.namespaces.middleware.tgcrud.services.tgcrudservice.ObjectNotFoundFault; import info.textgrid.namespaces.middleware.tgcrud.services.tgcrudservice.ProtocolNotImplementedFault; import info.textgrid.services.aggregator.ITextGridRep.TGOSupplier; +import info.textgrid.utils.export.filenames.DefaultFilenamePolicy; import java.io.IOException; import java.io.InputStream; @@ -17,11 +19,14 @@ import java.util.logging.Level; import java.util.logging.Logger; +import javax.ws.rs.core.CacheControl; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Request; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.ResponseBuilder; import javax.ws.rs.core.StreamingOutput; +import javax.xml.datatype.DatatypeConstants; +import javax.xml.datatype.XMLGregorianCalendar; import net.sf.saxon.s9api.SaxonApiException; @@ -145,11 +150,21 @@ public AbstractExporter(final ITextGridRep repository, stopwatch.start(); this.repository = repository; this.request = request; - this.rootURIs = ArgUtils.extractURIs(uriList); + this.rootURIs = extractURIs(uriList); if (rootURIs.length > 1) this.sourceType = SourceType.BASKET; } + private static URI[] extractURIs(final String uriList) { + final String[] uriStrings = uriList.split(","); + Preconditions.checkArgument(uriStrings.length > 0, "No URI found in %s", uriList); + final URI[] uris = new URI[uriStrings.length]; + for (int i = 0; i < uriStrings.length; i++) { + uris[i] = URI.create(uriStrings[i]); + } + return uris; + } + /** * Returns an array with the metadata records of all root objects. */ @@ -157,8 +172,12 @@ protected ObjectType[] getRootObjects() throws MetadataParseFault, ObjectNotFoundFault, IoFault, AuthFault { if (rootObjects == null) { if (sourceType == SourceType.BASKET) { - rootObjects = ArgUtils.extractRootObjects(rootURIs, - sid.orNull(), repository.getCRUDService()); + final ObjectType[] objects = new ObjectType[rootURIs.length]; + for (int i = 0; i < rootURIs.length; i++) { + final MetadataContainerType container = repository.getCRUDService().readMetadata(sid.orNull(), null, rootURIs[i].toString()); + objects[i] = container.getObject(); + } + rootObjects = objects; logger.log(Level.INFO, MessageFormat.format( "Collected root objects for basket {0} after {1}", rootURIs, stopwatch.toString())); @@ -242,8 +261,16 @@ public AbstractExporter sid(final String sid) { */ protected Date getLastModified() throws MetadataParseFault, ObjectNotFoundFault, IoFault, AuthFault { - if (lastModified == null) - this.lastModified = RESTUtils.createLastModified(getRootObjects()); + if (lastModified == null) { + XMLGregorianCalendar youngest = null; + for (final ObjectType object : getRootObjects()) { + final XMLGregorianCalendar current = object.getGeneric().getGenerated().getLastModified(); + if (youngest == null || current.compare(youngest) == DatatypeConstants.GREATER) + youngest = current; + } + youngest.setMillisecond(0); + this.lastModified = youngest.toGregorianCalendar().getTime(); + } return lastModified; } @@ -324,8 +351,12 @@ protected ResponseBuilder getResponseBuilder() throws MetadataParseFault, */ protected void configureCache() throws MetadataParseFault, ObjectNotFoundFault, IoFault, AuthFault { - RESTUtils.configureCache(getResponseBuilder(), getLastModified(), - sid.isPresent()); + ResponseBuilder builder = getResponseBuilder(); + builder.lastModified(getLastModified()); + final CacheControl cacheControl = new CacheControl(); + cacheControl.setPrivate(sid.isPresent()); + cacheControl.setMaxAge(86400); // one day + builder.cacheControl(cacheControl); } /** @@ -338,12 +369,36 @@ protected void configureCache() throws MetadataParseFault, */ protected void configureFilename() throws MetadataParseFault, ObjectNotFoundFault, IoFault, AuthFault { + getResponseBuilder().header( "Content-Disposition", getDisposition() + ";filename=\"" - + ArgUtils.createFilename(getRootObjects(), getTitle(), - getFileExtension()) + "\""); + + calculateFilename() + "\""); + } + + + private String calculateFilename() throws MetadataParseFault, ObjectNotFoundFault, IoFault, AuthFault { + final String title = calculateTitle(); + final StringBuilder result = new StringBuilder(title.length() + 30); + result.append(DefaultFilenamePolicy.INSTANCE.translate(title)); + if (getRootObjects().length == 1) + result.append('.').append(URI.create(rootObjects[0].getGeneric().getGenerated().getTextgridUri().getValue()).getSchemeSpecificPart()); + if (fileExtension != null && !fileExtension.isEmpty()) + result.append('.').append(fileExtension); + return result.toString(); + } + + private String calculateTitle() throws MetadataParseFault, ObjectNotFoundFault, IoFault, AuthFault { + ObjectType[] rootObjects = getRootObjects(); + if (title != null && !title.isEmpty()) + return title; + else if (rootObjects.length == 0) + return "(nothing)"; + else if (rootObjects.length == 1) + return rootObjects[0].getGeneric().getProvided().getTitle().get(0); + else + return rootObjects[0].getGeneric().getProvided().getTitle().get(0) + " etc"; } /** diff --git a/src/main/java/info/textgrid/services/aggregator/ArgUtils.java b/src/main/java/info/textgrid/services/aggregator/ArgUtils.java deleted file mode 100644 index 46e8c122bae2c0050238fcabffbddeee47a3a94d..0000000000000000000000000000000000000000 --- a/src/main/java/info/textgrid/services/aggregator/ArgUtils.java +++ /dev/null @@ -1,68 +0,0 @@ -package info.textgrid.services.aggregator; - -import info.textgrid.namespaces.metadata.core._2010.MetadataContainerType; -import info.textgrid.namespaces.metadata.core._2010.ObjectType; -import info.textgrid.namespaces.middleware.tgcrud.services.tgcrudservice.AuthFault; -import info.textgrid.namespaces.middleware.tgcrud.services.tgcrudservice.IoFault; -import info.textgrid.namespaces.middleware.tgcrud.services.tgcrudservice.MetadataParseFault; -import info.textgrid.namespaces.middleware.tgcrud.services.tgcrudservice.ObjectNotFoundFault; -import info.textgrid.namespaces.middleware.tgcrud.services.tgcrudservice.TGCrudService; -import info.textgrid.utils.export.filenames.DefaultFilenamePolicy; - -import java.net.URI; - -import com.google.common.base.Preconditions; - -public class ArgUtils { - - @Deprecated - public static ObjectType[] extractRootObjects(final String uriList, final String sid, - final TGCrudService crud) throws MetadataParseFault, - ObjectNotFoundFault, IoFault, AuthFault { - return extractRootObjects(extractURIs(uriList), sid, crud); - } - - public static URI[] extractURIs(final String uriList) { - final String[] uriStrings = uriList.split(","); - Preconditions.checkArgument(uriStrings.length > 0, "No URI found in %s", uriList); - final URI[] uris = new URI[uriStrings.length]; - for (int i = 0; i < uriStrings.length; i++) { - uris[i] = URI.create(uriStrings[i]); - } - return uris; - } - - public static ObjectType[] extractRootObjects(final URI[] uris, final String sid, - final TGCrudService crud) throws MetadataParseFault, - ObjectNotFoundFault, IoFault, AuthFault { - final ObjectType[] objects = new ObjectType[uris.length]; - for (int i = 0; i < uris.length; i++) { - final MetadataContainerType container = crud.readMetadata(sid, null, uris[i].toString()); - objects[i] = container.getObject(); - } - return objects; - } - - public static String createTitle(final ObjectType[] rootObjects, final String title) { - if (title != null && !title.isEmpty()) - return title; - else if (rootObjects.length == 0) - return "(nothing)"; - else if (rootObjects.length == 1) - return rootObjects[0].getGeneric().getProvided().getTitle().get(0); - else - return rootObjects[0].getGeneric().getProvided().getTitle().get(0) + " etc"; - } - - public static String createFilename(final ObjectType[] rootObjects, final String suggestedTitle, final String extension) { - final String title = createTitle(rootObjects, suggestedTitle); - final StringBuilder result = new StringBuilder(title.length() + 30); - result.append(DefaultFilenamePolicy.INSTANCE.translate(title)); - if (rootObjects.length == 1) - result.append('.').append(URI.create(rootObjects[0].getGeneric().getGenerated().getTextgridUri().getValue()).getSchemeSpecificPart()); - if (extension != null && !extension.isEmpty()) - result.append('.').append(extension); - return result.toString(); - } - -} diff --git a/src/main/java/info/textgrid/services/aggregator/RESTUtils.java b/src/main/java/info/textgrid/services/aggregator/RESTUtils.java deleted file mode 100644 index f466c1945d2a7d452923ce393e37747e7d6dc8ea..0000000000000000000000000000000000000000 --- a/src/main/java/info/textgrid/services/aggregator/RESTUtils.java +++ /dev/null @@ -1,61 +0,0 @@ -package info.textgrid.services.aggregator; - -import info.textgrid.namespaces.metadata.core._2010.ObjectType; - -import java.util.Date; - -import javax.ws.rs.core.CacheControl; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.ResponseBuilder; -import javax.ws.rs.core.UriBuilder; -import javax.xml.datatype.DatatypeConstants; -import javax.xml.datatype.XMLGregorianCalendar; - -public class RESTUtils { - - public static ResponseBuilder addAttachmentFilename(final ResponseBuilder builder, final String fileName) { - final String asciiFileName = fileName.replaceAll("[^A-Za-z0-9.-]", "_"); - final String extendedNameSpec = "UTF-8''" + UriBuilder.fromPath(fileName).build().toASCIIString(); - - if (!asciiFileName.equals(fileName)) - builder.header("Content-Disposition", "attachment;filename*=\"" + extendedNameSpec + "\";" + - /* builder.header("Content-Disposition", */ "filename=\"" + asciiFileName + "\"" ); - else - builder.header("Content-Disposition", "attachment;filename=\"" + asciiFileName + "\"" ); - builder.header("X-Attachment-Orig-Filename", fileName); - return builder; - } - - public static ResponseBuilder attachmentResponse(final String fileName) { - return addAttachmentFilename(Response.ok(), fileName); - } - - /** - * Creates a last-modified date suitable for use in HTTP headers. I.e. it extrats - * the lastModified header fields from the given objects, finds the youngest one - * and strips the millisecond part. - * - * @param objects The objects to consider in the calculation - * @return a date/time stamp, with the milliseconds stripped - */ - public static Date createLastModified(final ObjectType... objects) { - XMLGregorianCalendar youngest = null; - for (final ObjectType object : objects) { - final XMLGregorianCalendar current = object.getGeneric().getGenerated().getLastModified(); - if (youngest == null || current.compare(youngest) == DatatypeConstants.GREATER) - youngest = current; - } - youngest.setMillisecond(0); - return youngest.toGregorianCalendar().getTime(); - } - - public static ResponseBuilder configureCache(final ResponseBuilder builder, Date lastModified, boolean isPrivate) { - builder.lastModified(lastModified); - final CacheControl cacheControl = new CacheControl(); - cacheControl.setPrivate(isPrivate); - cacheControl.setMaxAge(86400); // one day - builder.cacheControl(cacheControl); - return builder; - } - -} diff --git a/src/test/java/info/textgrid/services/aggregator/ArgUtilsTest.java b/src/test/java/info/textgrid/services/aggregator/ArgUtilsTest.java deleted file mode 100644 index 0a21dee82a61c5701c6f1606b705056455398a1f..0000000000000000000000000000000000000000 --- a/src/test/java/info/textgrid/services/aggregator/ArgUtilsTest.java +++ /dev/null @@ -1,66 +0,0 @@ -package info.textgrid.services.aggregator; - -import static org.junit.Assert.*; -import info.textgrid.namespaces.metadata.core._2010.MetadataContainerType; -import info.textgrid.namespaces.metadata.core._2010.ObjectType; - -import java.io.InputStream; -import java.util.Date; - -import javax.xml.bind.JAXB; - -import org.junit.Before; -import org.junit.Test; - -public class ArgUtilsTest { - - private ObjectType metadata0; - private ObjectType metadata1; - private ObjectType[] metadata; - - @Before - public void setup() { - InputStream stream0 = getClass().getClassLoader().getResourceAsStream("kscz.0.meta"); - metadata0 = JAXB.unmarshal(stream0, MetadataContainerType.class).getObject(); - InputStream stream1 = getClass().getClassLoader().getResourceAsStream("ksd3.0.meta"); - metadata1 = JAXB.unmarshal(stream1, MetadataContainerType.class).getObject(); - metadata = new ObjectType[] { metadata0, metadata1 }; - } - -// Requires CRUD, ie IT -// @Test -// public void testExtractRootObjects() { -// fail("Not yet implemented"); -// } - - @Test - public void testCreateTitle2() { - String title = ArgUtils.createTitle(metadata, null); - assertEquals("Erzählung etc", title); - } - @Test - public void testCreateTitle1() { - String title = ArgUtils.createTitle(new ObjectType[] { metadata0 }, null); - assertEquals("Erzählung", title); - } - - @Test - public void testCreateFilename2() { - String filename = ArgUtils.createFilename(metadata, null, "zip"); - assertEquals("Erzaehlung_etc.zip", filename); - } - - @Test - public void testCreateFilename1() { - String filename = ArgUtils.createFilename(new ObjectType[] { metadata0 }, null, "html"); - assertEquals("Erzaehlung.kscz.0.html", filename); - } - - @Test - public void testCreateLastModified() { - Date lastModified = RESTUtils.createLastModified(metadata); - Date expected = new Date(1325700856000l); - assertEquals(expected, lastModified); - } - -}