Skip to content

GSIP 81

Jody Garnett edited this page Jul 12, 2017 · 1 revision

GSIP 81 - GetLegendGraphic as text (JSON)

Overview

To compose the legend on the client side making it interactive localized and styled in the way the web-styler (or the map component) wants.

Proposed By

Carlo Cancellieri

Assigned to Release

master then backport to 2.2.3 or 2.2.4

State

Choose one of: Under Discussion, In Progress, Completed, Rejected, Deferred

Motivation

GeoServer should be able to create an interactive and configurable legend on the client side.

Some of the advantages which can be achieved are:

  • Get filters (intervals and comparators), colors or graphics on the client side as individual objects to apply css, layout and modify the shape of the legend accordingly with the site style and layout.
  • Get labels as texts (so they can be localized client side).
  • In combination with the json outputFormat getFeatureInfo (or imageMap ) can be used to highlight the element of the legend representing that value into the map and vice versa (see here for an example).

NOTE that most of the parts of this response handler encoder can be reused to serialize the styles in json format (which currently is still missing).

Proposal

{quote}{}NOTE The getLegendGraphic does not implements all the output format supported by the getMap as specified here:http://docs.geoserver.org/latest/en/user/services/wms/getlegendgraphic/legendgraphic.html#get-legend-graphic

{quote}Create a response handler to replay to getLegendGraphic requests in text json format.

My intension is to provide a textual representation of the rules for a target layer/style (in an OpenLayer like format) including:

  • names, title, …
  • filter (as structured object)
  • symbolizers (also with graphic objects)

External resources

Embedded URL

advantages:

  • Small and quick response body.
  • You can selectively download only really needed graphical resources.

disadvantages:

  • To show the graphic resources into the legend, multiple getLegendGraphic (filtered) requests to the GeoServer should be performed.

Embedded graphic resource

advantages:

  • Get all the legend resources in one shot.
  • No other request are needed.

disadvantages:

  • For some style you may have many external resources in some case this may result in a really big response.

So depending on the style you are using and the legend you want to generate, (sometime you only want to show the first (lower?) and the last (higher?) values), users may prefer the embedded url or the embedded graphic resource version.

The graphic object will be serialized in base64 so the client can use it directly as image. fe:

