Commit 83dca441 authored by thorsten.vitt's avatar thorsten.vitt
Browse files

Merge branch 'release/1.4.9'

parents 3fe2f481 fe96cc45
......@@ -25,7 +25,6 @@
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
<attribute name="org.eclipse.jst.component.dependency" value="/WEB-INF/lib"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/webapp/WEB-INF">
......@@ -35,7 +34,7 @@
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
<attributes>
<attribute name="owner.project.facets" value="java"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
......
......@@ -139,6 +139,20 @@ Custom stylesheets will generally be able to resolve ``textgrid:`` URIs using fu
- *ID* might be an ``xml:id``. If this is passed, your stylesheet should *only* render the XML fragment with the given ID.
Embedded mode — HTML rendering at textgridrep.de
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
textgridrep.de uses the aggregator to render TEI files as HTML. It will activate ``embedded=true``, and it will embed resulting XHTML fragment into its own HTML. If you use your own XSLT, this means, in addition to the notes for custom XSLT above:
* Your stylesheet must return valid XHTML.
* Embedded ``<style>`` elements from the HTML header will be moved to the body and converted to a `scoped style element <https://davidwalsh.name/scoped-css>`_.
* The ``<body>`` element will be converted to a ``<div class="body">`` and returned to be embedded into the container HTML. Everything else your XSLT delivers, especially the HTML ``<head>``, is thrown away. Thus, if you load any JavaScript, make sure to load it from ``<script>`` tags in the body.
You will of course need to pay attention to the usual web development issues, e.g., make sure that any resource you load from within the HTML can be loaded from within pages that are served at <https://textgridrep.de/>.
You can use the simulate mode to partially simulate embedding; it will run the same embed code, but instead of returning just an XHTML fragment it embeds the fragment into a full HTML frame that resembles the TextGridRep.de design. This method can also be used even for unpublished data from within the TextGridLab using the TextGridRep Preview tool that is available from the Marketplace.
Generating a Table of Contents
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
......
......@@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>info.textgrid.services</groupId>
<artifactId>aggregator</artifactId>
<version>1.4.8</version>
<version>1.4.9</version>
<packaging>war</packaging>
<name>TextGrid Aggregator Service</name>
......
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.ProtocolNotImplementedFault;
import info.textgrid.services.aggregator.ITextGridRep.TGOSupplier;
import info.textgrid.utils.export.filenames.DefaultFilenamePolicy;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
......@@ -30,8 +20,6 @@
import javax.xml.datatype.DatatypeConstants;
import javax.xml.datatype.XMLGregorianCalendar;
import net.sf.saxon.s9api.SaxonApiException;
import com.google.common.base.Joiner;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
......@@ -39,6 +27,17 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
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.ProtocolNotImplementedFault;
import info.textgrid.services.aggregator.ITextGridRep.TGOSupplier;
import info.textgrid.utils.export.filenames.DefaultFilenamePolicy;
import net.sf.saxon.s9api.SaxonApiException;
/**
* The abstract base class for all aggregators/exporters. This tries to capture
* all behavior common to the various format specific exporters, and it tries to
......@@ -80,10 +79,19 @@ public abstract class AbstractExporter implements StreamingOutput {
private static final Logger logger = Logger
.getLogger(AbstractExporter.class.getCanonicalName());
private Optional<String> sid = Optional.absent();
private boolean sandbox = false;
protected Optional<String> getSid() {
return sid;
}
public boolean getSandbox() {
return sandbox;
}
public void sandbox(boolean sandbox) {
this.sandbox = sandbox;
}
public SourceType getSourceType() {
return sourceType;
......@@ -172,7 +180,7 @@ private static URI[] extractURIs(final String uriList) {
}
protected void initFromSearch(final String query, final String target, int start, int stop, List<String> filter) {
rootObjects = SearchResultList.create(repository.getPublicSearchClient(), query, target, filter).start(start).stop(stop);
rootObjects = SearchResultList.create(repository.getPublicSearchClient(), query, target, filter, getSandbox()).start(start).stop(stop);
}
/**
......@@ -395,9 +403,11 @@ private String calculateFilename() throws MetadataParseFault, ObjectNotFoundFaul
final StringBuilder result = new StringBuilder(title.length() + 30);
result.append(DefaultFilenamePolicy.INSTANCE.translate(title));
Iterator<ObjectType> roots = getRootObjects().iterator();
ObjectType first = roots.next();
if (!roots.hasNext())
result.append('.').append(URI.create(first.getGeneric().getGenerated().getTextgridUri().getValue()).getSchemeSpecificPart());
if (roots.hasNext()) {
ObjectType first = roots.next();
if (!roots.hasNext())
result.append('.').append(URI.create(first.getGeneric().getGenerated().getTextgridUri().getValue()).getSchemeSpecificPart());
}
if (fileExtension != null && !fileExtension.isEmpty())
result.append('.').append(fileExtension);
return result.toString();
......
package info.textgrid.services.aggregator;
import info.textgrid.middleware.tgsearch.client.SearchClient;
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 java.io.IOException;
import java.io.InputStream;
import java.net.URI;
......@@ -18,6 +9,15 @@
import com.google.common.io.InputSupplier;
import info.textgrid.middleware.tgsearch.client.SearchClient;
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;
public interface ITextGridRep {
public SearchClient getPublicSearchClient();
......
package info.textgrid.services.aggregator;
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.services.aggregator.epub.EPUBSerializer;
import info.textgrid.services.aggregator.html.HTMLWriter;
import info.textgrid.services.aggregator.pdf.PDF;
import info.textgrid.services.aggregator.teicorpus.TEICorpusExporter;
import info.textgrid.services.aggregator.util.StylesheetManager;
import info.textgrid.services.aggregator.zip.ZipResult;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
......@@ -33,8 +21,6 @@
import javax.ws.rs.core.StreamingOutput;
import javax.ws.rs.core.UriInfo;
import net.sf.saxon.s9api.SaxonApiException;
import org.apache.cxf.jaxrs.model.wadl.Description;
import org.apache.cxf.jaxrs.model.wadl.Descriptions;
import org.apache.cxf.jaxrs.model.wadl.DocTarget;
......@@ -42,6 +28,19 @@
import com.google.common.base.Optional;
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.services.aggregator.epub.EPUBSerializer;
import info.textgrid.services.aggregator.html.HTMLWriter;
import info.textgrid.services.aggregator.pdf.PDF;
import info.textgrid.services.aggregator.teicorpus.TEICorpusExporter;
import info.textgrid.services.aggregator.util.StylesheetManager;
import info.textgrid.services.aggregator.zip.ZipResult;
import net.sf.saxon.s9api.SaxonApiException;
@Description(title = "TextGrid Aggregator Service",
value = "The Aggregator is a service to export and convert TextGrid documents. It is able to recursively process collections, editions, and other TextGrid aggregations.")
@CrossOriginResourceSharing(allowAllOrigins=true)
......@@ -76,6 +75,7 @@ public Response getCorpus(
@Description("If true, no intermediate TEI corpus documents will be generated for intermediate aggregations, hierarchical structure will be lost") @QueryParam("flat") @DefaultValue("false") final boolean flat,
@Description("Title for the container if multiple root objects are given") @QueryParam("title") final String titleArgument,
@Description("Session id for accessing restricted resources") @QueryParam("sid") final String sid,
@Description("Also access sandboxed data") @QueryParam("sandbox") final boolean sandbox,
@Context final Request request) throws URISyntaxException,
ObjectNotFoundFault, MetadataParseFault, IoFault, AuthFault,
ProtocolNotImplementedFault, IOException, SaxonApiException {
......@@ -85,6 +85,7 @@ public Response getCorpus(
exporter.setFlat(flat);
exporter.setTitle(titleArgument);
exporter.sid(sid);
exporter.sandbox(sandbox);
return exporter.createResponse().build();
}
......@@ -98,6 +99,7 @@ public Response getEPUB(
@Description("URL of an alternative stylesheet to use. Must be compatible.") @QueryParam("stylesheet") final URI xsluri,
@Description("Title if multiple root objects given") @QueryParam("title") final String titleParam,
@Description("Session ID for accessing protected objects") @QueryParam("sid") final String sid,
@Description("Also access sandboxed data") @QueryParam("sandbox") final boolean sandbox,
@Context final Request request) throws ObjectNotFoundFault,
MetadataParseFault, IoFault, AuthFault,
ProtocolNotImplementedFault, IOException, SaxonApiException {
......@@ -107,6 +109,7 @@ public Response getEPUB(
request);
serializer.setStylesheet(xsluri);
serializer.setTitle(titleParam);
serializer.sandbox(sandbox);
return serializer.createResponse().build();
}
......@@ -121,7 +124,7 @@ public Response getEPUB(
public Response getHTML(
@Description("The TextGrid URIs of the TEI document(s) or aggregation(s) to transform, separated by commas") @PathParam("object") final String uriList,
@Description("If given, an alternative XSLT stylesheet to use. Must be a textgrid URI.") @QueryParam("stylesheet") final URI xsluri,
@Description("If true, check for an <?xsl-stylesheet?> processing instruction in the document to render. Only textgrid: URIs will be resolved.") @QueryParam("pi") final boolean pi,
@Description("If true, check for an <?xsl-stylesheet?> processing instruction in the document to render. Only textgrid: URIs will be resolved.") @QueryParam("pi") @DefaultValue("true") final boolean pi,
@Description("If true and a stylesheet has been given, force reloading the stylesheet, do not cache") @QueryParam("refreshStylesheet") final boolean refreshStylesheet,
@Description("Session ID to access protected resources") @QueryParam("sid") final String sid,
@Description("If true, an HTML fragment consisting of a <div class='body'> element containing the contents of the HTML <body> will be returned, ready to be embedded in an existing HTML page") @QueryParam("embedded") final boolean embedded,
......@@ -131,6 +134,7 @@ public Response getHTML(
@Description("An XML ID. If given, only this element will be transformed.") @QueryParam("id") final String id,
@Description("If true, a full webpage that looks similar to textgridrep.de's browse view will be returned") @QueryParam("simulate") @DefaultValue("false") final boolean simulate,
@Description("If given, generate a table of contents instead of a full HTML document") @QueryParam("toc") final String toc,
@Description("Also access sandboxed data") @QueryParam("sandbox") final boolean sandbox,
@Context final Request request) throws ObjectNotFoundFault,
MetadataParseFault, IoFault, AuthFault,
ProtocolNotImplementedFault, WebApplicationException, IOException,
......@@ -139,6 +143,7 @@ public Response getHTML(
final HTMLWriter writer = new HTMLWriter(repository,
getStylesheetManager(), uriList, xsluri, refreshStylesheet, pi,
embedded, css, sid, mediaType, id, request);
writer.sandbox(sandbox);
writer.simulate(simulate);
writer.linkUrlPattern(linkURLPattern);
writer.toc(toc);
......@@ -180,7 +185,8 @@ public Response getZIP(
@QueryParam("target") @Description("if query is used, the query target (metadata, fulltext or both)") @DefaultValue("both") final String target,
@QueryParam("start") @Description("for query: start at result no.") @DefaultValue("0") int start,
@QueryParam("stop") @Description("for query: max. number of results") @DefaultValue("65535") int stop,
@QueryParam("stream") @Description("if true, favor fast results over ideal rewriting") @DefaultValue("false") boolean stream,
@QueryParam("stream") @Description("if true, favor fast results over ideal rewriting") @DefaultValue("true") boolean stream,
@Description("Also access sandboxed data") @QueryParam("sandbox") final boolean sandbox,
@Context final Request request) throws MetadataParseFault,
ObjectNotFoundFault, IoFault, AuthFault,
ProtocolNotImplementedFault, IOException, SaxonApiException {
......@@ -188,14 +194,14 @@ public Response getZIP(
final ZipResult zipResult = new ZipResult(repository,
getStylesheetManager(), request, uriList, filenames, metanames,
dirnames, only, meta, transform);
zipResult.sandbox(sandbox);
if (title != null)
zipResult.setTitle(title);
if (sid != null)
zipResult.sid(sid);
if (query != null)
zipResult.initFromSearch(query, target, start, stop, filter);
if (stream)
zipResult.streaming(stream);
zipResult.streaming(stream);
return zipResult.createResponse().build();
}
......
......@@ -12,6 +12,7 @@
import info.textgrid.namespaces.middleware.tgsearch.Response;
import info.textgrid.namespaces.middleware.tgsearch.ResultType;
import com.google.common.base.Joiner;
import com.google.common.collect.ForwardingCollection;
import com.google.common.collect.Lists;
import com.google.common.collect.UnmodifiableIterator;
......@@ -58,16 +59,18 @@ public boolean hasNext() {
private int hits = -1; // # of hits, -1 if we don't know yet
private int nextStart = 0; //
private int stop = Integer.MAX_VALUE;
private SearchClient searchClient;
private final SearchClient searchClient;
protected SearchResultList(final SearchClient client, final String query, final String target, List<String> filter) {
protected SearchResultList(final SearchClient client, final String query, final String target, List<String> filter, boolean sandbox) {
this.searchClient = client;
this.query = query;
this.query = query == null || "".equals(query)? "*" : query;
this.filter = filter;
client.setTarget(target);
client.setSandbox(sandbox);
}
public static SearchResultList create(final SearchClient client, final String query, final String target, List<String> filter) {
return new SearchResultList(client, query, target, filter);
public static SearchResultList create(final SearchClient client, final String query, final String target, List<String> filter, boolean sandbox) {
return new SearchResultList(client, query, target, filter, sandbox);
}
private void ensureNotStarted() {
......@@ -102,9 +105,9 @@ public int size() {
private Logger logger = Logger.getLogger(getClass().getCanonicalName());
private String query;
private final String query;
private List<String> filter;
private final List<String> filter;
@Override
......@@ -138,10 +141,13 @@ protected Collection<ObjectType> delegate() {
protected void fetchNextChunk() {
if (finished)
return;
Response response = searchClient.query(query, null, "", nextStart,
Math.min(stop - nextStart, chunkSize), filter);
hits = Integer.parseInt(response.getHits());
logger.info(MessageFormat.format("Next query for {0}, filters {3}, sandbox {1}, {2} hits", query, searchClient.getSandbox(), hits,
filter == null? "null" : Joiner.on("; ").join(filter)));
if (!started) {
availableResults = Lists.newArrayListWithExpectedSize(hits);
started = true;
......
package info.textgrid.services.aggregator.util;
import info.textgrid.middleware.confclient.ConfservClient;
import info.textgrid.middleware.confclient.ConfservClientConstants;
import info.textgrid.middleware.tgsearch.client.SearchClient;
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.ProtocolNotImplementedFault;
import info.textgrid.namespaces.middleware.tgcrud.services.tgcrudservice.TGCrudService;
import info.textgrid.namespaces.middleware.tgcrud.services.tgcrudservice.tgcrudclient.TGCrudClientUtilities;
import info.textgrid.services.aggregator.ITextGridRep;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
......@@ -38,6 +24,20 @@
import com.google.common.base.Joiner;
import com.google.common.collect.Maps;
import info.textgrid.middleware.confclient.ConfservClient;
import info.textgrid.middleware.confclient.ConfservClientConstants;
import info.textgrid.middleware.tgsearch.client.SearchClient;
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.ProtocolNotImplementedFault;
import info.textgrid.namespaces.middleware.tgcrud.services.tgcrudservice.TGCrudService;
import info.textgrid.namespaces.middleware.tgcrud.services.tgcrudservice.tgcrudclient.TGCrudClientUtilities;
import info.textgrid.services.aggregator.ITextGridRep;
public class TextGridRepProvider implements ITextGridRep {
private HashMap<String, String> config;
......
......@@ -116,7 +116,7 @@ protected void walkAggregation(ObjectType aggregation, boolean again) {
private boolean includeMeta;
private StylesheetManager stylesheetManager;
private Optional<Transformation> transformation = Optional.absent();
private boolean streamingMode = false;
private boolean streamingMode = true;
public ZipResult streaming(final boolean streamingMode) {
this.streamingMode = streamingMode;
......@@ -206,7 +206,7 @@ public void write(final OutputStream output) throws IOException,
try {
final Iterable<ObjectType> rootObjects = getRootObjects();
logger.log(Level.INFO, MessageFormat.format(
"Starting ZIP export after {0}", stopwatch));
"Starting {1} ZIP export after {0}", stopwatch, streamingMode? "streaming" : "fully link rewriting"));
zip.setComment("# Exported from TextGrid -- www.textgrid.de");
mapping = new ImportMapping();
......
This diff is collapsed.
This diff is collapsed.
......@@ -15,7 +15,7 @@ public class SearchResultListTest {
@Test
public void test() {
SearchResultList results = SearchResultList
.create(repository.getPublicSearchClient(), "genre:\"verse\" AND edition.agent.value:\"anakreon\"", "both", null)
.create(repository.getPublicSearchClient(), "genre:\"verse\" AND edition.agent.value:\"anakreon\"", "both", null, false)
.chunkSize(10);
int i = 0;
for (ObjectType object : results) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment