org.mapfish.print.map.style.json.MapfishStyleParserPlugin Maven / Gradle / Ivy
Show all versions of print-lib Show documentation
package org.mapfish.print.map.style.json;
import org.geotools.styling.Style;
import org.geotools.styling.StyleBuilder;
import org.json.JSONObject;
import org.mapfish.print.Constants;
import org.mapfish.print.ExceptionUtils;
import org.mapfish.print.config.Configuration;
import org.mapfish.print.map.style.ParserPluginUtils;
import org.mapfish.print.map.style.SLDParserPlugin;
import org.mapfish.print.map.style.StyleParserPlugin;
import org.mapfish.print.wrapper.json.PJsonObject;
import org.springframework.http.client.ClientHttpRequestFactory;
import java.util.Optional;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import static org.mapfish.print.map.style.json.MapfishJsonStyleVersion1.DEFAULT_GEOM_ATT_NAME;
/**
* Supports all style format.
*
* This style parser support two versions of JSON and SLD formatting. Both versions use the same parameter
* names for configuring the values of the various properties of the style but the layout differs between the
* two and version 2 is more flexible and powerful than version 1.
*
* Mapfish JSON Style Version 1 ¶
*
* Version 1 is compatible with mapfish print <= v2 and is based on the OpenLayers v2 styling. The layout
* is as follows:
*
*
* {
* "version" : "1",
* "styleProperty":"_gx_style",
* "1": {
* "fillColor":"#FF0000",
* "fillOpacity":0,
* "rotation" : "30",
*
* "externalGraphic" : "mark.png"
* "graphicName": "circle",
* "graphicOpacity": 0.4,
* "pointRadius": 5,
*
* "strokeColor":"#FFA829",
* "strokeOpacity":1,
* "strokeWidth":5,
* "strokeLinecap":"round",
* "strokeDashstyle":"dot",
*
* "fontColor":"#000000",
* "fontFamily": "sans-serif",
* "fontSize": "12px",
* "fontStyle": "normal",
* "fontWeight": "bold",
* "haloColor": "#123456",
* "haloOpacity": "0.7",
* "haloRadius": "3.0",
* "label": "${name}",
* "labelAlign": "cm",
* "labelRotation": "45",
* "labelXOffset": "-25.0",
* "labelYOffset": "-35.0"
* }
* }
*
*
* Mapfish JSON Style Version 2 ¶
*
* Version 2 uses the same property names as version 1 but has a different structure. The layout is as
* follows:
*
*
* {
* "version" : "2",
* // shared values can be declared here (at top level)
* // and used in form ${constName} later in json
* "val1" : "#FFA829",
* // default values for properties can be defined here
* " strokeDashstyle" : "dot"
* "[population > 300]" : {
* // default values for current rule can be defined here
* // they will override default values defined at
* // higher level
* "rotation" : "30",
*
* //min and max scale denominator are optional
* "maxScale" : 1000000,
* "minScale" : 100000,
* "symbolizers" : [{
* // values defined in symbolizer will override defaults
* "type" : "point",
* "fillColor":"#FF0000",
* "fillOpacity":0,
* "rotation" : "30",
* "externalGraphic" : "mark.png",
*
* "graphicName": "circle",
* "graphicOpacity": 0.4,
* "pointRadius": 5,
*
* "strokeColor":"${val1}",
* "strokeOpacity":1,
* "strokeWidth":5,
* "strokeLinecap":"round",
* "strokeDashstyle":"dot"
* }, {
* "type" : "line",
* "strokeColor":"${val1}",
* "strokeOpacity":1,
* "strokeWidth":5,
* "strokeLinecap":"round",
* "strokeDashstyle":"dot"
* }, {
* "type" : "polygon",
* "fillColor":"#FF0000",
* "fillOpacity":0,
*
* "strokeColor":"${val1}",
* "strokeOpacity":1,
* "strokeWidth":5,
* "strokeLinecap":"round",
* "strokeDashstyle":"dot"
* }, {
* "type" : "text",
* "fontColor":"#000000",
* "fontFamily": "sans-serif",
* "fontSize": "12px",
* "fontStyle": "normal",
* "fontWeight": "bold",
* "haloColor": "#123456",
* "haloOpacity": "0.7",
* "haloRadius": "3.0",
* "label": "[name]",
* "fillColor":"#FF0000",
* "fillOpacity":0,
* "labelAlign": "cm",
* "labelRotation": "45",
* "labelXOffset": "-25.0",
* "labelYOffset": "-35.0"
* }
* ]}
* }
*
*
* As illustrated above the style consists of:
*
*
* - The version number (2) (required)
* -
* Common values which can be referenced in symbolizer property values.(optional)
*
Values can be referenced in the value of a property with the pattern: ${valName}
* Value names can only contain numbers, characters, _ or -
*
* Values do not have to be the full property they will be interpolated. For example:
* The value is ${val}
*
*
* -
* Defaults property definitions(optional):
*
* In order to reduce duplication and keep the style definitions small, default values can be specified. The
* default values in the root (style level) will be used in all symbolizers if the value is not defined. The
* style level default will apply to all symbolizers defined in the system.
*
*
* The only difference between a value and a default is that the default has a well known name, therefore
* defaults can also be used as values.
*
*
* -
* All the styling rules (At least one is required)
*
* A styling rule has a key which is the filter which selects the features that the rule will be used to draw
* and the rule definition object.
*
* The filter is either *
or an
*
* ECQL Expression) surrounded by square brackets. For example: [att < 23].
*
*
* WARNING: At the moment DWITHIN and BEYOND spatial functions take a unit parameter.
* However it is ignored by geotools and the distance is always in the crs of the geometry projection.
*
* The rule definition is as follows:
*
* -
* Default property values (optional):
*
* Each rule can also have defaults. If the style and the rule have a default for the same property the rule
* will override the style default. All defaults can be (of course) overridden by a value in a symbolizer.
*
*
* -
* minScale (optional)
*
* The minimum scale that the rule should evaluate to true
*
*
* -
* maxScale (optional)
*
* The maximum scale that the rule should evaluate to true
*
*
* -
* An array of symbolizers. (at least one required).
*
* A symbolizer must have a type property (point, line, polygon, text) which indicates the type of symbolizer
* and it has the attributes for that type of symbolizer. All values have defaults so it is possible to
* define a symbolizer as with only the type property. The only exception is that the "text" symbolizer needs
* a label property.
*
*
*
*
*
*
* Configuration Elements ¶
* The items in the list below are the properties that can be set on the different symbolizers. In brackets
* list the symbolizers the values can apply to.
*
* Most properties can be static values or ECQL expressions. If the property has [ ]
around the
* property value then it will be interpreted as an ECQL expression. Otherwise it is assumed to be static
* text. If you need static text that start and ends with [ ]
then you will have to enter:
* ['propertyValue']
(where propertyValue start and ends with [ ]
.
*
*
* The items below with (ECQL) can have ECQL expressions.
*
*
* - fillColor(ECQL) - (polygon, point, text) The color used to fill the point
* graphic, polygon or text.
* - fillOpacity(ECQL) - (polygon, point, text) The opacity used when fill the
* point graphic, polygon or text.
* - rotation(ECQL) - (point) The rotation of the point graphic
* -
* externalGraphic - (point) one of the two options for declaring the point
* graphic to use. This can be a URL to the icon to use or, if just a string it will be assumed to refer to a
* file in the configuration directory (or subdirectory). Only files in the configuration directory (or
* subdirectory) will be allowed.
*
* -
* graphicName(ECQL) - (point) one of the two options for declaring the point
* graphic to use. This is the default and will be a square if not specified. The option are any of the
* Geotools Marks.
*
Geotools has by default 3 types of marks:
*
* - WellKnownMarks: cross, star, triangle, arrow, X, hatch, square
* - ShapeMarks: shape://vertline, shape://horline, shape://slash, shape://backslash,
* shape://dot, shape://plus, shape://times, shape://oarrow, shape://carrow, shape://coarrow,
* shape://ccarrow
* - TTFMarkFactory: ttf://fontName#code (where fontName is a TrueType font and the code is
* the code number of thecharacter to render for the point.
*
*
* - graphicOpacity(ECQL) - (point) the opacity to use when drawing the point
* graphic
* - pointRadius(ECQL) - (point) the size at which to draw the point graphic
* -
* strokeColor(ECQL) - (line, point, polygon) the color to use when drawing a line
* or the outline of a polygon or point graphic
*
* - strokeOpacity(ECQL) - (line, point, polygon) the opacity to use when drawing
* the line/stroke
* - strokeWidth(ECQL) - (line, point, polygon) the widh of the line/stroke
* -
* strokeLinecap(ECQL) - (line, point, polygon) the style used when drawing the
* end of a line.
*
* Options: butt (sharp square edge), round (rounded edge), and square (slightly elongated square edge).
* Default is butt
*
*
* -
* strokeDashstyle - (line, point, polygon) A string describing how to draw the
* line or an array of floats describing the line lengths and space lengths:
*
* - dot - translates to dash array: [0.1, 2 * strokeWidth]
* - dash - translates to dash array: [2 * strokeWidth, 2 * strokeWidth]
* - dashdot - translates to dash array: [3 * strokeWidth, 2 * strokeWidth, 0.1, 2 *
* strokeWidth]
* - longdash - translates to dash array: [4 * strokeWidth, 2 * strokeWidth]
* - longdashdot - translates to dash array: [5 * strokeWidth, 2 * strokeWidth, 0.1, 2 *
* strokeWidth]
* - {string containing spaces to delimit array elements} - Example: [1 2 3 1 2]
*
*
* - fontColor(ECQL) - (text) the color of the text drawn
* - fontFamily(ECQL) - (text) the font of the text drawn
* - fontSize(ECQL) - (text) the font size of the text drawn
* - fontStyle(ECQL) - (text) the font style of the text drawn
* - fontWeight(ECQL) - (text) the font weight of the text drawn
* - haloColor(ECQL) - (text) the color of the halo around the text
* - haloOpacity(ECQL) - (text) the opacity of the halo around the text
* - haloRadius(ECQL) - (text) the radius of the halo around the text
* -
* label(ECQL) - (text) the expression used to create the label e. See the
* section on labelling for more details
*
* -
* labelAlign - (Point Placement) the indicator of how to align the text with
* respect to the geometry. This property must have 2 characters, the x-align and the y-align.
*
* X-Align options:
*
*
* - l - align to the left of the geometric center
* - c - align on the center of the geometric center
* - r - align to the right of the geometric center
*
*
* Y-Align options:
*
*
* - b - align to the bottom of the geometric center
* - m - align on the middle of the geometric center
* - t - align to the top of the geometric center
*
*
*
* - labelRotation(ECQL) - (Point Placement) the rotation of the label
* - labelXOffset(ECQL) - (Point Placement) the amount to offset the label along the
* x axis. negative number offset to the left
* - labelYOffset(ECQL) - (Point Placement) the amount to offset the label along the
* y axis. negative number offset to the top of the printing
* - labelAnchorPointX(ECQL) - (Point Placement) The point along the x axis that the
* label is started at anchored). Offset and rotation is relative to this point. Only one of
* labelAnchorPointX/Y or labelAlign will be respected, since they are both ways of defining the anchor
* Point
* - labelAnchorPointY(ECQL) - (Point Placement) The point along the y axis that the
* label is started at (anchored). Offset and rotation is relative to this point. Only one of
* labelAnchorPointX/Y or labelAlign will be respected, since they are both ways of defining the anchor
* Point
* - labelPerpendicularOffset(ECQL) - (Line Placement) If this property is defined
* it will be assumed that the geometry is a line and this property defines how far from the center of the
* line the label should be drawn.
*
*
* Labelling: ¶
*
* Labelling in this style format is done by defining a text symbolizer ("type":"text"). All text symbolizers
* consist of:
*
*
* - Label Property
* - Halo Properties
* - Font/weight/style/color/opacity
* - Placement Properties
* - Vendor Options
*
*
* Label Property ¶
*
* The label property defines what label will be drawn for a given feature. The value is either a string
* which will be the static label for all features that the symbolizer will be drawn on or a string surrounded
* by [] which indicates that it is an ECQL Expression. Examples:
*
*
* - Static label
* - [attributeName]
* - ['Static Label Again']
* - [5]
* - 5
* - env('java.home')
* - centroid(geomAtt)
*
*
* Halo Properties ¶
*
* A halo is a space around the drawn label text that is color (using the halo properties). A label with a
* halo is like the drawn label text with a buffer around the label text drawn using the halo properties. This
* allows the label to be clearly visible regardless of the background. For example if the text is black and
* the halo is with, then the text will always be readable thanks to the white buffer around the label text.
*
*
* Font/weight/style/color/opacity
* ¶
*
* The Font/weight/style/color/opacity properties define how the label text is drawn. They are for the most
* part equivalent to the similarly named css and SLD properties.
*
*
* Placement Properties
* ¶
*
* An important part of defining a text symbolizer is defining where the text/label will be drawn. The
* placement properties are used for this purpose. There are two types of placements, Point and Line
* placement and only one type of placement can be used. The type of placement is determined by
* inspecting the properties in the text symbolizer and if the labelPerpendicularOffset property is
* defined then a line placement will be created for the text symbolizer.
*
*
* It is important to realize that since only one type of placement can be used, an error will be reported if
* labelPerpendicularOffset is defined in the text symbolizer along with
* any of the point placement properties.
*
* Point Placement
*
* Point placement defines an anchor point which is the point to draw the text relative to. For
* example an anchor point of 0.5, 0.5 ("labelAnchorPointX" : "0.5", "labelAnchorPointY" : "0.5") would
* position the start of the label at the center of the geometry.
*
*
* After anchor point, comes displacement displacement defines the distance from the anchor
* point to start the label. The combination of the two values determines the final location of the label.
*
* Lastly, there is a label rotation which defines the orientation of the label.
*
* There are two ways to define the anchor point, either the labelAnchorPointX/Y properties are set
* or the labelAlign property is set. If both are defined then the
* labelAlign will be ignored.
*
*
* Vendor Options ¶
* For text symbolizers the following vendor options are available:
*
* - allowOverruns (false): When false does not allow labels on lines to get beyond the
* beginning/end of the line. By default a partial overrun is tolerated, set to false to disallow it.
*
* - autoWrap (400): Number of pixels are which a long label should be split into
* multiple lines. Works on all geometries, on lines it is mutually exclusive with the followLine option.
*
* - conflictResolution (true): Enables conflict resolution (default, true) meaning no
* two labels will be allowed to overlap. Symbolizers with conflict resolution off are considered outside of
* the conflict resolution game, they don’t reserve area and can overlap with other labels.
*
* - followLine (true): When true activates curved labels on linear geometries. The
* label will follow the shape of the current line, as opposed to being drawn a tangent straight line
*
* - goodnessOfFit (90): Sets the percentage of the label that must sit inside the
* geometry to allow drawing the label. Works only on polygons.
*
* - group (false): If true, geometries with the same labels are grouped and considered
* a single entity to be labelled. This allows to avoid or control repeated labels.
*
* - maxDisplacement (400): The distance, in pixel, a label can be displaced from its
* natural position in an attempt to find a position that does not conflict with already drawn labels.
*
* - spaceAround (50): The minimum distance between two labels, in pixels.
*
* Example
*
* {
* "version" : "2",
* "*" : {
* "symbolizers" : [{
* "type" : "text",
* "fontColor":"#000000",
* "label": "[name]",
* "goodnessOfFit": 0.1,
* "spaceAround": 10
* }
* ]}
* }
*
* For more information, please refer to the
* GeoTools
* documentation.
*
*
* ECQL references:
*
* -
* http://docs.geoserver.org/stable/en/user/filter/ecql_reference.html#ecql-expr
* -
* http://udig.refractions.net/files/docs/latest/user/Constraint%20Query%20Language.html
* -
* http://docs.geoserver.org/stable/en/user/filter/function_reference.html#filter-function-reference
* -
* http://docs.geotools.org/stable/userguide/library/cql/ecql.html
* -
* http://docs.geoserver.org/latest/en/user/tutorials/cql/cql_tutorial.html
*
*/
public final class MapfishStyleParserPlugin implements StyleParserPlugin {
static final String JSON_VERSION = "version";
private StyleBuilder sldStyleBuilder = new StyleBuilder();
@Override
public Optional