<img alt="Embedded Image" width="80" height="31"
  src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAAAfCAYAAABwH0oUAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAADfJJREFUeNrkWglwlOUZfvY+ks29QMhFwpEEAhFQjqIcHRBREbwHxasiVfHsiWKnHZWhY+uMFaxStVJvxasgFlRGARFBzgQhJoEkm4Tc2c1ujr237/vn/eNvJlA6TDNt/Wae2d3//87ne97j+xJdLBZLBJBOGEEYSogj+AU9BBvBStARfIRmQgchQnAQhhCSpd5ARe0rQLBIX9YB6rgJtYQGglf6U+eV2q9NjwYWmQu3qSE0yjyjGISiIwIL6PNCwgLCRIJTJuAVopjgBIKe0EKolEkGCWmE0YRMqTdQ8Wng0KB/HSbva8J+QpVsymTCTBlD26ZDg3jZgBOErYQvCdWyYYNC4CX0eQfhKvx3lCNCZIpsqu3faPsW4a+Er0QA//FiFLNl5eGhhx7qe7FmzZq+7+pz9dmqVauwevXq773nd/yp1+sRjUb7fnPhZ2r9/mMMUKdY0DcW96cdXx2v//hU8kSphkHbblLg3QQfIbZy5cqYWtTv2mcPP/zwgO8Gqns2/Z2uztm8P01/WwkL2K8TMBgwSnDQn05t2qIq4Uylf/uB+lNVxc9YeWrRfj9Tn1r1ap6xH/yC4Bos/6eacEwbsQYi7l8tUPtc2141SyZMW7Tmr92UgTaov/mfYX6bxPc1SIAbNAK7JDWJH6gCT1irGO2zAVTwvboqIUyAtt7ZqFRLqupbz0CeW6JvhUTm6GARqEbh2wnXaJ63EU5KepI+yFHYQzhMGEYoOMs27xBeJOwRAjGYCuSc6x+ya0xYE2EfoV6S2AslSidIfTaPdk0O5pBk9pximRB3TPxYreSYP5KIzEn0KcIhmZ+ZUCRz4nluk3X4BzvnMkpSvJtQJ4R0S8JslFwsjlTqPN7Rg88bumHV62yXZydkDLGZ4mSxZVK/5xxMJ6YZl08TnXIiKpU0yyAEn5J3ZnluFReknkBCA5rZ2r2nH/jeqedMoE92rkF+mwhJhEmEeYQZG8vr4epyozhFDw7cJU1dGJeWnpQeb1ogE2fnfVyS18hAaxASdIKY1NMSHhF1++W7XjbVLG1CmndGibb8GRby/YPp+7QERiXs8+TtYjrTCNcRLt1cWY41pSHELBY0k0NfnhfGIXcAT5fW4I6xWYa8RMsyUV+bmJdHQ6JeThIpckRMkmc+UVubKCh8mvkF+m2CWcw2Tc7HdqnTLmN7BzOFUYOIOjmeTK6cPW9k/7OlshTeQAPyEnW4+UAu4mn6o+JjSDDr8JPMKPa2GTAtPR3TnNwU6wjvEo5KVNTJ+ZhPB+eJH82RTauTQHFAzrBe2UhVmbF+qo2Jnx0ivo/7Gysb0y6mzu6kXH5HNf2pG6mqH5rULdbvmU5TN6pRtK6f9fT1b5QK7EuyCHMJy6jGuE3l++EL1iIrLoaXqrP4yILOkA6+UJRIJKYTekXT2d2E+s4MZMSb75HOY2LOkCh6GeH6SCyWU+b2ozMYwegkK1KsRpecXfcI4Woy7BEV2eRCwSy/zdLfFXxG/pb68gTCyHKYQf54kVGv2yCpTK3UV5VtFX9q1hzx1JumoBAW07gNu7ixiPSjl7ZmedYpaR9vVLdROmVzuIBwE5P3XtluePzVyIyPIM6oo1ws3EfN8hHtmJTM+ZmFSKTQR9opa6NAGCMSHeYVMimTTJRTpHs/qvaYH/mqDuWeHuh1OlgNetxfPDR71QUZN9D7fGljFiW6xMSZvGwJbD7pb3xHMFJ0/85qvH/CjXA0hiSLEZ9fVWihTblZbm8apZ9mISpZ3EeCzEuN+K1ST80gokJWihAeknFNQqp6zcc3PXvl1shllA44XZlHKpn06je70BUow/C4EOxEXoiIWppdjWM+B1pCFmRZvajpsqDEZ8Xi9G6McNhQTcMcbyOr1GXqSYk3a46GS/9+0m2+cks5Zgx3YNuiAqTQgt+qaEN6HPOFDEZzTwgVHj9yHBbaNHOff2GVNXWHMCHNTkT1iufxr+vxt+OteGP+KBSl2nGiw49sh9LG1h2Onl/S2q3ULUjuvcRp84cRjLDbMeCb9m5l3J5wVBnHbtSjoSuk/CZfrtSv7QzC5QtgDFmJ02ai9cfQSHNIpPZuUrwnEEFxmv1NUWCzUXZ4FGHOM8da4Wqtwvlp7bDTfEMRi6LPx46fhxM+A6anEUnRZrzuysJzNXbMd9bCpA+Qmdtx0mfB4aZaJFtynXaT/mreaTIx5wO7apBLk9uyMF9ZBJffTc3sI+mVslb8htTJiyBx4u1LRuNCIvs+Utm7le3kNqIKQe9fNkZZFBPEZdKQOOV3UWovUV82+HD79irFrLuor8enZeK+4mG4fmsFOmjRZOJkLQEsGzcETx5swNZF+ZiVkYBH99Xhw2oPym8qxnNHm/HkoQYEIlHEmwz4ZHGBQtiCTWWYQ3W3ujowi+a2eWF+nvh3o16kOZyT6A3H2rG5biJerpqCZr8B1aS0U91RGKINuHhIGR7IKyVSe7Asy4VH812o7gyjinbwot3xSLX0YDstwuVj16KYXs7exi5U06QfoIWo5CnOpjdwYW9jJ2799AQenDiMCBqtqG1vUyfWlTTimZImvHLxSFJtPo619yi/uSwvGqJ8XvHhtzjY0qV8byEFX7e1EhMpmB1eMl6R/6YqtzJWfWcI+5u7MCPdoWziwhFJ8BNB37T39Ppw2iBW7Ec1HvycNnvdrBF4dnauMm8eN0h1W3vC2HnKh7UzR2DdbDZWxc2wGwjrNdEOwWhvYKjvSiT/EkBdVxjrK9JR7nWgyNFIcvZThwT6XOBswFGvDksPDYWrR4+VZXa8VR3D0fbvDgPH3T19alHLZ3VezHjnGLbRbm4khTGXPFlWzyRnHC6lBf6BFHLVyBTMzUrEZGrL5lPb2ZudXE3PX5qbp6hp7vtlONpGG1frJaKCsJEebvy4EiaDDisnDyfzDComvjgvGX+8MFvpK5vchIP78wWVcd8kd/Jrqruxop2yDAN2EVG/+MKF2aQ4Vt3Bll7FP3VRDm4pTGM3s4N+fihHXb9eHCPnZB42HV7R9LQSOnHUItd2EMtzP0WauQMVPjvcwahCYijSiycq0zHG3oWnCl3kN4NoDRrJP3xHlknfmyGwCamFfR0rzyQmRdFYCQS/nZKBPdeOo6ClRx2RMXVY790G+x8KHChM/u5i+tZCJz5ZVKiY6/qjTX1qcpDZXTsqFaU3TFDIZ3NnH3ZLobOvbYrVgDQas5KIvX9nDWbSmpeMSVVU6rQZlXdPz8rBp1cWKETvIatKo+cLczkWKacu9n+75FQUVJNazsV2/H5qBmy0mKYeC0XhVhq8W0EsFsHzVefhnsOziMSIosB9HismJrTjifzjGGtzY1FqC36Wn8wpSljOpmUzMxyKvFfvP4Uacsw+avt5vVchr1gCA5sQK2R+TiIepQBxlMjgKF1Gn7R2rD3SBN6HG/PT8DWdgFhtbIKsNjZRDgQSRDCNSL+pIE0JUh+cdKOU1Mm+b2yKTU3KT1qo7/EUfCgzwB7ayOfm5MJAzpdJ8odjSnvu51e7a5WAUtLWrdSPMylxcYf8uaFW0qSoUfIhJvDjJLNh/PZF+Xnz3mukoJBIfiuK11yLUdZJ+a8+hia/XRRoIBMPYqStAztabNBF9DAZR2HNDCU4vCiDjKSBV6ydNSLhl7tdKHy1BKm0u6fIrH6cmah8v7NoqOKrJr5RShM0KIu4fawTPyU/96cjjcoC2QzX0yKZhD+XNuFB8lMZFElZpWySKyYMI4evx7OlzViyrVLZFFbd5svzifBORdE8lpp2cMo2JtmayOM+RoGGc1Iuj1yQgWs/qsDIlw/DSIROJHfCG84u4s4i5e9ZXrnsaNGeudWTiBqJOUm9h0K/885PnqeAMoG2zcK3mgId3pm6gXyMFW83TMJr9WNhD5MpT06ihYzkfl4gbJSbEU5RFhJuo3QkeU+jj4IHyBStyCdzlEUpJv0FmQkraR6ZHZs0px1bSCGtfgpQZGKSksQo+OgOkKkdJr/E9S7OTuwLTuzot7k8tLF0lCLl5yZYsI8I5FxxytB4DylxvZyAptImLmU1X0KqJ0UeEnImH2ntjmdTZjNmi2BqdtPc8hKsnOa8QXU2SA7Y0Z9AvVxLjZGTw4p2fzht3OslaPRHNATqcU3mAeTFe/FM1Uz0BHR4YboNt40r0JJ3WCak9jddMFpOBc1CcL2cNnLkGi2q+ZuzQ5JfkySu6kVptvQ5XFxPtZCik5NUtgREr8Akn9/KUc8t482QYyFfoJTIZQTPb4rkxHox0ZDGxe2Wo2e99sZbJXAgEu92ByLOca8fQgOHGfId0PWq0GoIwRoLYMXYLDw+leeM5+VSk8lr163dG47dO9UoKdJQUWOqLKhTLhG8ci5OlkuGqExW/WN5gpDhllNDQHIvp8wzIP14hMBkgV768Mv3sJDfKG3iZU42mUurEJUkG5OkuciIyDuvXFa0Sd+xgQjUkjhaSLyLsu+hs9/7DJ1hLwoTq5FNAYMd+KiUJbiruJDb/EXIO6KS1+++zSjHNJMsNCyTCst4Js3fZkKaM6lJQ4D63CB9qbdIIYFOcxWnk7oRzSWBcnVGc4vSfAyaS4qo5vLCqJlLtN91W6xfnxiQQB05T/qtJXE+n4+7w6H8tYf2U05VSb4qDleMuogCgZMl/hLhAzEDN7UP4+mv8L9UzvVCtb8CtUqMF3/AI8yRz0yRPattO2Gn3Lx4znCn939dTkeg9jI0TRxvjviHoDjSk5JM+k5zC/2DJ1AtBnHqdvE/Mc1/RgW1DvWHWP4pwAAUiSGmZL9i4wAAAABJRU5ErkJggg%3D%3D" />

Will result in: image

A good alternative (for big images) is to use the RULE parameter of the getLegendGraphic (image output format) to renderize and return only one graphic object at time.

*RULE*  Optional    Rule of style to produce legend graphic for, if applicable. In the case that a style has multiple rules but no specific rule is selected, then the map server is obligated to produce a graphic that is representative of all of the rules of the style.
dynamic symbolizers

The rules of the dynamic symbolizers will be resolved for each feature and the list of obtained external graphic will be serialized as a list of rules with the name initialized to the value of the resolved attribute.

For example:

     <FeatureTypeStyle>
        <Rule>
          <Name>Flags</Name>
          <Title>USA state flags</Title>
          <PointSymbolizer>
            <Graphic>
              <ExternalGraphic>
                <OnlineResource xlink:type="simple"
                  xlink:href="http://www.usautoparts.net/bmw/images/states/tn_${strToLowerCase(STATE_ABBR)}.jpg" />
                <Format>image/gif</Format>
              </ExternalGraphic>
            </Graphic>
          </PointSymbolizer>
        </Rule>
      </FeatureTypeStyle>

Will be resolved as:

     <FeatureTypeStyle>
        <Rule>
          <Name>alaska</Name>
          <Title>USA state flags</Title>
          <PointSymbolizer>
            <Graphic>
              <ExternalGraphic>
                <OnlineResource xlink:type="simple"
                  xlink:href="http://www.usautoparts.net/bmw/images/states/tn_alaska.jpg" />
                <Format>image/gif</Format>
              </ExternalGraphic>
            </Graphic>
          </PointSymbolizer>
        </Rule>
        ...
        <Rule>
          <Name>wyoming</Name>
          <Title>USA state flags</Title>
          <PointSymbolizer>
            <Graphic>
              <ExternalGraphic>
                <OnlineResource xlink:type="simple"
                  xlink:href="http://www.usautoparts.net/bmw/images/states/tn_wyoming.jpg" />
                <Format>image/gif</Format>
              </ExternalGraphic>
            </Graphic>
          </PointSymbolizer>
        </Rule>
      </FeatureTypeStyle>

Then serialized as json.

If the OnlineResource is a relative path we have 2 ways to proceed:

  • generate a base64 encoded string to encode and send the image.

  • use getLegendGraphic with image output format to be able to serve images from the FileSystem (selecting them using the RULE parameter and probably the CQL_FIlter to select the feature by FeatureID f.e.). I think this (cql_filter) can be another good improvement if it is not supported.

SVG, or Mark objects, or graphic fills and graphic strokes

As said the graphical objects can be:

  • serialized as is (json style representation)

This will minimize the data transfer and the load on the target geoserver delegating render operation to the client library this make sense for standard Mark objects (ttf://, shape://, …) 

  • rendered all graphic objects as embedded images into the response encoded as base64 string (json with graphic embedded).

  • provide links to external graphic using geoserver url (s):

F.e.:[http://localhost:80///geoserver/wms?REQUEST=GetLegendGraphic&VERSION=....&FORMAT=image/png&LAYER=layerName&RULE=RuleName&LEGEND_OPTIONS=forceLabels:off]

NOTE: For  dynamic symbolizers we need the cql_filter improvement

Examples

{quote}{}Note: the below examples are used only to discuss the proposal, this is not the final representation of the getLegendGraphic as text. {quote}Using this call:

[http://localhost:8080/geoserver/sf/wms?service=WMS&version=1.1.0&request=GetLegendGraphic&layer=sf:sfdem&styles=&bbox=589980.0,4913700.0,609000.0,4928010.0&width=512&height=385&srs=EPSG:26713&format=application/json&outputFormat=application/json]

You will get something like:

Raster colormap

{
 getLegendGraphic:[
 {
 description:null,
 title:null,
 name:null,
 symbolyzers:[
 {
 name:null,
 description:null,
 title:null,
 type:“RasterSymbolizer”,
 colormap:{
 entries:[
 {
 label:“nodata”,
 opacity:“0.0”,
 quantity:“–500”,
 color:“\#000000”
 },
 {
 label:“values”,
 opacity:null,
 quantity:“0”,
 color:“\#AAFFAA”
 },
 {
 label:null,
 opacity:null,
 quantity:“1000”,
 color:“\#00FF00”
 },
 {
 label:“values”,
 opacity:null,
 quantity:“1200”,
 color:“\#FFFF00”
 },
 {
 label:“values”,
 opacity:null,
 quantity:“1400”,
 color:“\#FF7F00”
 },
 {
 label:“values”,
 opacity:null,
 quantity:“1600”,
 color:“\#BF7F3F”
 },
 {
 label:“values”,
 opacity:null,
 quantity:“2000”,
 color:“\#000000”
 }
 ]
 },
 geometry:“geom”,
 geometryPropertyName:“geom”
 }
 ]
 }
 ]
}

This is the matching style:

<?xml version="1.0" encoding="ISO-8859-1"?>
<StyledLayerDescriptor version="1.0.0" xmlns="http://www.opengis.net/sld" xmlns:ogc="http://www.opengis.net/ogc"
  xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd">
 <NamedLayer>
 <Name>gtopo</Name>
 <UserStyle>
 <Name>dem</Name>

<Title>
Simple DEM style

</Title>
<Abstract>Classic elevation color progression</Abstract>
 <FeatureTypeStyle>
 <Rule>
 <RasterSymbolizer>
 <Opacity>1.0</Opacity>
 <ColorMap>

<ColorMapEntry color="#000000" quantity="-500" label="nodata" opacity="0.0" />
 <ColorMapEntry color="#AAFFAA" quantity="0" label="values" />
 <ColorMapEntry color="#00FF00" quantity="1000"/>
 <ColorMapEntry color="#FFFF00" quantity="1200" label="values" />
 <ColorMapEntry color="#FF7F00" quantity="1400" label="values" />
 <ColorMapEntry color="#BF7F3F" quantity="1600" label="values" />
 <ColorMapEntry color="#000000" quantity="2000" label="values" />
 </ColorMap>
 </RasterSymbolizer>
 </Rule>
 </FeatureTypeStyle>
 </UserStyle>
 </NamedLayer>
</StyledLayerDescriptor>

Filter Example (1):

{quote}{}NOTE take a look to the filters shown here which should result in an OpenLayer compatible representation. {quote}

{
   getLegendGraphic:[
      {
         description:null,
         title:"Default",
         name:"Default",
         symbolyzers:[
            {
               name:"Default",
               description:null,
               title:"Default",
               Polygon:{
                  fill:true,
                  opacity:0,
                  fillColor:"#ffffff",
                  strokeColor:"#c0c0c0",
                  strokeDashArray:"null",
                  strokeDashOffset:0
               },
               geometry:null,
               geometryPropertyName:null
            }
         ]
      },
      {
         description:"...",
         title:"class0",
         name:"class0",
         filter:{
            type:"<=",
            property:"total_usd_percapita",
            value:"env([c0_upper], [1])",
            matchCase:false
         },
         symbolyzers:[
            {
               name:"class0",
               description:"...",
               title:"class0",
               Polygon:{
                  fill:true,
                  opacity:1,
                  fillColor:"env([c0_fill], [#00ff00])"
               },
               geometry:null,
               geometryPropertyName:null
            }
         ]
      },
      {
         description:"...",
         title:"class1",
         name:"class1",
         filter:{
            type:"&&",
            filters:[
               {
                  type:"<=",
                  property:"total_usd_percapita",
                  value:"env([c1_upper], [2])",
                  matchCase:false
               },
               {
                  type:">",
                  property:"total_usd_percapita",
                  value:"env([c1_lower], [1])",
                  matchCase:true
               }
            ]
         },
         symbolyzers:[
            {
               name:"class1",
               description:"...",
               title:"class1",
               Polygon:{
                  fill:true,
                  opacity:1,
                  fillColor:"env([c1_fill], [#00ff00])"
               },
               geometry:null,
               geometryPropertyName:null
            }
         ]
      },
      {
         description:"...",
         title:"class2",
         name:"class2",
         filter:{
            type:"&&",
            filters:[
               {
                  type:"<=",
                  property:"total_usd_percapita",
                  value:"env([c2_upper], [4])",
                  matchCase:false
               },
               {
                  type:">",
                  property:"total_usd_percapita",
                  value:"env([c2_lower], [2])",
                  matchCase:true
               }
            ]
         },
         symbolyzers:[
            {
               name:"class2",
               description:"...",
               title:"class2",
               Polygon:{
                  fill:true,
                  opacity:1,
                  fillColor:"env([c2_fill], [#00ff00])"
               },
               geometry:null,
               geometryPropertyName:null
            }
         ]
      },
      {
         description:"...",
         title:"class3",
         name:"class3",
         filter:{
            type:"&&",
            filters:[
               {
                  type:"<=",
                  property:"total_usd_percapita",
                  value:"env([c3_upper], [5])",
                  matchCase:false
               },
               {
                  type:">",
                  property:"total_usd_percapita",
                  value:"env([c3_lower], [4])",
                  matchCase:true
               }
            ]
         },
         symbolyzers:[
            {
               name:"class3",
               description:"...",
               title:"class3",
               Polygon:{
                  fill:true,
                  opacity:1,
                  fillColor:"env([c3_fill], [#00ff00])"
               },
               geometry:null,
               geometryPropertyName:null
            }
         ]
      },
      {
         description:"...",
         title:"class4",
         name:"class4",
         filter:{
            type:">",
            property:"total_usd_percapita",
            value:"env([c4_lower], [5])",
            matchCase:true
         },
         symbolyzers:[
            {
               name:"class4",
               description:"...",
               title:"class4",
               Polygon:{
                  fill:true,
                  opacity:1,
                  fillColor:"env([c4_fill], [#00ff00])"
               },
               geometry:null,
               geometryPropertyName:null
            }
         ]
      }
   ]
}

Filter Example (2):

{
   getLegendGraphic:[
      {
         description:"...",
         title:"no_data",
         name:"no_data",
         filter:{
            type:"==",
            property:"fk_d_area",
            value:0,
            matchCase:true
         },
         symbolyzers:[
            {
               name:"no_data",
               description:"...",
               title:"no_data",
               Polygon:{
                  fill:true,
                  opacity:1,
                  fillColor:"#cccccc"
               },
               geometry:null,
               geometryPropertyName:null
            }
         ]
      },
      {
         description:"...",
         title:"class0",
         name:"class0",
         filter:{
            type:"&&",
            filters:[
               {
                  type:"!=",
                  property:"fk_d_area",
                  value:0,
                  matchCase:true
               },
               {
                  type:"<",
                  property:"at_value",
                  value:"env([c0_upper], [0])",
                  matchCase:false
               }
            ]
         },
         symbolyzers:[
            {
               name:"class0",
               description:"...",
               title:"class0",
               Polygon:{
                  fill:true,
                  opacity:1,
                  fillColor:"env([c0_fill], [#ffffff])"
               },
               geometry:null,
               geometryPropertyName:null
            }
         ]
      },
      {
         description:"...",
         title:"class1",
         name:"class1",
         filter:{
            type:"&&",
            filters:[
               {
                  type:"!=",
                  property:"fk_d_area",
                  value:0,
                  matchCase:true
               },
               {
                  type:">=",
                  property:"at_value",
                  value:"env([c1_lower], [0])",
                  matchCase:false
               },
               {
                  type:"<",
                  property:"at_value",
                  value:"env([c1_upper], [500])",
                  matchCase:false
               }
            ]
         },
         symbolyzers:[
            {
               name:"class1",
               description:"...",
               title:"class1",
               Polygon:{
                  fill:true,
                  opacity:1,
                  fillColor:"env([c1_fill], [#cccccc])"
               },
               geometry:null,
               geometryPropertyName:null
            }
         ]
      },
      {
         description:"...",
         title:"class2",
         name:"class2",
         filter:{
            type:"&&",
            filters:[
               {
                  type:"!=",
                  property:"fk_d_area",
                  value:0,
                  matchCase:true
               },
               {
                  type:">=",
                  property:"at_value",
                  value:"env([c2_lower], [500])",
                  matchCase:false
               },
               {
                  type:"<",
                  property:"at_value",
                  value:"env([c2_upper], [1000])",
                  matchCase:false
               }
            ]
         },
         symbolyzers:[
            {
               name:"class2",
               description:"...",
               title:"class2",
               Polygon:{
                  fill:true,
                  opacity:1,
                  fillColor:"env([c2_fill], [#BEDED8])"
               },
               geometry:null,
               geometryPropertyName:null
            }
         ]
      },
      {
         description:"...",
         title:"class3",
         name:"class3",
         filter:{
            type:"&&",
            filters:[
               {
                  type:"!=",
                  property:"fk_d_area",
                  value:0,
                  matchCase:true
               },
               {
                  type:">=",
                  property:"at_value",
                  value:"env([c3_lower], [1000])",
                  matchCase:false
               },
               {
                  type:"<",
                  property:"at_value",
                  value:"env([c3_upper], [1700])",
                  matchCase:false
               }
            ]
         },
         symbolyzers:[
            {
               name:"class3",
               description:"...",
               title:"class3",
               Polygon:{
                  fill:true,
                  opacity:1,
                  fillColor:"env([c3_fill], [#6BAFB6])"
               },
               geometry:null,
               geometryPropertyName:null
            }
         ]
      },
      {
         description:"...",
         title:"class4",
         name:"class4",
         filter:{
            type:"&&",
            filters:[
               {
                  type:"!=",
                  property:"fk_d_area",
                  value:0,
                  matchCase:true
               },
               {
                  type:">=",
                  property:"at_value",
                  value:"env([c4_lower], [1700])",
                  matchCase:false
               },
               {
                  type:"<",
                  property:"at_value",
                  value:"env([c4_upper], [6000])",
                  matchCase:false
               }
            ]
         },
         symbolyzers:[
            {
               name:"class4",
               description:"...",
               title:"class4",
               Polygon:{
                  fill:true,
                  opacity:1,
                  fillColor:"env([c4_fill], [#2C80B8])"
               },
               geometry:null,
               geometryPropertyName:null
            }
         ]
      },
      {
         description:"...",
         title:"class5",
         name:"class5",
         filter:{
            type:"&&",
            filters:[
               {
                  type:"!=",
                  property:"fk_d_area",
                  value:0,
                  matchCase:true
               },
               {
                  type:">=",
                  property:"at_value",
                  value:"env([c5_lower], [6000])",
                  matchCase:false
               }
            ]
         },
         symbolyzers:[
            {
               name:"class5",
               description:"...",
               title:"class5",
               Polygon:{
                  fill:true,
                  opacity:1,
                  fillColor:"env([c5_fill], [#08559C])"
               },
               geometry:null,
               geometryPropertyName:null
            }
         ]
      }
   ]
}

Feedback

This section should contain feedback provided by PSC members who may have a problem with the proposal.

Backwards Compatibility

Regarding the outputFormat and the format parameter, currently the unique way to add as add on (without modify the current getLegendGraphic output format) is implementing another response handler and a new output format which may results in query like:

[http://localhost:8080/geoserver/topp/wms?service=WMS&version=1.1.0&request=GetLegendGraphic&layer=topp:states&styles=population2&bbox=-124.73142200000001,24.955967,-66.969849,49.371735&width=780&height=330&srs=EPSG:4326&format=application/json&outputFormat=application/json]

For a better integration of the getLegendGraphic I think we may define if we want to switch using different responseHandlers or continue working with outputFormats.Let’s analyse differences:

Voting

Alessio Fabiani: Andrea Aime: Ben Caradoc Davies: +0 Christian Mueller: +0 Gabriel Roldan: Jody Garnett: Jukka Rahkonen: Justin Deoliveira: Phil Scadden: +1 Simone Giannecchini:

Links

JIRA Task Email Discussion Wiki Page

Clone this wiki locally