Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions doc/en/user/source/extensions/mapml/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,14 @@ For example, the UTM14WGS84Quad specified in the above selector has the followin

.. figure:: images/mapml_utm_gridset.png

Global Settings
---------------

.. figure:: images/mapml_global_menu.png

The Global settings menu (above) contains a Service Response Settings section (below) which contains the Verbose XML output (pretty print) checkbox. The MapML extension respects or uses this setting when serializing text/mapml (media type) responses. Be aware that caching on both the client and server may prevent this setting from becoming immediately obvious in devtools responses. Refreshing the browser cache can request a new version of the response, but if the response is cached on the server, for example as a vector tile, it may not be possible to obtain a pretty printed version of the data, short of deleting the tile cache, which may be undesirable.

.. figure:: images/mapml_global_verbose_output.png

Styles
------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,23 @@ private Marshaller createMarshaller() throws JAXBException {
* @param output OutputStream
*/
public void encode(Mapml mapml, OutputStream output) {
encode(mapml, output, false);
}

/**
* Use Marshaller to encode MapML object onto an output stream with optional pretty-printing
*
* @param mapml MapML object
* @param output OutputStream
* @param prettyPrint true to enable pretty-printing with 2-space indents, false for dense markup
*/
public void encode(Mapml mapml, OutputStream output, boolean prettyPrint) {
try {
XMLStreamWriter writer = new Wrapper(XMLOutputFactory.newInstance().createXMLStreamWriter(output));
createMarshaller().marshal(mapml, writer);
writer.flush();
XMLOutputFactory factory = XMLOutputFactory.newInstance();
Wrapper wrapper = new Wrapper(factory.createXMLStreamWriter(output));
wrapper.setIndenting(prettyPrint);
createMarshaller().marshal(mapml, wrapper);
wrapper.flush();
} catch (JAXBException | XMLStreamException e) {
throw new ServiceException(e);
}
Expand All @@ -81,6 +94,13 @@ static class Wrapper implements XMLStreamWriter {

private final XMLStreamWriter writer;
private static final String NS_PREFIX = "";
public static final String MAPML_INDENT_PROPERTY = "mapml.indent";
private static final String INDENT = " ";

private boolean indenting = false;
private int depth = 0;
private boolean needsIndent = false;
private boolean lastWasStartElement = false;

/**
* Constructor
Expand All @@ -91,39 +111,90 @@ static class Wrapper implements XMLStreamWriter {
this.writer = writer;
}

/** Writes indentation if pretty-printing is enabled */
private void writeIndent() throws XMLStreamException {
if (indenting && needsIndent) {
writer.writeCharacters("\n");
for (int i = 0; i < depth; i++) {
writer.writeCharacters(INDENT);
}
needsIndent = false;
}
}

@Override
public void writeStartElement(String localName) throws XMLStreamException {
writeIndent();
writer.writeStartElement(localName);
depth++;
needsIndent = true;
lastWasStartElement = true;
}

@Override
public void writeStartElement(String namespaceURI, String localName) throws XMLStreamException {
writeIndent();
writer.writeStartElement(namespaceURI, localName);
depth++;
needsIndent = true;
lastWasStartElement = true;
}

@Override
public void writeStartElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
writeIndent();
writer.writeStartElement(NS_PREFIX, localName, namespaceURI);
depth++;
needsIndent = true;
lastWasStartElement = true;
}

@Override
public void writeEmptyElement(String namespaceURI, String localName) throws XMLStreamException {
writer.writeEmptyElement(namespaceURI, localName);
// Force HTML-compatible empty elements with explicit end tags
writeIndent();
writer.writeStartElement(namespaceURI, localName);
writer.writeEndElement();
needsIndent = true;
}

@Override
public void writeEmptyElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
writer.writeEmptyElement(prefix, localName, namespaceURI);
// Force HTML-compatible empty elements with explicit end tags
writeIndent();
writer.writeStartElement(NS_PREFIX, localName, namespaceURI);
writer.writeEndElement();
needsIndent = true;
}

@Override
public void writeEmptyElement(String localName) throws XMLStreamException {
writer.writeEmptyElement(localName);
// Force HTML-compatible empty elements with explicit end tags
writeIndent();
writer.writeStartElement(localName);
writer.writeEndElement();
needsIndent = true;
}

@Override
public void writeEndElement() throws XMLStreamException {
depth--;
// For empty elements (start immediately followed by end), keep on same line
if (needsIndent && !lastWasStartElement) {
writeIndent();
} else if (lastWasStartElement) {
// Note: empty string typically doesn't add content but signals "non-empty" to writer
writer.writeCharacters("");
}
writer.writeEndElement();

// Add two newlines after the root closing tag
if (depth == 0 && indenting) {
writer.writeCharacters("\n\n");
}

needsIndent = true;
lastWasStartElement = false;
}

@Override
Expand Down Expand Up @@ -169,7 +240,9 @@ public void writeDefaultNamespace(String namespaceURI) throws XMLStreamException

@Override
public void writeComment(String data) throws XMLStreamException {
writeIndent();
writer.writeComment(data);
needsIndent = true;
}

@Override
Expand Down Expand Up @@ -214,11 +287,17 @@ public void writeStartDocument(String encoding, String version) throws XMLStream

@Override
public void writeCharacters(String text) throws XMLStreamException {
// Don't indent before text content as it would alter the actual content
needsIndent = false;
lastWasStartElement = false;
writer.writeCharacters(text);
}

@Override
public void writeCharacters(char[] text, int start, int len) throws XMLStreamException {
// Don't indent before text content as it would alter the actual content
needsIndent = false;
lastWasStartElement = false;
writer.writeCharacters(text, start, len);
}

Expand Down Expand Up @@ -249,7 +328,28 @@ public NamespaceContext getNamespaceContext() {

@Override
public Object getProperty(String name) throws IllegalArgumentException {
if (MAPML_INDENT_PROPERTY.equals(name)) {
return indenting;
}
return writer.getProperty(name);
}

/**
* Sets the indenting property for pretty-printing
*
* @param indent true to enable pretty-printing with 2-space indents, false for dense markup
*/
public void setIndenting(boolean indent) {
this.indenting = indent;
}

/**
* Gets the current indenting state
*
* @return true if pretty-printing is enabled
*/
public boolean isIndenting() {
return indenting;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
Expand All @@ -16,8 +15,6 @@
import java.util.function.Function;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.transform.Result;
import javax.xml.transform.stream.StreamResult;
import net.opengis.wfs.FeatureCollectionType;
import org.geoserver.catalog.Catalog;
import org.geoserver.catalog.FeatureTypeInfo;
Expand Down Expand Up @@ -47,7 +44,6 @@
import org.geotools.feature.FeatureCollection;
import org.geotools.util.logging.Logging;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;

/**
* @author Chris Hodgson
Expand All @@ -57,7 +53,7 @@ public class MapMLGetFeatureInfoOutputFormat extends GetFeatureInfoOutputFormat
private static final Logger LOGGER = Logging.getLogger("org.geoserver.mapml");

@Autowired
private Jaxb2Marshaller mapmlMarshaller;
private MapMLEncoder mapMLEncoder;

private WMS wms;

Expand Down Expand Up @@ -157,10 +153,9 @@ public void write(FeatureCollectionType results, GetFeatureInfoRequest request,
}
}

OutputStreamWriter osw = new OutputStreamWriter(out, wms.getCharSet());
Result result = new StreamResult(osw);
mapmlMarshaller.marshal(mapml, result);
osw.flush();
// write to output based on global verbose setting
boolean verbose = wms.getGeoServer().getGlobal().getSettings().isVerbose();
mapMLEncoder.encode(mapml, out, verbose);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,11 @@

import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import javax.xml.transform.Result;
import javax.xml.transform.stream.StreamResult;
import net.opengis.wfs.impl.GetFeatureTypeImpl;
import net.opengis.wfs.impl.QueryTypeImpl;
import org.geoserver.catalog.LayerInfo;
Expand All @@ -32,7 +29,6 @@
import org.geotools.referencing.CRS;
import org.geotools.util.logging.Logging;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;

/**
* @author Chris Hodgson
Expand All @@ -42,7 +38,7 @@ public class MapMLGetFeatureOutputFormat extends WFSGetFeatureOutputFormat {
private static final Logger LOGGER = Logging.getLogger(MapMLGetFeatureOutputFormat.class);

@Autowired
private Jaxb2Marshaller mapmlMarshaller;
private MapMLEncoder mapMLEncoder;

private String base;
private String path;
Expand Down Expand Up @@ -97,11 +93,9 @@ protected void write(FeatureCollectionResponse featureCollectionResponse, Output
null,
null);

// write to output
OutputStreamWriter osw = new OutputStreamWriter(out, gs.getSettings().getCharset());
Result result = new StreamResult(osw);
mapmlMarshaller.marshal(mapml, result);
osw.flush();
// write to output based on global verbose setting
boolean verbose = gs.getGlobal().getSettings().isVerbose();
mapMLEncoder.encode(mapml, out, verbose);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ public WebMap produceMap(WMSMapContent mapContent) throws ServiceException, IOEx
mapMLDocument = mapMLDocumentBuilder.getMapMLDocument();
}
ByteArrayOutputStream bos = new ByteArrayOutputStream();
encoder.encode(mapMLDocument, bos);
// write to output based on global verbose setting
boolean verbose = geoServer.getGlobal().getSettings().isVerbose();
encoder.encode(mapMLDocument, bos, verbose);
return new RawMap(mapContent, bos, MapMLConstants.MAPML_MIME_TYPE);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,12 @@
package org.geoserver.mapml;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import javax.xml.transform.Result;
import javax.xml.transform.stream.StreamResult;
import org.geoserver.rest.converters.BaseMessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.lang.Nullable;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;

/**
* @author Chris Hodgson
Expand All @@ -23,7 +19,7 @@
public class MapMLMessageConverter extends BaseMessageConverter<Object> {

@Autowired
private Jaxb2Marshaller mapmlMarshaller;
private MapMLEncoder mapMLEncoder;

/** */
public MapMLMessageConverter() {
Expand All @@ -47,7 +43,7 @@ public boolean canRead(Class<?> clazz, @Nullable MediaType mediaType) {
*/
@Override
public boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType) {
return canWrite(mediaType) && mapmlMarshaller.supports(clazz);
return canWrite(mediaType) && org.geoserver.mapml.xml.Mapml.class.isAssignableFrom(clazz);
}

/**
Expand All @@ -69,11 +65,12 @@ protected boolean supports(Class<?> clazz) {
@Override
protected void writeInternal(Object o, HttpOutputMessage outputMessage)
throws UnsupportedEncodingException, IOException {
try (OutputStreamWriter osw = new OutputStreamWriter(
outputMessage.getBody(), geoServer.getSettings().getCharset())) {
Result result = new StreamResult(osw);
mapmlMarshaller.marshal(o, result);
osw.flush();
if (o instanceof org.geoserver.mapml.xml.Mapml) {
// write to output based on global verbose setting
boolean verbose = geoServer.getGlobal().getSettings().isVerbose();
mapMLEncoder.encode((org.geoserver.mapml.xml.Mapml) o, outputMessage.getBody(), verbose);
} else {
throw new IllegalArgumentException("Can only write Mapml objects, got: " + o.getClass());
}
}
}
Loading
Loading