001 //$HeadURL: http://svn.wald.intevation.org/svn/deegree/base/trunk/src/org/deegree/graphics/sld/SLDFactory.java $ 002 /*---------------------------------------------------------------------------- 003 This file is part of deegree, http://deegree.org/ 004 Copyright (C) 2001-2009 by: 005 Department of Geography, University of Bonn 006 and 007 lat/lon GmbH 008 009 This library is free software; you can redistribute it and/or modify it under 010 the terms of the GNU Lesser General Public License as published by the Free 011 Software Foundation; either version 2.1 of the License, or (at your option) 012 any later version. 013 This library is distributed in the hope that it will be useful, but WITHOUT 014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 015 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 016 details. 017 You should have received a copy of the GNU Lesser General Public License 018 along with this library; if not, write to the Free Software Foundation, Inc., 019 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 020 021 Contact information: 022 023 lat/lon GmbH 024 Aennchenstr. 19, 53177 Bonn 025 Germany 026 http://lat-lon.de/ 027 028 Department of Geography, University of Bonn 029 Prof. Dr. Klaus Greve 030 Postfach 1147, 53001 Bonn 031 Germany 032 http://www.geographie.uni-bonn.de/deegree/ 033 034 e-mail: info@deegree.org 035 ----------------------------------------------------------------------------*/ 036 package org.deegree.graphics.sld; 037 038 import static java.lang.Float.parseFloat; 039 import static java.lang.StrictMath.sqrt; 040 import static org.deegree.framework.xml.XMLTools.getElement; 041 import static org.deegree.framework.xml.XMLTools.getNodeAsDouble; 042 import static org.deegree.ogcbase.CommonNamespaces.SLDNS; 043 import static org.deegree.ogcbase.CommonNamespaces.SLD_PREFIX; 044 045 import java.io.IOException; 046 import java.io.StringReader; 047 import java.net.MalformedURLException; 048 import java.net.URI; 049 import java.net.URL; 050 import java.util.ArrayList; 051 import java.util.HashMap; 052 import java.util.Iterator; 053 import java.util.LinkedList; 054 import java.util.List; 055 056 import org.deegree.datatypes.QualifiedName; 057 import org.deegree.framework.log.ILogger; 058 import org.deegree.framework.log.LoggerFactory; 059 import org.deegree.framework.xml.ElementList; 060 import org.deegree.framework.xml.NamespaceContext; 061 import org.deegree.framework.xml.XMLFragment; 062 import org.deegree.framework.xml.XMLParsingException; 063 import org.deegree.framework.xml.XMLTools; 064 import org.deegree.model.filterencoding.AbstractFilter; 065 import org.deegree.model.filterencoding.ComplexFilter; 066 import org.deegree.model.filterencoding.Expression; 067 import org.deegree.model.filterencoding.FalseFilter; 068 import org.deegree.model.filterencoding.Filter; 069 import org.deegree.model.filterencoding.FilterEvaluationException; 070 import org.deegree.model.filterencoding.LogicalOperation; 071 import org.deegree.model.filterencoding.Operation; 072 import org.deegree.model.filterencoding.OperationDefines; 073 import org.deegree.ogcbase.CommonNamespaces; 074 import org.deegree.ogcbase.OGCDocument; 075 import org.deegree.ogcbase.PropertyPath; 076 import org.w3c.dom.Element; 077 import org.w3c.dom.Node; 078 import org.w3c.dom.NodeList; 079 import org.w3c.dom.Text; 080 import org.xml.sax.SAXException; 081 082 /** 083 * Factory class for all mapped SLD-elements. 084 * <p> 085 * TODO: Default values for omitted elements (such as fill color) should better not be used in the construction of the 086 * corresponding objects (Fill), but marked as left out (to make it possible to differentiate between explicitly given 087 * values and default values). 088 * <p> 089 * 090 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> 091 * @author <a href="mailto:mschneider@lat-lon.de">Markus Schneider</a> 092 * @version $Revision: 30390 $ $Date: 2011-04-07 10:21:25 +0200 (Thu, 07 Apr 2011) $ 093 */ 094 public class SLDFactory { 095 096 private static final ILogger LOG = LoggerFactory.getLogger( SLDFactory.class ); 097 098 private static URI ogcNS = CommonNamespaces.OGCNS; 099 100 private static URI xlnNS = CommonNamespaces.XLNNS; 101 102 private static final String PSE = CommonNamespaces.SE_PREFIX + ":"; 103 104 private static NamespaceContext nsContext = CommonNamespaces.getNamespaceContext(); 105 106 private static XMLFragment sldDoc = null; 107 108 /** 109 * Creates a <tt>StyledLayerDescriptor</tt>-instance from the given XML-representation. 110 * <p> 111 * 112 * @param s 113 * contains the XML document 114 * @throws XMLParsingException 115 * if a syntactic or semantic error in the XML document is encountered 116 * @return the constructed <tt>StyledLayerDescriptor</tt>-instance 117 */ 118 public static synchronized StyledLayerDescriptor createSLD( String s ) 119 throws XMLParsingException { 120 StyledLayerDescriptor sld = null; 121 try { 122 sldDoc = new XMLFragment(); 123 sldDoc.load( new StringReader( s.trim() ), XMLFragment.DEFAULT_URL ); 124 sld = createSLD( sldDoc ); 125 } catch ( IOException e ) { 126 LOG.logDebug( e.getMessage(), e ); 127 throw new XMLParsingException( "IOException encountered while parsing SLD-Document" ); 128 } catch ( SAXException e ) { 129 LOG.logDebug( e.getMessage(), e ); 130 throw new XMLParsingException( "SAXException encountered while parsing SLD-Document" ); 131 } 132 133 return sld; 134 } 135 136 /** 137 * Creates a <tt>StyledLayerDescriptor</tt>-instance from a SLD document read from the passed URL 138 * 139 * @param url 140 * @return the SLD bean 141 * @throws XMLParsingException 142 */ 143 public static synchronized StyledLayerDescriptor createSLD( URL url ) 144 throws XMLParsingException { 145 StyledLayerDescriptor sld = null; 146 147 try { 148 sldDoc = new XMLFragment(); 149 sldDoc.load( url ); 150 sld = createSLD( sldDoc ); 151 } catch ( IOException e ) { 152 LOG.logError( e.getMessage(), e ); 153 throw new XMLParsingException( "IOException encountered while parsing SLD-Document" ); 154 } catch ( SAXException e ) { 155 LOG.logError( e.getMessage(), e ); 156 throw new XMLParsingException( "SAXException encountered while parsing SLD-Document" ); 157 } 158 159 return sld; 160 } 161 162 /** 163 * Creates a <tt>StyledLayerDescriptor</tt>-instance according to the contents of the DOM-subtree starting at the 164 * given 'StyledLayerDescriptor'-<tt>Element</tt>. 165 * <p> 166 * 167 * @param sldDoc 168 * 169 * @throws XMLParsingException 170 * if a syntactic or semantic error in the DOM-subtree is encountered 171 * @return the constructed <tt>StyledLayerDescriptor</tt>-instance 172 */ 173 public static StyledLayerDescriptor createSLD( XMLFragment sldDoc ) 174 throws XMLParsingException { 175 176 Element element = sldDoc.getRootElement(); 177 178 // optional: <Name> 179 String name = XMLTools.getStringValue( "Name", CommonNamespaces.SLDNS, element, null ); 180 181 // optional: <Title> 182 String title = XMLTools.getStringValue( "Title", CommonNamespaces.SLDNS, element, null ); 183 // optional: <Abstract> 184 String abstract_ = XMLTools.getStringValue( "Abstract", CommonNamespaces.SLDNS, element, null ); 185 // required: version-Attribute 186 String version = XMLTools.getRequiredAttrValue( "version", null, element ); 187 188 // optional: <NamedLayer>(s) / <UserLayer>(s) 189 NodeList nodelist = element.getChildNodes(); 190 ArrayList<AbstractLayer> layerList = new ArrayList<AbstractLayer>( 100 ); 191 192 for ( int i = 0; i < nodelist.getLength(); i++ ) { 193 if ( nodelist.item( i ) instanceof Element ) { 194 Element child = (Element) nodelist.item( i ); 195 String namespace = child.getNamespaceURI(); 196 if ( !CommonNamespaces.SLDNS.toASCIIString().equals( namespace ) ) { 197 continue; 198 } 199 200 String childName = child.getLocalName(); 201 if ( childName.equals( "NamedLayer" ) ) { 202 layerList.add( createNamedLayer( child ) ); 203 } else if ( childName.equals( "UserLayer" ) ) { 204 layerList.add( createUserLayer( child ) ); 205 } 206 } 207 } 208 209 AbstractLayer[] al = new AbstractLayer[layerList.size()]; 210 AbstractLayer[] layers = layerList.toArray( al ); 211 212 return new StyledLayerDescriptor( name, title, version, abstract_, layers ); 213 } 214 215 private static Categorize createCategorize( Element root ) 216 throws XMLParsingException { 217 // ignore fallback value, we really implement it 218 // String fallbackValue = root.getAttribute( "fallbackValue" ); 219 220 Categorize categorize = new Categorize(); 221 222 // ignore lookup value element, should be set to "Rasterdata" 223 // Element lv = XMLTools.getElement( root, PSE + "LookupValue", nsContext ); 224 // ParameterValueType lookupValue = lv == null ? null : createParameterValueType( lv ); 225 // 226 // if ( lookupValue != null ) { 227 // categorize.setLookupValue( lookupValue ); 228 // } 229 230 List<Element> valueElements = XMLTools.getElements( root, PSE + "Value", nsContext ); 231 List<Element> thresholdElements = XMLTools.getElements( root, PSE + "Threshold", nsContext ); 232 233 LinkedList<ParameterValueType> values = new LinkedList<ParameterValueType>(); 234 LinkedList<ParameterValueType> thresholds = new LinkedList<ParameterValueType>(); 235 236 for ( Element e : valueElements ) { 237 values.add( createParameterValueType( e ) ); 238 } 239 240 for ( Element e : thresholdElements ) { 241 thresholds.add( createParameterValueType( e ) ); 242 } 243 244 categorize.setValues( values ); 245 categorize.setThresholds( thresholds ); 246 247 String tbt = root.getAttribute( "threshholdsBelongTo" ); 248 if ( tbt == null ) { 249 tbt = root.getAttribute( "thresholdsBelongTo" ); 250 } 251 252 ThresholdsBelongTo thresholdsBelongTo = null; 253 254 if ( tbt != null ) { 255 if ( tbt.equalsIgnoreCase( "succeeding" ) ) { 256 thresholdsBelongTo = ThresholdsBelongTo.SUCCEEDING; 257 } 258 if ( tbt.equalsIgnoreCase( "preceding" ) ) { 259 thresholdsBelongTo = ThresholdsBelongTo.PRECEDING; 260 } 261 } 262 263 if ( thresholdsBelongTo != null ) { 264 categorize.setThresholdsBelongTo( thresholdsBelongTo ); 265 } 266 267 return categorize; 268 } 269 270 /** 271 * 272 * @param root 273 * @param min 274 * @param max 275 * @return a raster symbolizer 276 * @throws XMLParsingException 277 */ 278 private static RasterSymbolizer createRasterSymbolizer( Element root, double min, double max ) 279 throws XMLParsingException { 280 RasterSymbolizer symbolizer = new RasterSymbolizer( min, max ); 281 282 if ( root.getAttribute( "shaded" ) != null && root.getAttribute( "shaded" ).equals( "true" ) ) { 283 symbolizer.setShaded( true ); 284 285 String kernelAtt = root.getAttribute( "kernel" ); 286 if ( kernelAtt == null || kernelAtt.trim().length() == 0 ) { 287 kernelAtt = "0, 1, 2, -1, 1, 1, -2, -1, 0"; 288 } 289 String[] vals = kernelAtt.split( "[,]" ); 290 float[] kernel = new float[vals.length]; 291 for ( int i = 0; i < vals.length; ++i ) { 292 kernel[i] = parseFloat( vals[i] ); 293 } 294 295 symbolizer.setShadeKernel( (int) sqrt( kernel.length ), kernel ); 296 } 297 298 Element opacity = XMLTools.getElement( root, PSE + "Opacity", nsContext ); 299 if ( opacity != null ) { 300 symbolizer.setOpacity( createParameterValueType( opacity ) ); 301 } 302 303 Element colorMap = XMLTools.getElement( root, PSE + "ColorMap", nsContext ); 304 if ( colorMap != null ) { 305 Element categorize = XMLTools.getElement( colorMap, PSE + "Categorize", nsContext ); 306 307 if ( categorize != null ) { 308 symbolizer.setCategorize( createCategorize( categorize ) ); 309 } 310 311 Element interpolate = XMLTools.getElement( colorMap, PSE + "Interpolate", nsContext ); 312 313 if ( interpolate != null ) { 314 symbolizer.setInterpolate( createInterpolate( interpolate ) ); 315 } 316 } 317 318 Element contrastEnhancement = getElement( root, PSE + "ContrastEnhancement", nsContext ); 319 if ( contrastEnhancement != null ) { 320 symbolizer.setGamma( getNodeAsDouble( contrastEnhancement, PSE + "GammaValue", nsContext, 0d ) ); 321 } 322 323 return symbolizer; 324 } 325 326 /** 327 * @param root 328 * @return an Interpolate object 329 * @throws XMLParsingException 330 */ 331 private static Interpolate createInterpolate( Element root ) 332 throws XMLParsingException { 333 String fallbackValue = root.getAttribute( "fallbackValue" ); 334 335 Interpolate interpolate = new Interpolate( fallbackValue ); 336 337 Element elem = XMLTools.getElement( root, PSE + "lookupValue", nsContext ); 338 if ( elem != null ) { 339 interpolate.setLookupValue( createParameterValueType( elem ) ); 340 } 341 342 String mode = root.getAttribute( "mode" ); 343 if ( mode != null ) { 344 if ( mode.equalsIgnoreCase( "linear" ) ) { 345 interpolate.setMode( Mode.LINEAR ); 346 } 347 if ( mode.equalsIgnoreCase( "cosine" ) ) { 348 LOG.logWarning( "Cosine interpolation is not supported." ); 349 interpolate.setMode( Mode.COSINE ); 350 } 351 if ( mode.equalsIgnoreCase( "cubic" ) ) { 352 LOG.logWarning( "Cubic interpolation is not supported." ); 353 interpolate.setMode( Mode.CUBIC ); 354 } 355 } 356 357 String method = root.getAttribute( "method" ); 358 if ( method != null ) { 359 if ( method.equalsIgnoreCase( "numeric" ) ) { 360 LOG.logWarning( "Numeric method is not supported, using color method anyway." ); 361 interpolate.setMethod( Method.NUMERIC ); 362 } 363 if ( method.equalsIgnoreCase( "color" ) ) { 364 interpolate.setMethod( Method.COLOR ); 365 } 366 } 367 368 List<Element> ips = XMLTools.getElements( root, PSE + "InterpolationPoint", nsContext ); 369 370 interpolate.setInterpolationPoints( createInterpolationPoints( ips ) ); 371 372 return interpolate; 373 } 374 375 private static List<InterpolationPoint> createInterpolationPoints( List<Element> ips ) 376 throws XMLParsingException { 377 List<InterpolationPoint> ps = new ArrayList<InterpolationPoint>( ips.size() ); 378 379 for ( Element elem : ips ) { 380 double data = XMLTools.getRequiredNodeAsDouble( elem, PSE + "Data", nsContext ); 381 Element e = XMLTools.getRequiredElement( elem, PSE + "Value", nsContext ); 382 try { 383 String val = createParameterValueType( e ).evaluate( null ).substring( 1 ); 384 ps.add( new InterpolationPoint( data, val ) ); 385 } catch ( NumberFormatException e1 ) { 386 LOG.logError( "A 'Value' in an 'InterpolationPoint' could not be parsed.", e1 ); 387 } catch ( FilterEvaluationException e1 ) { 388 LOG.logError( "A 'Value' in an 'InterpolationPoint' could not be parsed.", e1 ); 389 } 390 } 391 392 return ps; 393 } 394 395 /** 396 * Creates a <tt>TextSymbolizer</tt>-instance according to the contents of the DOM-subtree starting at the given 397 * 'TextSymbolizer'-<tt>Element</tt>. 398 * <p> 399 * 400 * @param element 401 * the 'TextSymbolizer'-<tt>Element</tt> 402 * @param min 403 * scale-constraint to be used 404 * @param max 405 * scale-constraint to be used 406 * @throws XMLParsingException 407 * if a syntactic or semantic error in the DOM-subtree is encountered 408 * @return the constructed <tt>TextSymbolizer</tt>-instance 409 */ 410 private static TextSymbolizer createTextSymbolizer( Element element, double min, double max ) 411 throws XMLParsingException { 412 413 // optional: <Geometry> 414 Geometry geometry = null; 415 Element geometryElement = XMLTools.getChildElement( "Geometry", CommonNamespaces.SLDNS, element ); 416 417 if ( geometryElement != null ) { 418 geometry = createGeometry( geometryElement ); 419 } 420 421 // optional: <Label> 422 ParameterValueType label = null; 423 Element labelElement = XMLTools.getChildElement( "Label", CommonNamespaces.SLDNS, element ); 424 425 if ( labelElement != null ) { 426 label = createParameterValueType( labelElement ); 427 } 428 429 // optional: <Font> 430 Font font = null; 431 Element fontElement = XMLTools.getChildElement( "Font", CommonNamespaces.SLDNS, element ); 432 433 if ( fontElement != null ) { 434 font = createFont( fontElement ); 435 } 436 437 // optional: <LabelPlacement> 438 LabelPlacement labelPlacement = null; 439 Element lpElement = XMLTools.getChildElement( "LabelPlacement", CommonNamespaces.SLDNS, element ); 440 441 if ( lpElement != null ) { 442 labelPlacement = createLabelPlacement( lpElement ); 443 } else { 444 PointPlacement pp = StyleFactory.createPointPlacement(); 445 labelPlacement = StyleFactory.createLabelPlacement( pp ); 446 } 447 448 // optional: <Halo> 449 Halo halo = null; 450 Element haloElement = XMLTools.getChildElement( "Halo", SLDNS, element ); 451 452 if ( haloElement != null ) { 453 halo = createHalo( haloElement ); 454 } 455 456 // optional: <Fill> 457 Fill fill = null; 458 459 TextSymbolizer ps = null; 460 461 // deegree specific extension: 462 Element bbox = getElement( element, SLD_PREFIX + ":BoundingBox", nsContext ); 463 if ( bbox != null ) { 464 try { 465 ParameterValueType minx = createParameterValueType( getElement( bbox, SLD_PREFIX + ":Minx", nsContext ) ); 466 ParameterValueType miny = createParameterValueType( getElement( bbox, SLD_PREFIX + ":Miny", nsContext ) ); 467 ParameterValueType maxx = createParameterValueType( getElement( bbox, SLD_PREFIX + ":Maxx", nsContext ) ); 468 ParameterValueType maxy = createParameterValueType( getElement( bbox, SLD_PREFIX + ":Maxy", nsContext ) ); 469 470 ps = new TextSymbolizer( geometry, label, font, halo, minx, miny, maxx, maxy ); 471 } catch ( NullPointerException npe ) { 472 npe.printStackTrace(); 473 LOG.logError( "One of Minx, Miny, Maxx, Maxy was missing in a BoundingBox." ); 474 } 475 } else { 476 477 String respClass = XMLTools.getAttrValue( element, null, "responsibleClass", null ); 478 if ( respClass == null ) { 479 ps = new TextSymbolizer( geometry, label, font, labelPlacement, halo, fill, min, max ); 480 } else { 481 ps = new TextSymbolizer( geometry, respClass, label, font, labelPlacement, halo, fill, min, max ); 482 } 483 } 484 485 return ps; 486 } 487 488 /** 489 * Creates a <tt>Halo</tt>-instance according to the contents of the DOM-subtree starting at the given 'Halo'- 490 * <tt>Element</tt>. 491 * <p> 492 * 493 * @param element 494 * the 'Halo'-<tt>Element</tt> 495 * @throws XMLParsingException 496 * if a syntactic or semantic error in the DOM-subtree is encountered 497 * @return the constructed <tt>Halo</tt>-instance 498 */ 499 private static Halo createHalo( Element element ) 500 throws XMLParsingException { 501 // optional: <Radius> 502 ParameterValueType radius = null; 503 Element radiusElement = XMLTools.getChildElement( "Radius", CommonNamespaces.SLDNS, element ); 504 505 if ( radiusElement != null ) { 506 radius = createParameterValueType( radiusElement ); 507 } 508 509 // optional: <Fill> 510 Fill fill = null; 511 Element fillElement = XMLTools.getChildElement( "Fill", CommonNamespaces.SLDNS, element ); 512 513 if ( fillElement != null ) { 514 fill = createFill( fillElement ); 515 } 516 517 // optional: <Stroke> 518 Stroke stroke = null; 519 Element strokeElement = XMLTools.getChildElement( "Stroke", CommonNamespaces.SLDNS, element ); 520 521 if ( strokeElement != null ) { 522 stroke = createStroke( strokeElement ); 523 } 524 525 return new Halo( radius, fill, stroke ); 526 } 527 528 /** 529 * Creates a <tt>LabelPlacement</tt>-instance according to the contents of the DOM-subtree starting at the given 530 * 'LabelPlacement'-<tt>Element</tt>. 531 * <p> 532 * 533 * @param element 534 * the 'LabelPlacement'-<tt>Element</tt> 535 * @throws XMLParsingException 536 * if a syntactic or semantic error in the DOM-subtree is encountered 537 * @return the constructed <tt>LabelPlacement</tt>-instance 538 */ 539 private static LabelPlacement createLabelPlacement( Element element ) 540 throws XMLParsingException { 541 LabelPlacement labelPlacement = null; 542 543 // required: <PointPlacement> / <LinePlacement> 544 NodeList nodelist = element.getChildNodes(); 545 PointPlacement pPlacement = null; 546 LinePlacement lPlacement = null; 547 548 for ( int i = 0; i < nodelist.getLength(); i++ ) { 549 if ( nodelist.item( i ) instanceof Element ) { 550 Element child = (Element) nodelist.item( i ); 551 String namespace = child.getNamespaceURI(); 552 553 if ( !CommonNamespaces.SLDNS.toASCIIString().equals( namespace ) ) { 554 continue; 555 } 556 557 String childName = child.getLocalName(); 558 559 if ( childName.equals( "PointPlacement" ) ) { 560 pPlacement = createPointPlacement( child ); 561 } else if ( childName.equals( "LinePlacement" ) ) { 562 lPlacement = createLinePlacement( child ); 563 } 564 } 565 } 566 567 if ( ( pPlacement != null ) && ( lPlacement == null ) ) { 568 labelPlacement = new LabelPlacement( pPlacement ); 569 } else if ( ( pPlacement == null ) && ( lPlacement != null ) ) { 570 labelPlacement = new LabelPlacement( lPlacement ); 571 } else { 572 throw new XMLParsingException( "Element 'LabelPlacement' must contain exactly one " 573 + "'PointPlacement'- or one 'LinePlacement'-element!" ); 574 } 575 576 return labelPlacement; 577 } 578 579 /** 580 * Creates a <tt>PointPlacement</tt>-instance according to the contents of the DOM-subtree starting at the given 581 * 'PointPlacement'-<tt>Element</tt>. 582 * <p> 583 * 584 * @param element 585 * the 'PointPlacement'-<tt>Element</tt> 586 * @throws XMLParsingException 587 * if a syntactic or semantic error in the DOM-subtree is encountered 588 * @return the constructed <tt>PointPlacement</tt>-instance 589 */ 590 private static PointPlacement createPointPlacement( Element element ) 591 throws XMLParsingException { 592 593 // optional: auto-Attribute (this is deegree-specific) 594 boolean auto = false; 595 String autoStr = XMLTools.getAttrValue( element, null, "auto", null ); 596 597 if ( autoStr != null && autoStr.equals( "true" ) ) { 598 auto = true; 599 } 600 601 // optional: <AnchorPoint> 602 ParameterValueType[] anchorPoint = null; 603 Element apElement = XMLTools.getChildElement( "AnchorPoint", CommonNamespaces.SLDNS, element ); 604 605 if ( apElement != null ) { 606 anchorPoint = new ParameterValueType[2]; 607 608 Element apXElement = XMLTools.getChildElement( "AnchorPointX", CommonNamespaces.SLDNS, apElement ); 609 Element apYElement = XMLTools.getChildElement( "AnchorPointY", CommonNamespaces.SLDNS, apElement ); 610 611 if ( ( apXElement == null ) || ( apYElement == null ) ) { 612 throw new XMLParsingException( "Element 'AnchorPoint' must contain exactly one " 613 + "'AnchorPointX'- and one 'AnchorPointY'-element!" ); 614 } 615 616 anchorPoint[0] = createParameterValueType( apXElement ); 617 anchorPoint[1] = createParameterValueType( apYElement ); 618 } 619 620 // optional: <Displacement> 621 ParameterValueType[] displacement = null; 622 Element dElement = XMLTools.getChildElement( "Displacement", CommonNamespaces.SLDNS, element ); 623 624 if ( dElement != null ) { 625 displacement = new ParameterValueType[2]; 626 627 Element dXElement = XMLTools.getChildElement( "DisplacementX", CommonNamespaces.SLDNS, dElement ); 628 Element dYElement = XMLTools.getChildElement( "DisplacementY", CommonNamespaces.SLDNS, dElement ); 629 630 if ( ( dXElement == null ) || ( dYElement == null ) ) { 631 throw new XMLParsingException( "Element 'Displacement' must contain exactly one " 632 + "'DisplacementX'- and one 'DisplacementY'-element!" ); 633 } 634 635 displacement[0] = createParameterValueType( dXElement ); 636 displacement[1] = createParameterValueType( dYElement ); 637 } 638 639 // optional: <Rotation> 640 ParameterValueType rotation = null; 641 Element rElement = XMLTools.getChildElement( "Rotation", CommonNamespaces.SLDNS, element ); 642 643 if ( rElement != null ) { 644 rotation = createParameterValueType( rElement ); 645 } 646 647 return new PointPlacement( anchorPoint, displacement, rotation, auto ); 648 } 649 650 /** 651 * Creates a <tt>LinePlacement</tt>-instance according to the contents of the DOM-subtree starting at the given 652 * 'LinePlacement'-<tt>Element</tt>. 653 * <p> 654 * 655 * @param element 656 * the 'LinePlacement'-<tt>Element</tt> 657 * @throws XMLParsingException 658 * if a syntactic or semantic error in the DOM-subtree is encountered 659 * @return the constructed <tt>LinePlacement</tt>-instance 660 */ 661 private static LinePlacement createLinePlacement( Element element ) 662 throws XMLParsingException { 663 664 // optional: <PerpendicularOffset> 665 ParameterValueType pOffset = null; 666 Element pOffsetElement = XMLTools.getChildElement( "PerpendicularOffset", CommonNamespaces.SLDNS, element ); 667 668 if ( pOffsetElement != null ) { 669 pOffset = createParameterValueType( pOffsetElement ); 670 } 671 672 // optional: <Gap> (this is deegree-specific) 673 ParameterValueType gap = null; 674 Element gapElement = XMLTools.getChildElement( "Gap", CommonNamespaces.SLDNS, element ); 675 676 if ( gapElement != null ) { 677 gap = createParameterValueType( gapElement ); 678 } 679 680 // optional: <LineWidth> (this is deegree-specific) 681 ParameterValueType lineWidth = null; 682 Element lineWidthElement = XMLTools.getChildElement( "LineWidth", CommonNamespaces.SLDNS, element ); 683 684 if ( lineWidthElement != null ) { 685 lineWidth = createParameterValueType( lineWidthElement ); 686 } 687 688 return new LinePlacement( pOffset, lineWidth, gap ); 689 } 690 691 /** 692 * Creates a <tt>Font</tt>-instance according to the contents of the DOM-subtree starting at the given 'Font'- 693 * <tt>Element</tt>. 694 * <p> 695 * 696 * @param element 697 * the 'Font'-<tt>Element</tt> 698 * @throws XMLParsingException 699 * if a syntactic or semantic error in the DOM-subtree is encountered 700 * @return the constructed <tt>Font</tt>-instance 701 */ 702 private static Font createFont( Element element ) 703 throws XMLParsingException { 704 705 // optional: <CssParameter>s 706 ElementList nl = XMLTools.getChildElements( "CssParameter", CommonNamespaces.SLDNS, element ); 707 HashMap<String, CssParameter> cssParams = new HashMap<String, CssParameter>( nl.getLength() ); 708 709 for ( int i = 0; i < nl.getLength(); i++ ) { 710 CssParameter cssParam = createCssParameter( nl.item( i ) ); 711 cssParams.put( cssParam.getName(), cssParam ); 712 } 713 714 return new Font( cssParams ); 715 } 716 717 /** 718 * Creates a <tt>ParameterValueType</tt>-instance according to the contents of the DOM-subtree starting at the given 719 * <tt>Element</tt>. 720 * <p> 721 * 722 * @param element 723 * the <tt>Element</tt> (must be of the type sld:ParameterValueType) 724 * @throws XMLParsingException 725 * if a syntactic or semantic error in the DOM-subtree is encountered 726 * @return the constructed <tt>ParameterValueType</tt>-instance 727 */ 728 private static ParameterValueType createParameterValueType( Element element ) 729 throws XMLParsingException { 730 // mix of text nodes and <wfs:Expression>-elements 731 ArrayList<Object> componentList = new ArrayList<Object>(); 732 NodeList nl = element.getChildNodes(); 733 734 for ( int i = 0; i < nl.getLength(); i++ ) { 735 Node node = nl.item( i ); 736 737 switch ( node.getNodeType() ) { 738 case Node.TEXT_NODE: { 739 componentList.add( node.getNodeValue() ); 740 break; 741 } 742 case Node.ELEMENT_NODE: { 743 Expression expression = Expression.buildFromDOM( (Element) node ); 744 componentList.add( expression ); 745 break; 746 } 747 default: 748 throw new XMLParsingException( "Elements of type 'ParameterValueType' may only " 749 + "consist of CDATA and 'ogc:Expression'-elements!" ); 750 } 751 } 752 753 Object[] components = componentList.toArray( new Object[componentList.size()] ); 754 return new ParameterValueType( components ); 755 } 756 757 /** 758 * Creates a <tt>NamedStyle</tt>-instance according to the contents of the DOM-subtree starting at the given 759 * 'NamedStyle'-<tt>Element</tt>. 760 * <p> 761 * 762 * @param element 763 * the 'NamedStyle'-<tt>Element</tt> 764 * @throws XMLParsingException 765 * if a syntactic or semantic error in the DOM-subtree is encountered 766 * @return the constructed <tt>NamedStyle</tt>-instance 767 */ 768 private static NamedStyle createNamedStyle( Element element ) 769 throws XMLParsingException { 770 // required: <Name> 771 String name = XMLTools.getRequiredStringValue( "Name", CommonNamespaces.SLDNS, element ); 772 773 return new NamedStyle( name ); 774 } 775 776 /** 777 * 778 */ 779 public static NamedStyle createNamedStyle( String name ) { 780 return new NamedStyle( name ); 781 } 782 783 /** 784 * Creates a <tt>RemoteOWS</tt>-instance according to the contents of the DOM-subtree starting at the given 785 * 'RemoteOWS'-<tt>Element</tt>. 786 * <p> 787 * 788 * @param element 789 * the 'RemoteOWS'-<tt>Element</tt> 790 * @throws XMLParsingException 791 * if a syntactic or semantic error in the DOM-subtree is encountered 792 * @return the constructed <tt>RemoteOWS</tt>-instance 793 */ 794 private static RemoteOWS createRemoteOWS( Element element ) 795 throws XMLParsingException { 796 // required: <Service> 797 String service = XMLTools.getRequiredStringValue( "Service", CommonNamespaces.SLDNS, element ); 798 799 if ( !( service.equals( "WFS" ) || service.equals( "WCS" ) ) ) { 800 throw new XMLParsingException( "Value ('" + service + "') of element 'service' is invalid. " 801 + "Allowed values are: 'WFS' and 'WCS'." ); 802 } 803 804 // required: <OnlineResource> 805 Element onlineResourceElement = XMLTools.getRequiredChildElement( "OnlineResource", CommonNamespaces.SLDNS, 806 element ); 807 String href = XMLTools.getRequiredAttrValue( "xlink:href", null, onlineResourceElement ); 808 URL url = null; 809 810 try { 811 url = new URL( href ); 812 } catch ( MalformedURLException e ) { 813 LOG.logDebug( e.getMessage(), e ); 814 throw new XMLParsingException( "Value ('" + href + "') of attribute 'href' of " 815 + "element 'OnlineResoure' does not denote a valid URL" ); 816 } 817 818 return new RemoteOWS( service, url ); 819 } 820 821 /** 822 * Creates a <tt>NamedLayer</tt>-instance according to the contents of the DOM-subtree starting at the given 823 * 'UserLayer'-<tt>Element</tt>. 824 * <p> 825 * 826 * @param element 827 * the 'NamedLayer'-<tt>Element</tt> 828 * @throws XMLParsingException 829 * if a syntactic or semantic error in the DOM-subtree is encountered 830 * @return the constructed <tt>NamedLayer</tt>-instance 831 */ 832 private static NamedLayer createNamedLayer( Element element ) 833 throws XMLParsingException { 834 // required: <Name> 835 String name = XMLTools.getRequiredStringValue( "Name", CommonNamespaces.SLDNS, element ); 836 837 // optional: <LayerFeatureConstraints> 838 LayerFeatureConstraints lfc = null; 839 Element lfcElement = XMLTools.getChildElement( "LayerFeatureConstraints", CommonNamespaces.SLDNS, element ); 840 841 if ( lfcElement != null ) { 842 lfc = createLayerFeatureConstraints( lfcElement ); 843 } 844 845 // optional: <NamedStyle>(s) / <UserStyle>(s) 846 NodeList nodelist = element.getChildNodes(); 847 ArrayList<AbstractStyle> styleList = new ArrayList<AbstractStyle>(); 848 849 for ( int i = 0; i < nodelist.getLength(); i++ ) { 850 if ( nodelist.item( i ) instanceof Element ) { 851 Element child = (Element) nodelist.item( i ); 852 String namespace = child.getNamespaceURI(); 853 854 if ( !CommonNamespaces.SLDNS.toASCIIString().equals( namespace ) ) { 855 continue; 856 } 857 858 String childName = child.getLocalName(); 859 860 if ( childName.equals( "NamedStyle" ) ) { 861 styleList.add( createNamedStyle( child ) ); 862 } else if ( childName.equals( "UserStyle" ) ) { 863 styleList.add( createUserStyle( child ) ); 864 } 865 } 866 } 867 868 AbstractStyle[] styles = styleList.toArray( new AbstractStyle[styleList.size()] ); 869 870 return new NamedLayer( name, lfc, styles ); 871 } 872 873 /** 874 * 875 */ 876 public static NamedLayer createNamedLayer( String name, LayerFeatureConstraints layerFeatureConstraints, 877 AbstractStyle[] styles ) { 878 return new NamedLayer( name, layerFeatureConstraints, styles ); 879 } 880 881 /** 882 * Creates a <tt>UserLayer</tt>-instance according to the contents of the DOM-subtree starting at the given 883 * 'UserLayer'-<tt>Element</tt>. 884 * <p> 885 * 886 * @param element 887 * the 'UserLayer'-<tt>Element</tt> 888 * @throws XMLParsingException 889 * if a syntactic or semantic error in the DOM-subtree is encountered 890 * @return the constructed <tt>UserLayer</tt>-instance 891 */ 892 private static UserLayer createUserLayer( Element element ) 893 throws XMLParsingException { 894 // optional: <Name> 895 String name = XMLTools.getStringValue( "Name", CommonNamespaces.SLDNS, element, null ); 896 897 // optional: <RemoteOWS> 898 RemoteOWS remoteOWS = null; 899 Element remoteOWSElement = XMLTools.getChildElement( "RemoteOWS", CommonNamespaces.SLDNS, element ); 900 901 if ( remoteOWSElement != null ) { 902 remoteOWS = createRemoteOWS( remoteOWSElement ); 903 } 904 905 // required: <LayerFeatureConstraints> 906 LayerFeatureConstraints lfc = null; 907 Element lfcElement = XMLTools.getRequiredChildElement( "LayerFeatureConstraints", CommonNamespaces.SLDNS, 908 element ); 909 lfc = createLayerFeatureConstraints( lfcElement ); 910 911 // optional: <UserStyle>(s) 912 ElementList nodelist = XMLTools.getChildElements( "UserStyle", CommonNamespaces.SLDNS, element ); 913 UserStyle[] styles = new UserStyle[nodelist.getLength()]; 914 for ( int i = 0; i < nodelist.getLength(); i++ ) { 915 styles[i] = createUserStyle( nodelist.item( i ) ); 916 } 917 918 return new UserLayer( name, lfc, styles, remoteOWS ); 919 } 920 921 /** 922 * Creates a <tt>FeatureTypeConstraint</tt>-instance according to the contents of the DOM-subtree starting at the 923 * given 'FeatureTypeConstraint'-<tt>Element</tt>. 924 * <p> 925 * 926 * @param element 927 * the 'FeatureTypeConstraint'-<tt>Element</tt> 928 * @throws XMLParsingException 929 * if a syntactic or semantic error in the DOM-subtree is encountered 930 * @return the constructed <tt>FeatureTypeConstraint</tt>-instance 931 */ 932 private static FeatureTypeConstraint createFeatureTypeConstraint( Element element ) 933 throws XMLParsingException { 934 // optional: <Name> 935 Node node = XMLTools.getNode( element, "sld:FeatureTypeName/text()", CommonNamespaces.getNamespaceContext() ); 936 937 QualifiedName name; 938 if ( node == null ) { 939 name = null; 940 } else { 941 name = XMLTools.getQualifiedNameValue( node ); 942 } 943 944 // optional: <Filter> 945 Filter filter = null; 946 Element filterElement = XMLTools.getChildElement( "Filter", ogcNS, element ); 947 948 if ( filterElement != null ) { 949 filter = AbstractFilter.buildFromDOM( filterElement ); 950 } 951 952 // optional: <Extent>(s) 953 ElementList nodelist = XMLTools.getChildElements( "Extent", CommonNamespaces.SLDNS, element ); 954 Extent[] extents = new Extent[nodelist.getLength()]; 955 956 for ( int i = 0; i < nodelist.getLength(); i++ ) { 957 extents[i] = createExtent( nodelist.item( i ) ); 958 } 959 960 return new FeatureTypeConstraint( name, filter, extents ); 961 } 962 963 /** 964 * Creates an <tt>Extent</tt>-instance according to the contents of the DOM-subtree starting at the given 'Extent'- 965 * <tt>Element</tt>. 966 * <p> 967 * 968 * @param element 969 * the 'Extent'-<tt>Element</tt> 970 * @throws XMLParsingException 971 * if a syntactic or semantic error in the DOM-subtree is encountered 972 * @return the constructed <tt>Extent</tt>-instance 973 */ 974 private static Extent createExtent( Element element ) 975 throws XMLParsingException { 976 // required: <Name> 977 String name = XMLTools.getRequiredStringValue( "Name", CommonNamespaces.SLDNS, element ); 978 // required: <Value> 979 String value = XMLTools.getRequiredStringValue( "Value", CommonNamespaces.SLDNS, element ); 980 981 return new Extent( name, value ); 982 } 983 984 /** 985 * Creates a <tt>LayerFeatureConstraints</tt>-instance according to the contents of the DOM-subtree starting at the 986 * given 'LayerFeatureConstraints'-<tt>Element</tt>. 987 * <p> 988 * 989 * @param element 990 * the 'LayerFeatureConstraints'-<tt>Element</tt> 991 * @throws XMLParsingException 992 * if a syntactic or semantic error in the DOM-subtree is encountered 993 * @return the constructed <tt>LayerFeatureConstraints</tt>-instance 994 */ 995 public static LayerFeatureConstraints createLayerFeatureConstraints( Element element ) 996 throws XMLParsingException { 997 // required: <FeatureTypeConstraint>(s) 998 ElementList nodelist = XMLTools.getChildElements( "FeatureTypeConstraint", CommonNamespaces.SLDNS, element ); 999 FeatureTypeConstraint[] ftcs = new FeatureTypeConstraint[nodelist.getLength()]; 1000 1001 for ( int i = 0; i < nodelist.getLength(); i++ ) { 1002 ftcs[i] = createFeatureTypeConstraint( nodelist.item( i ) ); 1003 } 1004 1005 return new LayerFeatureConstraints( ftcs ); 1006 } 1007 1008 /** 1009 * Creates a <tt>UserStyle</tt>-instance according to the contents of the DOM-subtree starting at the given 1010 * 'UserStyle'-<tt>Element</tt>. 1011 * <p> 1012 * 1013 * @param element 1014 * the 'UserStyle'-<tt>Element</tt> 1015 * @throws XMLParsingException 1016 * if a syntactic or semantic error in the DOM-subtree is encountered 1017 * @return the constructed <tt>UserStyle</tt>-instance 1018 */ 1019 public static UserStyle createUserStyle( Element element ) 1020 throws XMLParsingException { 1021 // optional: <Name> 1022 String name = XMLTools.getStringValue( "Name", CommonNamespaces.SLDNS, element, null ); 1023 // optional: <Title> 1024 String title = XMLTools.getStringValue( "Title", CommonNamespaces.SLDNS, element, null ); 1025 // optional: <Abstract> 1026 String abstract_ = XMLTools.getStringValue( "Abstract", CommonNamespaces.SLDNS, element, null ); 1027 1028 // optional: <IsDefault> 1029 String defaultString = XMLTools.getStringValue( "IsDefault", CommonNamespaces.SLDNS, element, null ); 1030 boolean isDefault = false; 1031 1032 if ( defaultString != null ) { 1033 if ( defaultString.equals( "1" ) ) { 1034 isDefault = true; 1035 } 1036 } 1037 1038 // required: <FeatureTypeStyle> (s) 1039 ElementList nl = XMLTools.getChildElements( "FeatureTypeStyle", CommonNamespaces.SLDNS, element ); 1040 FeatureTypeStyle[] styles = new FeatureTypeStyle[nl.getLength()]; 1041 1042 if ( styles.length == 0 ) { 1043 throw new XMLParsingException( "Required child-element 'FeatureTypeStyle' of element " 1044 + "'UserStyle' is missing!" ); 1045 } 1046 1047 for ( int i = 0; i < nl.getLength(); i++ ) { 1048 styles[i] = createFeatureTypeStyle( nl.item( i ) ); 1049 } 1050 1051 return new UserStyle( name, title, abstract_, isDefault, styles ); 1052 } 1053 1054 /** 1055 * Creates a <tt>FeatureTypeStyle</tt>-instance according to the contents of the DOM-subtree starting at the given 1056 * 'FeatureTypeStyle'-<tt>Element</tt>. 1057 * <p> 1058 * TODO: The ElseFilter currently does not work correctly with FeatureFilters. 1059 * <p> 1060 * 1061 * @param element 1062 * the 'FeatureTypeStyle'-<tt>Element</tt> 1063 * @throws XMLParsingException 1064 * if a syntactic or semantic error in the DOM-subtree is encountered 1065 * @return the constructed <tt>FeatureTypeStyle</tt>-instance 1066 */ 1067 public static FeatureTypeStyle createFeatureTypeStyle( Element element ) 1068 throws XMLParsingException { 1069 // optional: <Name> 1070 String name = XMLTools.getStringValue( "Name", CommonNamespaces.SLDNS, element, null ); 1071 // optional: <Title> 1072 String title = XMLTools.getStringValue( "Title", CommonNamespaces.SLDNS, element, null ); 1073 // optional: <Abstract> 1074 String abstract_ = XMLTools.getStringValue( "Abstract", CommonNamespaces.SLDNS, element, null ); 1075 // optional: <FeatureTypeName> 1076 String featureTypeName = XMLTools.getStringValue( "FeatureTypeName", CommonNamespaces.SLDNS, element, null ); 1077 1078 // optional: several <Rule> / <SemanticTypeIdentifier> 1079 NodeList nodelist = element.getChildNodes(); 1080 ArrayList<Rule> ruleList = new ArrayList<Rule>(); 1081 ArrayList<String> typeIdentifierList = new ArrayList<String>(); 1082 1083 // collect Filters of all Rules 1084 ArrayList<Filter> filters = new ArrayList<Filter>(); 1085 // collect all Rules that have an ElseFilter 1086 ArrayList<Rule> elseRules = new ArrayList<Rule>(); 1087 1088 for ( int i = 0; i < nodelist.getLength(); i++ ) { 1089 if ( nodelist.item( i ) instanceof Element ) { 1090 Element child = (Element) nodelist.item( i ); 1091 String namespace = child.getNamespaceURI(); 1092 if ( !CommonNamespaces.SLDNS.toString().equals( namespace ) ) { 1093 continue; 1094 } 1095 1096 String childName = child.getLocalName(); 1097 1098 if ( childName.equals( "Rule" ) ) { 1099 Rule rule = createRule( child ); 1100 if ( rule.hasElseFilter() ) { 1101 elseRules.add( rule ); 1102 } else if ( rule.getFilter() == null || rule.getFilter() instanceof ComplexFilter ) { 1103 filters.add( rule.getFilter() ); 1104 } 1105 ruleList.add( rule ); 1106 } else if ( childName.equals( "SemanticTypeIdentifier" ) ) { 1107 typeIdentifierList.add( XMLTools.getStringValue( child ) ); 1108 } 1109 } 1110 } 1111 1112 // compute and set the ElseFilter for all ElseFilter-Rules 1113 Filter elseFilter = null; 1114 // a Rule exists with no Filter at all -> elseFilter = false 1115 if ( filters.contains( null ) ) { 1116 elseFilter = new FalseFilter(); 1117 // one Rule with a Filter exists -> elseFilter = NOT Filter 1118 } else if ( filters.size() == 1 ) { 1119 elseFilter = new ComplexFilter( OperationDefines.NOT ); 1120 List<Operation> arguments = ( (LogicalOperation) ( (ComplexFilter) elseFilter ).getOperation() ).getArguments(); 1121 ComplexFilter complexFilter = (ComplexFilter) filters.get( 0 ); 1122 arguments.add( complexFilter.getOperation() ); 1123 // several Rules with Filters exist -> elseFilter = NOT (Filter1 OR Filter2 OR...) 1124 } else if ( filters.size() > 1 ) { 1125 ComplexFilter innerFilter = new ComplexFilter( OperationDefines.OR ); 1126 elseFilter = new ComplexFilter( innerFilter, null, OperationDefines.NOT ); 1127 List<Operation> arguments = ( (LogicalOperation) innerFilter.getOperation() ).getArguments(); 1128 Iterator<Filter> it = filters.iterator(); 1129 while ( it.hasNext() ) { 1130 ComplexFilter complexFilter = (ComplexFilter) it.next(); 1131 arguments.add( complexFilter.getOperation() ); 1132 } 1133 } 1134 Iterator<Rule> it = elseRules.iterator(); 1135 while ( it.hasNext() ) { 1136 it.next().setFilter( elseFilter ); 1137 } 1138 1139 Rule[] rules = ruleList.toArray( new Rule[ruleList.size()] ); 1140 String[] typeIdentifiers = typeIdentifierList.toArray( new String[typeIdentifierList.size()] ); 1141 1142 return new FeatureTypeStyle( name, title, abstract_, featureTypeName, typeIdentifiers, rules ); 1143 } 1144 1145 /** 1146 * Creates a <tt>Rule</tt>-instance according to the contents of the DOM-subtree starting at the given 'Rule'- 1147 * <tt>Element</tt>. 1148 * <p> 1149 * 1150 * @param element 1151 * the 'Rule'-<tt>Element</tt> 1152 * @throws XMLParsingException 1153 * if a syntactic or semantic error in the DOM-subtree is encountered 1154 * @return the constructed <tt>Rule</tt>-instance 1155 */ 1156 private static Rule createRule( Element element ) 1157 throws XMLParsingException { 1158 // optional: <Name> 1159 String name = XMLTools.getStringValue( "Name", CommonNamespaces.SLDNS, element, null ); 1160 // optional: <Title> 1161 String title = XMLTools.getStringValue( "Title", CommonNamespaces.SLDNS, element, null ); 1162 // optional: <Abstract> 1163 String abstract_ = XMLTools.getStringValue( "Abstract", CommonNamespaces.SLDNS, element, null ); 1164 1165 // optional: <LegendGraphic> 1166 LegendGraphic legendGraphic = null; 1167 Element legendGraphicElement = XMLTools.getChildElement( "LegendGraphic", CommonNamespaces.SLDNS, element ); 1168 1169 if ( legendGraphicElement != null ) { 1170 legendGraphic = createLegendGraphic( legendGraphicElement ); 1171 } 1172 1173 // optional: <Filter> 1174 boolean isAnElseFilter = false; 1175 Filter filter = null; 1176 Element filterElement = XMLTools.getChildElement( "Filter", ogcNS, element ); 1177 if ( filterElement != null ) { 1178 filter = AbstractFilter.buildFromDOM( filterElement ); 1179 } 1180 1181 // optional: <ElseFilter> 1182 Element elseFilterElement = XMLTools.getChildElement( "ElseFilter", CommonNamespaces.SLDNS, element ); 1183 if ( elseFilterElement != null ) { 1184 isAnElseFilter = true; 1185 } 1186 1187 if ( ( filterElement != null ) && ( elseFilterElement != null ) ) { 1188 throw new XMLParsingException( "Element 'Rule' may contain a 'Filter'- or " 1189 + "an 'ElseFilter'-element, but not both!" ); 1190 } 1191 1192 // optional: <MinScaleDenominator> 1193 double min = XMLTools.getNodeAsDouble( element, "sld:MinScaleDenominator", nsContext, 0.0 ); 1194 // optional: <MaxScaleDenominator> 1195 double max = XMLTools.getNodeAsDouble( element, "sld:MaxScaleDenominator", nsContext, 9E99 ); 1196 1197 // optional: different Symbolizer-elements 1198 NodeList symbolizerNL = element.getChildNodes(); 1199 ArrayList<Symbolizer> symbolizerList = new ArrayList<Symbolizer>( symbolizerNL.getLength() ); 1200 1201 for ( int i = 0; i < symbolizerNL.getLength(); i++ ) { 1202 if ( symbolizerNL.item( i ) instanceof Element ) { 1203 Element symbolizerElement = (Element) symbolizerNL.item( i ); 1204 String namespace = symbolizerElement.getNamespaceURI(); 1205 1206 if ( !CommonNamespaces.SLDNS.toString().equals( namespace ) 1207 && !CommonNamespaces.SENS.toString().equals( namespace ) ) { 1208 continue; 1209 } 1210 1211 String symbolizerName = symbolizerElement.getLocalName(); 1212 1213 if ( symbolizerName.equals( "LineSymbolizer" ) ) { 1214 symbolizerList.add( createLineSymbolizer( symbolizerElement, min, max ) ); 1215 } else if ( symbolizerName.equals( "PointSymbolizer" ) ) { 1216 symbolizerList.add( createPointSymbolizer( symbolizerElement, min, max ) ); 1217 } else if ( symbolizerName.equals( "PolygonSymbolizer" ) ) { 1218 symbolizerList.add( createPolygonSymbolizer( symbolizerElement, min, max ) ); 1219 } else if ( symbolizerName.equals( "TextSymbolizer" ) ) { 1220 symbolizerList.add( createTextSymbolizer( symbolizerElement, min, max ) ); 1221 } else if ( symbolizerName.equals( "RasterSymbolizer" ) ) { 1222 symbolizerList.add( createRasterSymbolizer( symbolizerElement, min, max ) ); 1223 } 1224 } 1225 } 1226 1227 Symbolizer[] symbolizers = symbolizerList.toArray( new Symbolizer[symbolizerList.size()] ); 1228 1229 return new Rule( symbolizers, name, title, abstract_, legendGraphic, filter, isAnElseFilter, min, max ); 1230 } 1231 1232 /** 1233 * 1234 * @param symbolizerElement 1235 * @return {@link Symbolizer} 1236 * @throws XMLParsingException 1237 */ 1238 public static Symbolizer createSymbolizer( Element symbolizerElement ) 1239 throws XMLParsingException { 1240 String symbolizerName = symbolizerElement.getLocalName(); 1241 1242 double min = 0; 1243 double max = Double.MAX_VALUE; 1244 Symbolizer symbolizer = null; 1245 if ( symbolizerName.equals( "LineSymbolizer" ) ) { 1246 symbolizer = createLineSymbolizer( symbolizerElement, min, max ); 1247 } else if ( symbolizerName.equals( "PointSymbolizer" ) ) { 1248 symbolizer = createPointSymbolizer( symbolizerElement, min, max ); 1249 } else if ( symbolizerName.equals( "PolygonSymbolizer" ) ) { 1250 symbolizer = createPolygonSymbolizer( symbolizerElement, min, max ); 1251 } else if ( symbolizerName.equals( "TextSymbolizer" ) ) { 1252 symbolizer = createTextSymbolizer( symbolizerElement, min, max ); 1253 } else if ( symbolizerName.equals( "RasterSymbolizer" ) ) { 1254 symbolizer = createRasterSymbolizer( symbolizerElement, min, max ); 1255 } 1256 return symbolizer; 1257 } 1258 1259 /** 1260 * Creates a <tt>PointSymbolizer</tt>-instance according to the contents of the DOM-subtree starting at the given 1261 * 'PointSymbolizer'-<tt>Element</tt>. 1262 * <p> 1263 * 1264 * @param element 1265 * the 'PointSymbolizer'-<tt>Element</tt> 1266 * @param min 1267 * scale-constraint to be used 1268 * @param max 1269 * scale-constraint to be used 1270 * @throws XMLParsingException 1271 * if a syntactic or semantic error in the DOM-subtree is encountered 1272 * @return the constructed <tt>PointSymbolizer</tt>-instance 1273 */ 1274 private static PointSymbolizer createPointSymbolizer( Element element, double min, double max ) 1275 throws XMLParsingException { 1276 1277 // optional: <Geometry> 1278 Geometry geometry = null; 1279 Element geometryElement = XMLTools.getChildElement( "Geometry", CommonNamespaces.SLDNS, element ); 1280 1281 if ( geometryElement != null ) { 1282 geometry = createGeometry( geometryElement ); 1283 } 1284 1285 // optional: <Graphic> 1286 Graphic graphic = null; 1287 Element graphicElement = XMLTools.getChildElement( "Graphic", CommonNamespaces.SLDNS, element ); 1288 1289 if ( graphicElement != null ) { 1290 graphic = createGraphic( graphicElement ); 1291 } 1292 1293 PointSymbolizer ps = null; 1294 String respClass = XMLTools.getAttrValue( element, null, "responsibleClass", null ); 1295 if ( respClass == null ) { 1296 ps = new PointSymbolizer( graphic, geometry, min, max ); 1297 } else { 1298 ps = new PointSymbolizer( graphic, geometry, respClass, min, max ); 1299 } 1300 1301 return ps; 1302 } 1303 1304 /** 1305 * Creates a <tt>LineSymbolizer</tt>-instance according to the contents of the DOM-subtree starting at the given 1306 * 'LineSymbolizer'-<tt>Element</tt>. 1307 * <p> 1308 * 1309 * @param element 1310 * the 'LineSymbolizer'-<tt>Element</tt> 1311 * @param min 1312 * scale-constraint to be used 1313 * @param max 1314 * scale-constraint to be used 1315 * @throws XMLParsingException 1316 * if a syntactic or semantic error in the DOM-subtree is encountered 1317 * @return the constructed <tt>LineSymbolizer</tt>-instance 1318 */ 1319 private static LineSymbolizer createLineSymbolizer( Element element, double min, double max ) 1320 throws XMLParsingException { 1321 1322 // optional: <Geometry> 1323 Geometry geometry = null; 1324 Element geometryElement = XMLTools.getChildElement( "Geometry", CommonNamespaces.SLDNS, element ); 1325 1326 if ( geometryElement != null ) { 1327 geometry = createGeometry( geometryElement ); 1328 } 1329 1330 // optional: <Stroke> 1331 Stroke stroke = null; 1332 Element strokeElement = XMLTools.getChildElement( "Stroke", CommonNamespaces.SLDNS, element ); 1333 1334 if ( strokeElement != null ) { 1335 stroke = createStroke( strokeElement ); 1336 } 1337 1338 LineSymbolizer ls = null; 1339 String respClass = XMLTools.getAttrValue( element, null, "responsibleClass", null ); 1340 if ( respClass == null ) { 1341 ls = new LineSymbolizer( stroke, geometry, min, max ); 1342 } else { 1343 ls = new LineSymbolizer( stroke, geometry, respClass, min, max ); 1344 } 1345 return ls; 1346 } 1347 1348 /** 1349 * Creates a <tt>PolygonSymbolizer</tt>-instance according to the contents of the DOM-subtree starting at the given 1350 * 'PolygonSymbolizer'-<tt>Element</tt>. 1351 * <p> 1352 * 1353 * @param element 1354 * the 'PolygonSymbolizer'-<tt>Element</tt> 1355 * @param min 1356 * scale-constraint to be used 1357 * @param max 1358 * scale-constraint to be used 1359 * @throws XMLParsingException 1360 * if a syntactic or semantic error in the DOM-subtree is encountered 1361 * @return the constructed <tt>PolygonSymbolizer</tt>-instance 1362 */ 1363 private static PolygonSymbolizer createPolygonSymbolizer( Element element, double min, double max ) 1364 throws XMLParsingException { 1365 // optional: <Geometry> 1366 Geometry geometry = null; 1367 Element geometryElement = XMLTools.getChildElement( "Geometry", CommonNamespaces.SLDNS, element ); 1368 1369 if ( geometryElement != null ) { 1370 geometry = createGeometry( geometryElement ); 1371 } 1372 1373 // optional: <Fill> 1374 Fill fill = null; 1375 Element fillElement = XMLTools.getChildElement( "Fill", CommonNamespaces.SLDNS, element ); 1376 1377 if ( fillElement != null ) { 1378 fill = createFill( fillElement ); 1379 } 1380 1381 // optional: <Stroke> 1382 Stroke stroke = null; 1383 Element strokeElement = XMLTools.getChildElement( "Stroke", CommonNamespaces.SLDNS, element ); 1384 1385 if ( strokeElement != null ) { 1386 stroke = createStroke( strokeElement ); 1387 } 1388 1389 PolygonSymbolizer ps = null; 1390 String respClass = XMLTools.getAttrValue( element, null, "responsibleClass", null ); 1391 if ( respClass == null ) { 1392 ps = new PolygonSymbolizer( fill, stroke, geometry, min, max ); 1393 } else { 1394 ps = new PolygonSymbolizer( fill, stroke, geometry, respClass, min, max ); 1395 } 1396 1397 return ps; 1398 } 1399 1400 /** 1401 * Creates a <tt>Geometry</tt>-instance according to the contents of the DOM-subtree starting at the given 1402 * 'Geometry'-<tt>Element</tt>. 1403 * 1404 * @param element 1405 * the 'Geometry'-<tt>Element</tt> 1406 * @throws XMLParsingException 1407 * if a syntactic or semantic error in the DOM-subtree is encountered 1408 * @return the constructed <tt>Geometry</tt>-instance 1409 */ 1410 private static Geometry createGeometry( Element element ) 1411 throws XMLParsingException { 1412 Geometry geometry = null; 1413 1414 // required: <PropertyName> 1415 Element propertyNameElement = XMLTools.getRequiredChildElement( "PropertyName", ogcNS, element ); 1416 1417 // optional: <Function> 1418 Element functionElement = XMLTools.getChildElement( "Function", ogcNS, propertyNameElement ); 1419 1420 // just a property name exists 1421 if ( functionElement == null ) { 1422 Node node = XMLTools.getNode( propertyNameElement, "/text()", nsContext ); 1423 PropertyPath pp = OGCDocument.parsePropertyPath( (Text) node ); 1424 geometry = new Geometry( pp, null ); 1425 } else { 1426 // expressions are not supported 1427 } 1428 1429 return geometry; 1430 } 1431 1432 /** 1433 * Creates a <tt>Fill</tt>-instance according to the contents of the DOM-subtree starting at the given 'Fill'- 1434 * <tt>Element</tt>. 1435 * <p> 1436 * 1437 * @param element 1438 * the 'Fill'-<tt>Element</tt> 1439 * @throws XMLParsingException 1440 * if a syntactic or semantic error in the DOM-subtree is encountered 1441 * @return the constructed <tt>Fill</tt>-instance 1442 */ 1443 private static Fill createFill( Element element ) 1444 throws XMLParsingException { 1445 // optional: <GraphicFill> 1446 GraphicFill graphicFill = null; 1447 Element graphicFillElement = XMLTools.getChildElement( "GraphicFill", CommonNamespaces.SLDNS, element ); 1448 1449 if ( graphicFillElement != null ) { 1450 graphicFill = createGraphicFill( graphicFillElement ); 1451 } 1452 1453 // optional: <CssParameter>s 1454 ElementList nl = XMLTools.getChildElements( "CssParameter", CommonNamespaces.SLDNS, element ); 1455 HashMap<String, Object> cssParams = new HashMap<String, Object>( nl.getLength() ); 1456 1457 for ( int i = 0; i < nl.getLength(); i++ ) { 1458 CssParameter cssParam = createCssParameter( nl.item( i ) ); 1459 cssParams.put( cssParam.getName(), cssParam ); 1460 } 1461 1462 return new Fill( cssParams, graphicFill ); 1463 } 1464 1465 /** 1466 * Creates a <tt>LegendGraphic</tt>-instance according to the contents of the DOM-subtree starting at the given 1467 * 'LegendGraphic'-element. 1468 * <p> 1469 * 1470 * @param element 1471 * the 'LegendGraphic'-<tt>Element</tt> 1472 * @throws XMLParsingException 1473 * if a syntactic or semantic error in the DOM-subtree is encountered 1474 * @return the constructed <tt>Graphic</tt>-instance 1475 */ 1476 private static LegendGraphic createLegendGraphic( Element element ) 1477 throws XMLParsingException { 1478 // required: <Graphic> 1479 Element graphicElement = XMLTools.getRequiredChildElement( "Graphic", CommonNamespaces.SLDNS, element ); 1480 Graphic graphic = createGraphic( graphicElement ); 1481 1482 return new LegendGraphic( graphic ); 1483 } 1484 1485 /** 1486 * Creates an <tt>ExternalGraphic</tt>-instance according to the contents of the DOM-subtree starting at the given 1487 * 'ExternalGraphic'-<tt>Element</tt>. 1488 * <p> 1489 * 1490 * @param element 1491 * the 'ExternalGraphic'-<tt>Element</tt> 1492 * @throws XMLParsingException 1493 * if a syntactic or semantic error in the DOM-subtree is encountered 1494 * @return the constructed <tt>ExternalGraphic</tt>-instance 1495 */ 1496 private static ExternalGraphic createExternalGraphic( Element element ) 1497 throws XMLParsingException { 1498 // required: <OnlineResource> 1499 Element onlineResourceElement = XMLTools.getRequiredChildElement( "OnlineResource", CommonNamespaces.SLDNS, 1500 element ); 1501 1502 // required: href-Attribute (in <OnlineResource>) 1503 String href = XMLTools.getRequiredAttrValue( "href", xlnNS, onlineResourceElement ); 1504 URL url = null; 1505 try { 1506 url = sldDoc.resolve( href ); 1507 } catch ( MalformedURLException e ) { 1508 LOG.logDebug( e.getMessage(), e ); 1509 throw new XMLParsingException( "Value ('" + href + "') of attribute 'href' of " 1510 + "element 'OnlineResoure' does not denote a valid URL" ); 1511 } 1512 1513 // required: <Format> (in <OnlineResource>) 1514 String format = XMLTools.getRequiredStringValue( "Format", CommonNamespaces.SLDNS, element ); 1515 1516 return new ExternalGraphic( format, url ); 1517 } 1518 1519 /** 1520 * Creates a <tt>Mark</tt>-instance according to the contents of the DOM-subtree starting at the given 'Mark'- 1521 * <tt>Element</tt>. 1522 * <p> 1523 * 1524 * @param element 1525 * the 'Mark'-<tt>Element</tt> 1526 * @throws XMLParsingException 1527 * if a syntactic or semantic error in the DOM-subtree is encountered 1528 * @return the constructed <tt>Mark</tt>-instance 1529 */ 1530 private static Mark createMark( Element element ) 1531 throws XMLParsingException { 1532 Stroke stroke = null; 1533 Fill fill = null; 1534 1535 // optional: <WellKnownName> 1536 String wkn = XMLTools.getStringValue( "WellKnownName", CommonNamespaces.SLDNS, element, null ); 1537 1538 // optional: <Stroke> 1539 Element strokeElement = XMLTools.getChildElement( "Stroke", CommonNamespaces.SLDNS, element ); 1540 1541 if ( strokeElement != null ) { 1542 stroke = createStroke( strokeElement ); 1543 } 1544 1545 // optional: <Fill> 1546 Element fillElement = XMLTools.getChildElement( "Fill", CommonNamespaces.SLDNS, element ); 1547 1548 if ( fillElement != null ) { 1549 fill = createFill( fillElement ); 1550 } 1551 1552 return new Mark( wkn, stroke, fill ); 1553 } 1554 1555 /** 1556 * Creates a <tt>Stroke</tt>-instance according to the contents of the DOM-subtree starting at the given 'Stroke'- 1557 * <tt>Element</tt>. 1558 * <p> 1559 * 1560 * @param element 1561 * the 'Stroke'-<tt>Element</tt> 1562 * @throws XMLParsingException 1563 * if a syntactic or semantic error in the DOM-subtree is encountered 1564 * @return the constructed <tt>Stroke</tt>-instance 1565 */ 1566 private static Stroke createStroke( Element element ) 1567 throws XMLParsingException { 1568 GraphicFill gf = null; 1569 GraphicStroke gs = null; 1570 1571 // optional: <GraphicFill> 1572 Element gfElement = XMLTools.getChildElement( "GraphicFill", CommonNamespaces.SLDNS, element ); 1573 1574 if ( gfElement != null ) { 1575 gf = createGraphicFill( gfElement ); 1576 } 1577 1578 // optional: <GraphicStroke> 1579 Element gsElement = XMLTools.getChildElement( "GraphicStroke", CommonNamespaces.SLDNS, element ); 1580 1581 if ( gsElement != null ) { 1582 gs = createGraphicStroke( gsElement ); 1583 } 1584 1585 // optional: <CssParameter>s 1586 ElementList nl = XMLTools.getChildElements( "CssParameter", CommonNamespaces.SLDNS, element ); 1587 HashMap<String, Object> cssParams = new HashMap<String, Object>( nl.getLength() ); 1588 1589 for ( int i = 0; i < nl.getLength(); i++ ) { 1590 CssParameter cssParam = createCssParameter( nl.item( i ) ); 1591 cssParams.put( cssParam.getName(), cssParam ); 1592 } 1593 1594 return new Stroke( cssParams, gs, gf ); 1595 } 1596 1597 /** 1598 * Creates a <tt>GraphicFill</tt>-instance according to the contents of the DOM-subtree starting at the given 1599 * 'GraphicFill'-<tt>Element</tt>. 1600 * <p> 1601 * 1602 * @param element 1603 * the 'GraphicFill'-<tt>Element</tt> 1604 * @throws XMLParsingException 1605 * if a syntactic or semantic error in the DOM-subtree is encountered 1606 * @return the constructed <tt>GraphicFill</tt>-instance 1607 */ 1608 private static GraphicFill createGraphicFill( Element element ) 1609 throws XMLParsingException { 1610 // required: <Graphic> 1611 Element graphicElement = XMLTools.getRequiredChildElement( "Graphic", CommonNamespaces.SLDNS, element ); 1612 Graphic graphic = createGraphic( graphicElement ); 1613 1614 return new GraphicFill( graphic ); 1615 } 1616 1617 /** 1618 * Creates a <tt>GraphicStroke</tt>-instance according to the contents of the DOM-subtree starting at the given 1619 * 'GraphicStroke'-<tt>Element</tt>. 1620 * <p> 1621 * 1622 * @param element 1623 * the 'GraphicStroke'-<tt>Element</tt> 1624 * @throws XMLParsingException 1625 * if a syntactic or semantic error in the DOM-subtree is encountered 1626 * @return the constructed <tt>GraphicStroke</tt>-instance 1627 */ 1628 private static GraphicStroke createGraphicStroke( Element element ) 1629 throws XMLParsingException { 1630 // required: <Graphic> 1631 Element graphicElement = XMLTools.getRequiredChildElement( "Graphic", CommonNamespaces.SLDNS, element ); 1632 Graphic graphic = createGraphic( graphicElement ); 1633 1634 return new GraphicStroke( graphic ); 1635 } 1636 1637 /** 1638 * Creates a <tt>Graphic</tt>-instance according to the contents of the DOM-subtree starting at the given 1639 * 'Graphic'-element. 1640 * <p> 1641 * 1642 * @param element 1643 * the 'Graphic'-<tt>Element</tt> 1644 * @throws XMLParsingException 1645 * if a syntactic or semantic error in the DOM-subtree is encountered 1646 * @return the constructed <tt>Graphic</tt>-instance 1647 */ 1648 private static Graphic createGraphic( Element element ) 1649 throws XMLParsingException { 1650 1651 // optional: <Opacity> 1652 ParameterValueType opacity = null; 1653 // optional: <Size> 1654 ParameterValueType size = null; 1655 // optional: <Rotation> 1656 ParameterValueType rotation = null; 1657 // optional: <Displacement> 1658 ParameterValueType[] displacement = null; 1659 1660 // optional: <ExternalGraphic>s / <Mark>s 1661 NodeList nodelist = element.getChildNodes(); 1662 ArrayList<Object> marksAndExtGraphicsList = new ArrayList<Object>(); 1663 1664 for ( int i = 0; i < nodelist.getLength(); i++ ) { 1665 if ( nodelist.item( i ) instanceof Element ) { 1666 Element child = (Element) nodelist.item( i ); 1667 String namespace = child.getNamespaceURI(); 1668 1669 if ( !CommonNamespaces.SLDNS.toString().equals( namespace ) ) { 1670 continue; 1671 } 1672 1673 String childName = child.getLocalName(); 1674 1675 if ( childName.equals( "ExternalGraphic" ) ) { 1676 marksAndExtGraphicsList.add( createExternalGraphic( child ) ); 1677 } else if ( childName.equals( "Mark" ) ) { 1678 marksAndExtGraphicsList.add( createMark( child ) ); 1679 } else if ( childName.equals( "Opacity" ) ) { 1680 opacity = createParameterValueType( child ); 1681 } else if ( childName.equals( "Size" ) ) { 1682 size = createParameterValueType( child ); 1683 } else if ( childName.equals( "Rotation" ) ) { 1684 rotation = createParameterValueType( child ); 1685 } else if ( childName.equals( "Displacement" ) ) { 1686 displacement = new ParameterValueType[2]; 1687 Element dXElement = XMLTools.getRequiredElement( child, "sld:DisplacementX", 1688 CommonNamespaces.getNamespaceContext() ); 1689 Element dYElement = XMLTools.getRequiredElement( child, "sld:DisplacementY", 1690 CommonNamespaces.getNamespaceContext() ); 1691 if ( ( dXElement == null ) || ( dYElement == null ) ) { 1692 throw new XMLParsingException( "Element 'Displacement' must contain exactly one " 1693 + "'DisplacementX'- and one 'DisplacementY'-element!" ); 1694 } 1695 displacement[0] = createParameterValueType( dXElement ); 1696 displacement[1] = createParameterValueType( dYElement ); 1697 } 1698 } 1699 } 1700 1701 Object[] marksAndExtGraphics = marksAndExtGraphicsList.toArray( new Object[marksAndExtGraphicsList.size()] ); 1702 return new Graphic( marksAndExtGraphics, opacity, size, rotation, displacement ); 1703 } 1704 1705 /** 1706 * Creates a <tt>CssParameter</tt>-instance according to the contents of the DOM-subtree starting at the given 1707 * 'CssParameter'-<tt>Element</tt>. 1708 * <p> 1709 * 1710 * @param element 1711 * the 'CssParamter'-<tt>Element</tt> 1712 * @throws XMLParsingException 1713 * if a syntactic or semantic error in the DOM-subtree is encountered 1714 * @return the constructed <tt>CssParameter</tt>-instance 1715 */ 1716 private static CssParameter createCssParameter( Element element ) 1717 throws XMLParsingException { 1718 // required: name-Attribute 1719 String name = XMLTools.getRequiredAttrValue( "name", null, element ); 1720 ParameterValueType pvt = createParameterValueType( element ); 1721 1722 return ( new CssParameter( name, pvt ) ); 1723 } 1724 1725 /** 1726 * <code>TresholdsBelongTo</code> enumerates values possibly belonging to <code>ThreshholdsBelongToType</code>. 1727 * 1728 * @author <a href="mailto:schmitz@lat-lon.de">Andreas Schmitz</a> 1729 * @author last edited by: $Author: apoth $ 1730 * 1731 * @version $Revision: 30390 $, $Date: 2011-04-07 10:21:25 +0200 (Thu, 07 Apr 2011) $ 1732 */ 1733 public enum ThresholdsBelongTo { 1734 /** 1735 * <code>"succeeding"</code> 1736 */ 1737 SUCCEEDING, 1738 /** 1739 * <code>"preceding"</code> 1740 */ 1741 PRECEDING 1742 } 1743 1744 /** 1745 * <code>Mode</code> is the ModeType from the Symbology Encoding Schema. 1746 * 1747 * @author <a href="mailto:schmitz@lat-lon.de">Andreas Schmitz</a> 1748 * @author last edited by: $Author: apoth $ 1749 * 1750 * @version $Revision: 30390 $, $Date: 2011-04-07 10:21:25 +0200 (Thu, 07 Apr 2011) $ 1751 */ 1752 public enum Mode { 1753 /** 1754 * <code>"linear"</code> 1755 */ 1756 LINEAR, 1757 /** 1758 * <code>"cosine"</code> 1759 */ 1760 COSINE, 1761 /** 1762 * <code>"cubic"</code> 1763 */ 1764 CUBIC 1765 } 1766 1767 /** 1768 * <code>Method</code> is the MethodType from the Symbology encoding Schema. 1769 * 1770 * @author <a href="mailto:schmitz@lat-lon.de">Andreas Schmitz</a> 1771 * @author last edited by: $Author: apoth $ 1772 * 1773 * @version $Revision: 30390 $, $Date: 2011-04-07 10:21:25 +0200 (Thu, 07 Apr 2011) $ 1774 */ 1775 public enum Method { 1776 /** 1777 * <code>"numeric"</code> 1778 */ 1779 NUMERIC, 1780 /** 1781 * <code>"color"</code> 1782 */ 1783 COLOR 1784 } 1785 1786 }