Skip to content
Snippets Groups Projects
Commit ab48a34c authored by Thorsten Vitt's avatar Thorsten Vitt
Browse files

Refactored EPUB to use CorpusBasedExporter

parent 68a92ee3
No related branches found
No related tags found
No related merge requests found
package info.textgrid.services.aggregator.epub;
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.ProtocolNotImplementedFault;
import info.textgrid.namespaces.middleware.tgcrud.services.tgcrudservice.TGCrudService;
import info.textgrid.services.aggregator.ArgUtils;
import info.textgrid.services.aggregator.ITextGridRep;
import info.textgrid.services.aggregator.RESTUtils;
import info.textgrid.services.aggregator.StylesheetManager;
import info.textgrid.services.aggregator.TextGridRepProvider;
import info.textgrid.services.aggregator.teicorpus.TEICorpusSerializer;
import info.textgrid.utils.export.filenames.DefaultFilenamePolicy;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.Date;
import java.util.logging.Logger;
import javax.servlet.ServletContext;
......@@ -30,28 +19,21 @@
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.Request;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.xml.transform.stream.StreamSource;
import net.sf.saxon.s9api.SaxonApiException;
import net.sf.saxon.s9api.XsltExecutable;
import net.sf.saxon.s9api.XsltTransformer;
import org.apache.cxf.jaxrs.model.wadl.Description;
import com.google.common.base.Optional;
import com.google.common.io.Files;
import com.google.common.io.InputSupplier;
@Path("/epub")
@Description("Converts the given TEI object or the aggregation of TEI objects to an E-Book in EPUB format")
public class EPUB {
private static final URI EPUB_XSL = URI.create("/WEB-INF/stylesheets/epub.xsl");
private ITextGridRep repository = TextGridRepProvider.getInstance();
......@@ -84,72 +66,14 @@ public Response get(
@Description("Session ID for accessing protected objects") @QueryParam("sid") final String sid,
@Context final Request request)
throws ObjectNotFoundFault, MetadataParseFault, IoFault, AuthFault,
ProtocolNotImplementedFault {
logger.fine("EPUB called for root objects: " + uriList);
final TGCrudService crud = repository.getCRUDService();
try {
final ObjectType[] rootObjects = ArgUtils.extractRootObjects(uriList, sid, crud);
// Return fast if client already has our file
final Date lastModified = RESTUtils.createLastModified(rootObjects);
final ResponseBuilder builder = request.evaluatePreconditions(lastModified);
if (builder != null) {
logger.fine("Skipping EPUB generation for "+ uriList+ " due to request preconditions");
return builder.build();
}
final String title = ArgUtils.createTitle(rootObjects, titleParam);
final boolean multiple = (rootObjects.length > 1 || rootObjects.length == 1 && rootObjects[0].getGeneric().getProvided().getFormat().contains("aggregation"));
final File workingDir = Files.createTempDir();
logger.fine("Using " + workingDir + " to build the E-Book");
final File corpus = new File(workingDir, "corpus.xml");
if (multiple) {
// First, use the aggregator to create a TEI corpus file to build on
final TEICorpusSerializer corpusSerializer = new TEICorpusSerializer(rootObjects, true, sid);
corpusSerializer.setTitle(title);
final FileOutputStream corpusOutput = new FileOutputStream(corpus);
corpusSerializer.write(corpusOutput);
corpusOutput.close();
} else {
final InputStream tei = repository.getContent(URI.create(rootObjects[0].getGeneric().getGenerated().getTextgridUri().getValue()), sid);
Files.copy(new InputSupplier<InputStream>() {
@Override
public InputStream getInput() throws IOException {
return tei;
}
}, corpus);
}
// Now, run the EPUB stylesheet
// TODO cache the saxon stuff
final XsltTransformer transformer;
if (xsluri == null) {
transformer = getStylesheetManager().getStylesheet(EPUB_XSL, Optional.fromNullable(sid), false, true).load();
} else {
transformer = getStylesheetManager().getStylesheet(xsluri, Optional.fromNullable(sid), false, false).load();
}
transformer.setDestination(getStylesheetManager().xsltProcessor.newSerializer(new File(
workingDir, "output.xml")));
transformer.setSource(new StreamSource(corpus));
transformer.transform();
final ResponseBuilder responseBuilder = RESTUtils
.attachmentResponse(
DefaultFilenamePolicy.INSTANCE.translate(title)
+ ".epub").type("application/epub+zip");
RESTUtils.configureCache(responseBuilder, lastModified, sid == null || sid.isEmpty());
return responseBuilder.entity(new EPUBSerializer(workingDir, repository, corpus,
sid)).build();
} catch (final FileNotFoundException e) {
throw new WebApplicationException(e);
} catch (final IOException e) {
throw new WebApplicationException(e);
} catch (final SaxonApiException e) {
throw new WebApplicationException(e);
}
ProtocolNotImplementedFault, IOException, SaxonApiException {
final EPUBSerializer serializer = new EPUBSerializer(repository, getStylesheetManager(), uriList, Optional.fromNullable(sid), request);
serializer.setStylesheet(xsluri);
serializer.setTitle(titleParam);
return serializer.createResponse().build();
}
}
......@@ -5,7 +5,9 @@
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.ProtocolNotImplementedFault;
import info.textgrid.services.aggregator.CorpusBasedExporter;
import info.textgrid.services.aggregator.ITextGridRep;
import info.textgrid.services.aggregator.StylesheetManager;
import info.textgrid.utils.linkrewriter.ConfigurableXMLRewriter;
import java.io.File;
......@@ -17,50 +19,99 @@
import java.util.Deque;
import java.util.LinkedList;
import java.util.Map.Entry;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.StreamingOutput;
import javax.xml.stream.XMLStreamException;
import javax.xml.transform.Source;
import net.sf.saxon.s9api.SaxonApiException;
import net.sf.saxon.s9api.XsltTransformer;
import org.apache.cxf.helpers.FileUtils;
import org.xml.sax.SAXException;
import com.google.common.base.Optional;
import com.google.common.io.ByteStreams;
import com.google.common.io.Files;
public class EPUBSerializer implements StreamingOutput {
private final File workingDir;
private final ITextGridRep repository;
private final File corpus;
private final String sid;
public EPUBSerializer(final File workingDir, final ITextGridRep repository,
final File corpus, final String sid) {
super();
this.workingDir = workingDir;
this.repository = repository;
this.corpus = corpus;
public class EPUBSerializer extends CorpusBasedExporter implements
StreamingOutput {
private static final URI EPUB_XSL = URI
.create("/WEB-INF/stylesheets/epub.xsl");
private static final Logger logger = Logger.getLogger(EPUBSerializer.class
.getCanonicalName());
private final Optional<String> sid;
private StylesheetManager stylesheetManager;
private File workingDir;
private Optional<URI> providedStylesheet = Optional.absent();
private File corpus;
public EPUBSerializer(final ITextGridRep repository,
final StylesheetManager stylesheetManager, final String uriList,
final Optional<String> sid, final Request request) {
super(repository, request, uriList);
this.stylesheetManager = stylesheetManager;
this.sid = sid;
setMediaType("application/epub+zip");
setFileExtension("epub");
}
public void setStylesheet(final URI stylesheet) {
this.providedStylesheet = Optional.fromNullable(stylesheet);
}
@Override
public ResponseBuilder createResponse() throws MetadataParseFault,
ObjectNotFoundFault, IoFault, AuthFault,
ProtocolNotImplementedFault, IOException, SaxonApiException {
super.createResponse();
if (isNotModified())
return getResponseBuilder();
workingDir = Files.createTempDir();
logger.fine("Using " + workingDir + " to build the E-Book");
corpus = new File(workingDir, "corpus.xml");
setBufferFactory(new FileBufferFactory(corpus));
final Source source = loadSource(true);
final XsltTransformer transformer;
if (providedStylesheet.isPresent())
transformer = getStylesheetManager().getStylesheet(
providedStylesheet.get(), sid, false, false).load();
else
transformer = getStylesheetManager().getStylesheet(EPUB_XSL, sid,
false, true).load();
transformer.setDestination(getStylesheetManager().xsltProcessor
.newSerializer(new File(workingDir, "output.xml")));
transformer.setSource(source);
transformer.transform();
return getResponseBuilder();
}
private StylesheetManager getStylesheetManager() {
return stylesheetManager;
}
@Override
public void write(final OutputStream output) throws IOException,
WebApplicationException {
WebApplicationException {
final ZipOutputStream zip = new ZipOutputStream(output);
try {
// first entry is the uncompressed mimetype marker
new MimeTypeEntry("application/epub+zip").writeTo(zip);
// now filtered filesystem structure. FIXME add rewriting +
// images
final File mimeTypeFile = new File(workingDir, "mimetype");
final URI base = workingDir.toURI();
final File opsDir = new File(workingDir, "OPS");
......@@ -96,11 +147,11 @@ public void write(final OutputStream output) throws IOException,
zip.putNextEntry(new ZipEntry(name));
if (Files.getFileExtension(name).equals("html")) {
xhtmlRewriter.rewrite(
new FileInputStream(child), zip);
} else if (Files.getFileExtension(name).equals("opf")) {
opfRewriter.rewrite(new FileInputStream(child),
xhtmlRewriter.rewrite(new FileInputStream(child),
zip);
} else if (Files.getFileExtension(name).equals("opf")) {
opfRewriter
.rewrite(new FileInputStream(child), zip);
} else {
Files.copy(child, zip);
}
......@@ -111,11 +162,14 @@ public void write(final OutputStream output) throws IOException,
// now we need to add those files that are referenced by
// absolute URI in the manifest
for (final Entry<URI, String> externalItem : manifest.externalItems.entrySet()) {
final String pseudoFileName = base.relativize(new File(opsDir, manifest.getFileName(externalItem.getKey().toString())).toURI()).getPath();
for (final Entry<URI, String> externalItem : manifest.externalItems
.entrySet()) {
final String pseudoFileName = base.relativize(
new File(opsDir, manifest.getFileName(externalItem
.getKey().toString())).toURI()).getPath();
zip.putNextEntry(new ZipEntry(pseudoFileName));
ByteStreams.copy(
repository.getContent(externalItem.getKey(), sid), zip);
repository.getContent(externalItem.getKey(), sid.orNull()), zip);
zip.closeEntry();
}
} catch (final SAXException e) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment