001 //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/ogcwebservices/wmps/operation/PrintMap.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.ogcwebservices.wmps.operation; 037 038 import java.awt.Color; 039 import java.io.Serializable; 040 import java.io.UnsupportedEncodingException; 041 import java.net.URLDecoder; 042 import java.sql.Timestamp; 043 import java.util.ArrayList; 044 import java.util.Arrays; 045 import java.util.HashMap; 046 import java.util.List; 047 import java.util.Map; 048 import java.util.StringTokenizer; 049 050 import org.deegree.framework.log.ILogger; 051 import org.deegree.framework.log.LoggerFactory; 052 import org.deegree.framework.util.CharsetUtils; 053 import org.deegree.framework.util.StringTools; 054 import org.deegree.framework.xml.NamespaceContext; 055 import org.deegree.framework.xml.XMLParsingException; 056 import org.deegree.framework.xml.XMLTools; 057 import org.deegree.model.crs.CRSFactory; 058 import org.deegree.model.crs.CoordinateSystem; 059 import org.deegree.model.crs.UnknownCRSException; 060 import org.deegree.model.spatialschema.Envelope; 061 import org.deegree.model.spatialschema.GMLGeometryAdapter; 062 import org.deegree.model.spatialschema.GeometryException; 063 import org.deegree.model.spatialschema.GeometryFactory; 064 import org.deegree.model.spatialschema.Point; 065 import org.deegree.ogcbase.CommonNamespaces; 066 import org.deegree.ogcbase.InvalidGMLException; 067 import org.deegree.ogcwebservices.InconsistentRequestException; 068 import org.deegree.ogcwebservices.wms.InvalidFormatException; 069 import org.deegree.ogcwebservices.wms.operation.GetMap; 070 import org.deegree.ogcwebservices.wms.operation.GetMap.Layer; 071 import org.w3c.dom.Element; 072 import org.w3c.dom.Node; 073 074 /** 075 * This interface describes the access to the parameters of a PrintMap request. It is expected that 076 * there are two kinds of request. The first is the 'normal' HTTP GET request with name-value-pair 077 * enconding and the second is a HTTP POST request containing a SLD. It is possible to access the 078 * values of a HTTP GET request throught its bean accessor methods. The request shall be mapped to a 079 * SLD data structure, accessible using the <code>getSLD()</code> method. 080 * 081 * @author <a href="mailto:deshmukh@lat-lon.de">Anup Deshmukh</a> 082 * @version 2.0 083 */ 084 public class PrintMap extends WMPSRequestBase implements Serializable { 085 086 private static final long serialVersionUID = 6898492018448337645L; 087 088 private static final ILogger LOG = LoggerFactory.getLogger( PrintMap.class ); 089 090 private static final NamespaceContext nsContext = CommonNamespaces.getNamespaceContext(); 091 092 private List<Layer> layers; 093 094 private String srs; 095 096 private Envelope boundingBox; 097 098 private Point center; 099 100 private int scaleDenominator = -1; 101 102 private boolean transparent; 103 104 private Color bgColor; 105 106 private String title; 107 108 private String copyright; 109 110 private boolean legend; 111 112 private boolean scaleBar; 113 114 private String note; 115 116 private String template; 117 118 private String emailaddress; 119 120 private Timestamp timestamp; 121 122 private TextArea[] textAreas; 123 124 /** 125 * Create a new PrintMap instance. 126 * 127 * @param id 128 * @param version 129 * @param layers 130 * @param srs 131 * @param boundingBox 132 * @param center 133 * @param scaleDenominator 134 * @param transparent 135 * @param bgColor 136 * @param title 137 * @param copyright 138 * @param legend 139 * @param scaleBar 140 * @param note 141 * @param template 142 * @param emailaddress 143 * @param timestamp 144 * @param textAreas 145 * @param vendorSpecificParameter 146 */ 147 PrintMap( String id, String version, Layer[] layers, String srs, Envelope boundingBox, Point center, 148 int scaleDenominator, boolean transparent, Color bgColor, String title, String copyright, boolean legend, 149 boolean scaleBar, String note, String template, String emailaddress, Timestamp timestamp, 150 TextArea[] textAreas, Map<String, String> vendorSpecificParameter ) { 151 152 super( version, id, vendorSpecificParameter ); 153 154 setLayers( layers ); 155 this.srs = srs; 156 this.boundingBox = boundingBox; 157 this.center = center; 158 this.scaleDenominator = scaleDenominator; 159 this.transparent = transparent; 160 this.bgColor = bgColor; 161 this.title = title; 162 this.copyright = copyright; 163 this.legend = legend; 164 this.scaleBar = scaleBar; 165 this.note = note; 166 this.template = template; 167 this.emailaddress = emailaddress; 168 setTimestamp( timestamp ); 169 this.textAreas = textAreas; 170 } 171 172 /** 173 * Set the time stamp. 174 * 175 * @param timestamp 176 */ 177 private void setTimestamp( Timestamp timestamp ) { 178 179 if ( timestamp != null ) { 180 this.timestamp = timestamp; 181 } else { 182 this.timestamp = setCurrentTime(); 183 } 184 } 185 186 /** 187 * Sets the Current System Time where the request was recieved. 188 * 189 * @return Date 190 */ 191 private static Timestamp setCurrentTime() { 192 long now = System.currentTimeMillis(); 193 return new Timestamp( now ); 194 } 195 196 /** 197 * The required LAYERS parameter lists the map layer(s) to be returned by this PrintMapRequest 198 * request. The value of the LAYERS parameter is a comma-separated list of one or more valid 199 * layer names. Allowed layer names are the character data content of any <Layer><Name> element 200 * in the Capabilities XML. 201 * <p> 202 * </p> 203 * A WMS shall render the requested layers by drawing the leftmost in the list bottommost, the 204 * next one over that, and so on. 205 * <p> 206 * </p> 207 * Each layer is associated to a style. Styles are also is encoded as a comma- seperated list 208 * within the PrintMapRequest request. 209 * <p> 210 * </p> 211 * The required STYLES parameter lists the style in which each layer is to be rendered. There is 212 * a one-to-one correspondence between the values in the LAYERS parameter and the values in the 213 * STYLES parameter. Because of this layer-style combinations are returned coupled within an 214 * array of Layer- objects. Each map in the list of LAYERS is drawn using the corresponding 215 * style in the same position in the list of STYLES. Each style Name shall be one that was 216 * defined in the <Name> element of a <Style> element that is either directly contained within, 217 * or inherited by, the associated <Layer> element in Capabilities XML. 218 * 219 * @return The required LAYERS 220 */ 221 public Layer[] getLayers() { 222 return this.layers.toArray( new Layer[this.layers.size()] ); 223 } 224 225 /** 226 * adds the <Layer> 227 * 228 * @param layer 229 */ 230 protected void addLayers( Layer layer ) { 231 this.layers.add( layer ); 232 } 233 234 /** 235 * sets the <Layer> 236 * 237 * @param layers 238 * a set of layer 239 */ 240 private void setLayers( Layer[] layers ) { 241 this.layers = new ArrayList<Layer>( layers.length ); 242 this.layers.clear(); 243 if ( layers != null ) { 244 this.layers = Arrays.asList( layers ); 245 } 246 } 247 248 /** 249 * creates a <tt>PrintMapRequest</tt> from its XML representation as defined in the 250 * specification. 251 * 252 * @param root 253 * Element 254 * @return an instance of <tt>PrintMapRequest</tt> 255 * @throws InconsistentRequestException 256 * @throws XMLParsingException 257 */ 258 public static PrintMap create( Element root ) 259 throws InconsistentRequestException, XMLParsingException { 260 261 LOG.logInfo( "Validating PrintMapRequest request." ); 262 // Validation 263 if ( !root.getLocalName().equals( "PrintMap" ) ) { 264 StringBuffer sb = new StringBuffer( 50 ); 265 sb.append( "Unable to create a 'PrintMapRequest' operation for node '" ); 266 sb.append( root.getLocalName() + "'. Please check the node to be parsed." ); 267 throw new InconsistentRequestException( sb.toString() ); 268 } 269 // VERSION 270 String version; 271 try { 272 version = XMLTools.getRequiredAttrValue( "version", null, root ); 273 } catch ( XMLParsingException e ) { 274 throw new XMLParsingException( "Error parsing required attribute parameter 'Version'. " + e.getMessage() ); 275 } 276 277 // LAYERS & STYLES 278 List<Layer> layerList = new ArrayList<Layer>(); 279 List layerElements = null; 280 try { 281 layerElements = XMLTools.getNodes( root, "deegreewmps:Layers", nsContext ); 282 } catch ( XMLParsingException e ) { 283 throw new XMLParsingException( "Error parsing required parameter 'Layer(s)'. " + e.getMessage() ); 284 } 285 286 for ( int i = 0; i < layerElements.size(); i++ ) { 287 Element layer = (Element) layerElements.get( i ); 288 List namedLayers = null; 289 try { 290 namedLayers = XMLTools.getNodes( layer, "sld:NamedLayer", nsContext ); 291 layerList = createLayers( namedLayers, layerList ); 292 } catch ( XMLParsingException e ) { 293 throw new XMLParsingException( "Error parsing parameter 'NamedLayer'." ); 294 } 295 List userLayers = null; 296 try { 297 userLayers = XMLTools.getNodes( layer, "sld:UserLayer", nsContext ); 298 layerList = createLayers( userLayers, layerList ); 299 } catch ( XMLParsingException e ) { 300 throw new XMLParsingException( "Error parsing parameter 'UserLayer'." ); 301 } 302 if ( ( layerList == null ) || ( layerList.size() == 0 ) ) { 303 throw new InconsistentRequestException( "Atleast one 'NamedLayer' or one " 304 + "'UserLayer' has to be specified." ); 305 } 306 } 307 Layer[] layers = layerList.toArray( new Layer[layerList.size()] ); 308 309 // BBOX 310 Element bbox = null; 311 String srsName = null; 312 Envelope boundingBox = null; 313 try { 314 bbox = (Element) XMLTools.getNode( root, "gml:Envelope", nsContext ); 315 if ( bbox != null ) { 316 try { 317 srsName = XMLTools.getAttrValue( bbox, null, "srsName", null ); 318 boundingBox = GMLGeometryAdapter.wrapBox( bbox, null ); 319 } catch ( InvalidGMLException e ) { 320 throw new XMLParsingException( "Error creating a bounding box for the " + "'BBOX' parameter." ); 321 } catch ( UnknownCRSException e ) { 322 throw new InconsistentRequestException( e.getMessage() ); 323 } 324 } 325 } catch ( XMLParsingException e ) { 326 throw new XMLParsingException( "Error parsing optional parameter 'BoundingBox'. " + e.getMessage() ); 327 } 328 329 // Center 330 Point center = null; 331 try { 332 Element centerElement = (Element) XMLTools.getNode( root, "deegreewmps:Center", nsContext ); 333 if ( centerElement != null ) { 334 try { 335 srsName = XMLTools.getAttrValue( centerElement, null, "srsName", null ); 336 center = (Point) GMLGeometryAdapter.wrap( centerElement, null ); 337 } catch ( GeometryException e ) { 338 throw new XMLParsingException( "Error creating a Point for the 'Center' " + "parameter. " 339 + e.getMessage() ); 340 } 341 } 342 } catch ( XMLParsingException e ) { 343 throw new XMLParsingException( "Error parsing optional parameter 'Center'. " + e.getMessage() ); 344 } 345 346 // ScaleDenominator 347 int scaleDenominator = -1; 348 try { 349 scaleDenominator = XMLTools.getNodeAsInt( root, "deegreewmps:ScaleDenominator", nsContext, -1 ); 350 } catch ( XMLParsingException e ) { 351 throw new XMLParsingException( "Error parsing optional parameter 'Center'. " + e.getMessage() ); 352 } 353 354 if ( boundingBox == null ) { 355 if ( center == null ) { 356 throw new InconsistentRequestException( "Both 'BoundingBox' and 'Center' are not specified. Either of " 357 + "the two must be set. Both values cannot be null" ); 358 } 359 if ( scaleDenominator == -1 ) { 360 throw new InconsistentRequestException( "Scale Denominator must be specified if the Bounding Box has " 361 + "not been specified. Please check the 'SCALEDENOMINATOR' " 362 + "parameter." ); 363 } 364 } 365 366 // TRANSPARENT 367 boolean transparent = XMLTools.getNodeAsBoolean( root, "deegreewmps:Transparent", nsContext, false ); 368 369 // BGCOLOR 370 Color bgColor = null; 371 String colorstring = XMLTools.getNodeAsString( root, "deegreewmps:BGColor", nsContext, null ); 372 if ( colorstring == null ) { 373 bgColor = Color.WHITE; 374 } else { 375 try { 376 bgColor = Color.decode( colorstring ); 377 } catch ( Exception e ) { 378 throw new InconsistentRequestException( "Error parsing 'BGCOLOR' parameter. The color '" + colorstring 379 + "' is not a hexadecimal definition of a valid color. " 380 + e.getMessage() ); 381 } 382 } 383 384 boolean legend = XMLTools.getNodeAsBoolean( root, "deegreewmps:Legend", nsContext, false ); 385 386 boolean scaleBar = XMLTools.getNodeAsBoolean( root, "deegreewmps:ScaleBar", nsContext, false ); 387 388 String template = XMLTools.getNodeAsString( root, "deegreewmps:Template", nsContext, "default" ); 389 390 String emailAdd = XMLTools.getNodeAsString( root, "deegreewmps:EMailAddress", nsContext, null ); 391 392 List list = XMLTools.getNodes( root, "deegreewmps:TextAreas/deegreewmps:TextArea", nsContext ); 393 394 TextArea[] textAreas = null; 395 String title = null; 396 String copyright = null; 397 String note = null; 398 if ( list != null ) { 399 textAreas = new TextArea[list.size()]; 400 for ( int i = 0; i < list.size(); i++ ) { 401 Node textArea = (Node) list.get( i ); 402 String name = XMLTools.getRequiredNodeAsString( textArea, "deegreewmps:Name", nsContext ); 403 String value = XMLTools.getRequiredNodeAsString( textArea, "deegreewmps:Text", nsContext ); 404 if ( name.equalsIgnoreCase( "TITLE" ) ) { 405 title = value; 406 } 407 if ( name.equalsIgnoreCase( "COPYRIGHT" ) ) { 408 copyright = value; 409 } 410 if ( name.equalsIgnoreCase( "NOTE" ) ) { 411 note = value; 412 } 413 textAreas[i] = new TextArea( name, value ); 414 415 } 416 } 417 Map<String, String> vendorSpecificParameter = getVendorSpecificParameter( root ); 418 419 String id = "" + System.currentTimeMillis(); 420 421 LOG.logInfo( "Created PrintMap request request with id '" + id + "'." ); 422 423 return new PrintMap( id, version, layers, srsName, boundingBox, center, scaleDenominator, transparent, bgColor, 424 title, copyright, legend, scaleBar, note, template, emailAdd, setCurrentTime(), textAreas, 425 vendorSpecificParameter ); 426 427 } 428 429 /** 430 * Returns the vendorspecific parameters as a map. Currently handles only the 'session id' 431 * 432 * @param root 433 * @return Map 434 */ 435 private static Map<String, String> getVendorSpecificParameter( Element root ) { 436 437 Map<String, String> vendorspecific = new HashMap<String, String>(); 438 439 String sessionID = XMLTools.getAttrValue( root, null, "sessionID", null ); 440 if ( sessionID != null ) { 441 LOG.logInfo( "vendor specific parameter 'sessionid' retrieved" ); 442 vendorspecific.put( "SESSIONID", sessionID ); 443 } 444 445 return vendorspecific; 446 } 447 448 /** 449 * Create Layer objects for each of namedLayer and userLayer. 450 * 451 * @param layerNodes 452 * @param layers 453 * @return List list of layer objects 454 * @throws XMLParsingException 455 */ 456 private static List<Layer> createLayers( List layerNodes, List<Layer> layers ) 457 throws XMLParsingException { 458 459 if ( layerNodes != null ) { 460 for ( int i = 0; i < layerNodes.size(); i++ ) { 461 Node layerNode = (Node) layerNodes.get( i ); 462 try { 463 String layerName = XMLTools.getRequiredNodeAsString( layerNode, "sld:Name", nsContext ); 464 String styleName = XMLTools.getRequiredNodeAsString( layerNode, "sld:NamedStyle/sld:Name", 465 nsContext ); 466 layers.add( new Layer( layerName, styleName ) ); 467 } catch ( XMLParsingException e ) { 468 throw new XMLParsingException( "Error creating a Layer from the Node '" + layerNode.getNodeName() 469 + "'. " + e.getMessage() ); 470 } 471 } 472 } 473 474 return layers; 475 } 476 477 /** 478 * creates a <tt>PrintMapRequest</tt> from a <tt>HashMap</tt> that contains the request 479 * parameters as key-value-pairs. Keys are expected to be in upper case notation. 480 * 481 * @param model 482 * <tt>HashMap</tt> containing the request parameters 483 * @return an instance of <tt>PrinttMapRequest</tt> 484 * @throws InconsistentRequestException 485 */ 486 public static PrintMap create( Map<String, String> model ) 487 throws InconsistentRequestException { 488 489 retrieveRequestParameter( model ); 490 491 String version = retrieveVersionParameter( model ); 492 493 Layer[] layers = retrieveLayerAndStyleParameters( model ); 494 495 String srs = retrieveSRSParameter( model ); 496 497 Envelope boundingBox = null; 498 Point center = null; 499 try { 500 boundingBox = retrieveBBOXParameter( model, srs ); 501 center = retrieveCenterParameter( model, srs ); 502 } catch ( UnknownCRSException e ) { 503 throw new InconsistentRequestException( e.getMessage() ); 504 } 505 506 int scaleDenominator = retrieveScaleDenominatorParameter( model ); 507 508 if ( boundingBox == null ) { 509 if ( center == null ) { 510 throw new InconsistentRequestException( "Both 'BoundingBox' and 'Center' are not specified. Either of " 511 + "the 2 must be set. Both values cannot be null" ); 512 } 513 if ( scaleDenominator == -1 ) { 514 throw new InconsistentRequestException( "Scale Denominator must be specified if the Bounding Box has " 515 + "not been specified. Please check the 'SCALEDENOMINATOR' " 516 + "parameter." ); 517 } 518 } 519 520 boolean transparent = retrieveTransparentParameter( model ); 521 522 Color bgColor = retrieveBGColorParameter( model ); 523 524 String title = retrieveTitleParameter( model ); 525 526 String copyRightNote = retrieveCopyrightParameter( model ); 527 528 boolean legend = retrieveLegendParameter( model ); 529 530 boolean scaleBar = retrieveScaleBarParameter( model ); 531 532 String note = retrieveNoteParameter( model ); 533 534 String template = retrieveTemplateParameter( model ); 535 536 String emailaddress = retrieveEmailParameter( model ); 537 538 TextArea[] textAreas = retrieveTextAreas( model ); 539 540 Map<String, String> vendorSpecificParameter = model; 541 542 String id = "" + System.currentTimeMillis(); 543 544 return new PrintMap( id, version, layers, srs, boundingBox, center, scaleDenominator, transparent, bgColor, 545 title, copyRightNote, legend, scaleBar, note, template, emailaddress, setCurrentTime(), 546 textAreas, vendorSpecificParameter ); 547 548 } 549 550 /** 551 * Retrieve the Text Areas to be displayed on the PDF output file. Extract the comma seperated 552 * list of name, value pairs. The name and value should be seperated with a ':'. E.g.-> 553 * name:value,name:value,name:value 554 * 555 * @param model 556 * @return TextArea 557 */ 558 private static TextArea[] retrieveTextAreas( Map model ) { 559 560 List<TextArea> texts = new ArrayList<TextArea>(); 561 if ( model.containsKey( "TEXTAREAS" ) ) { 562 String textstring = (String) model.remove( "TEXTAREAS" ); 563 if ( textstring != null ) { 564 String[] nameValue = StringTools.toArray( textstring, ",", true ); 565 if ( nameValue != null ) { 566 for ( int i = 0; i < nameValue.length; i++ ) { 567 String tmp = nameValue[i].trim(); 568 int idx = tmp.indexOf( ":" ); 569 if ( idx != -1 ) { 570 String name = tmp.substring( 0, idx ); 571 String value = tmp.substring( idx + 1, tmp.length() ); 572 if ( ( name != null ) && ( value != null ) ) { 573 TextArea area = new TextArea( name.toUpperCase(), value ); 574 texts.add( area ); 575 } 576 } 577 } 578 } 579 } 580 } 581 582 return texts.toArray( new TextArea[texts.size()] ); 583 584 } 585 586 /** 587 * Parse 'Template' Parameter. 588 * 589 * @param model 590 * @return String 591 * @throws InconsistentRequestException 592 */ 593 private static String retrieveTemplateParameter( Map model ) 594 throws InconsistentRequestException { 595 596 String templatestring = null; 597 if ( model.containsKey( "TEMPLATE" ) ) { 598 templatestring = (String) model.remove( "TEMPLATE" ); 599 600 } 601 if ( templatestring == null ) { 602 throw new InconsistentRequestException( "No Template defined. A Template name has to be specified " 603 + "along with the 'PrintMap' request." ); 604 } 605 606 return templatestring; 607 } 608 609 /** 610 * Retrieve Email parameter 611 * 612 * @param model 613 * @return String 614 * @throws InconsistentRequestException 615 */ 616 private static String retrieveEmailParameter( Map model ) 617 throws InconsistentRequestException { 618 619 String email = null; 620 if ( model.containsKey( "EMAIL" ) ) { 621 email = (String) model.remove( "EMAIL" ); 622 } 623 624 if ( email == null ) { 625 throw new InconsistentRequestException( "EMail parameter must be set." ); 626 } 627 628 return email; 629 } 630 631 /** 632 * Parse 'Note' Parameter. 633 * 634 * @param model 635 * @return String 636 */ 637 private static String retrieveNoteParameter( Map model ) { 638 639 String note = null; 640 if ( model.containsKey( "NOTE" ) ) { 641 note = (String) model.remove( "NOTE" ); 642 } 643 644 return note; 645 } 646 647 /** 648 * Parse 'ScaleBar' Parameter. 649 * 650 * @param model 651 * @return boolean 652 * @throws InconsistentRequestException 653 */ 654 private static boolean retrieveScaleBarParameter( Map model ) 655 throws InconsistentRequestException { 656 657 boolean showScaleBar = false; 658 if ( model.containsKey( "SCALEBAR" ) ) { 659 String scaleBar = (String) model.remove( "SCALEBAR" ); 660 if ( scaleBar == null ) { 661 showScaleBar = false; 662 } else if ( scaleBar.equalsIgnoreCase( "True" ) ) { 663 showScaleBar = true; 664 } else if ( scaleBar.equalsIgnoreCase( "False" ) ) { 665 showScaleBar = false; 666 } else { 667 throw new InconsistentRequestException( "The 'ScaleBar' parameter can only have 'True', 'False' " 668 + "values. Here it is '" + scaleBar + "'." ); 669 } 670 } 671 672 return showScaleBar; 673 } 674 675 /** 676 * Parse 'Legend' Parameter. 677 * 678 * @param model 679 * @return boolean 680 * @throws InconsistentRequestException 681 */ 682 private static boolean retrieveLegendParameter( Map model ) 683 throws InconsistentRequestException { 684 685 boolean showLegend = false; 686 if ( model.containsKey( "LEGEND" ) ) { 687 String legend = (String) model.remove( "LEGEND" ); 688 if ( legend == null ) { 689 showLegend = false; 690 } else if ( legend.equalsIgnoreCase( "True" ) ) { 691 showLegend = true; 692 } else if ( legend.equalsIgnoreCase( "False" ) ) { 693 showLegend = false; 694 } else { 695 throw new InconsistentRequestException( "The 'Legend' parameter can only have 'True', 'False' values. " 696 + "Here it is '" + legend + "'." ); 697 } 698 } 699 700 return showLegend; 701 702 } 703 704 /** 705 * Parse 'Copyright' Parameter. 706 * 707 * @param model 708 * @return String 709 */ 710 private static String retrieveCopyrightParameter( Map model ) { 711 712 String copyright = null; 713 if ( model.containsKey( "COPYRIGHT" ) ) { 714 copyright = (String) model.remove( "COPYRIGHT" ); 715 } 716 717 return copyright; 718 } 719 720 /** 721 * Parse 'Title' Parameter. 722 * 723 * @param model 724 * @return String 725 */ 726 private static String retrieveTitleParameter( Map model ) { 727 728 String title = null; 729 if ( model.containsKey( "TITLE" ) ) { 730 title = (String) model.remove( "TITLE" ); 731 } 732 733 return title; 734 } 735 736 /** 737 * Parse 'BGColor' Parameter. 738 * 739 * @param model 740 * @return Color 741 * @throws InconsistentRequestException 742 */ 743 private static Color retrieveBGColorParameter( Map model ) 744 throws InconsistentRequestException { 745 746 Color bgColor = Color.WHITE; 747 if ( model.containsKey( "BGCOLOR" ) ) { 748 String colorstring = (String) model.remove( "BGCOLOR" ); 749 if ( ( colorstring != null ) || ( colorstring == "" ) ) { 750 try { 751 bgColor = Color.decode( colorstring ); 752 } catch ( Exception e ) { 753 throw new InconsistentRequestException( "Error parsing 'BGCOLOR' parameter. The color '" 754 + colorstring + "' is not a hexadecimal " 755 + "definition of a valid color. " + e.getMessage() ); 756 } 757 } 758 } 759 760 return bgColor; 761 } 762 763 /** 764 * Parse 'Transparent' Parameter. 765 * 766 * @param model 767 * @return boolean 768 * @throws InconsistentRequestException 769 */ 770 private static boolean retrieveTransparentParameter( Map model ) 771 throws InconsistentRequestException { 772 773 boolean isTransparent = false; 774 if ( model.containsKey( "TRANSPARENT" ) ) { 775 String transparent = (String) model.remove( "TRANSPARENT" ); 776 if ( transparent == null ) { 777 isTransparent = false; 778 } else if ( transparent.equalsIgnoreCase( "True" ) ) { 779 isTransparent = true; 780 } else if ( transparent.equalsIgnoreCase( "False" ) ) { 781 isTransparent = false; 782 } else { 783 throw new InconsistentRequestException( "The 'Transparent' parameter can only have " 784 + "'True', 'False' values. Here it has '" + transparent + "'." ); 785 } 786 } 787 788 return isTransparent; 789 } 790 791 /** 792 * Parse 'ScaleDenominator' Parameter. 793 * 794 * @param model 795 * @return String 796 */ 797 private static int retrieveScaleDenominatorParameter( Map model ) { 798 799 int scale = -1; 800 if ( model.containsKey( "SCALE" ) ) { 801 String value = (String) model.remove( "SCALE" ); 802 if ( value != null ) { 803 scale = Integer.parseInt( value ); 804 } 805 } 806 807 return scale; 808 809 } 810 811 /** 812 * Parse 'Center' Parameter and create a point. 813 * 814 * @param model 815 * @param srs 816 * @return Point to represent the x,y coordinates. 817 * @throws InconsistentRequestException 818 * @throws UnknownCRSException 819 */ 820 private static Point retrieveCenterParameter( Map model, String srs ) 821 throws InconsistentRequestException, UnknownCRSException { 822 823 Point center = null; 824 if ( model.containsKey( "CENTER" ) ) { 825 String centerstring = (String) model.remove( "CENTER" ); 826 827 String[] values = centerstring.split( "," ); 828 if ( values.length != 2 ) { 829 throw new InconsistentRequestException( "Centre should be defined as a Point with 'X' and 'Y' " 830 + "values. The current length is '" + values.length 831 + "'. It should " + "be '2'." ); 832 } 833 double x = -1; 834 double y = -1; 835 try { 836 x = Double.parseDouble( values[0] ); 837 y = Double.parseDouble( values[1] ); 838 } catch ( Exception e ) { 839 throw new InconsistentRequestException( "Error converting 'X','Y' coordinates in the request " 840 + "parameter 'CENTER' to double. Please check the " 841 + "values entered." ); 842 } 843 844 CoordinateSystem crs = CRSFactory.create( srs ); 845 center = GeometryFactory.createPoint( x, y, crs ); 846 847 } 848 849 return center; 850 } 851 852 /** 853 * Parse 'Envelope' Parameter and create an envelope. 854 * 855 * @param model 856 * @param srs 857 * @return Envelope 858 * @throws InconsistentRequestException 859 * @throws InvalidFormatException 860 * @throws UnknownCRSException 861 */ 862 private static Envelope retrieveBBOXParameter( Map model, String srs ) 863 throws InconsistentRequestException, InvalidFormatException, UnknownCRSException { 864 865 Envelope bbox = null; 866 867 if ( model.containsKey( "BBOX" ) ) { 868 String boxstring = (String) model.remove( "BBOX" ); 869 StringTokenizer st = new StringTokenizer( boxstring, "," ); 870 String s = st.nextToken().replace( ' ', '+' ); 871 double minx = Double.parseDouble( s ); 872 s = st.nextToken().replace( ' ', '+' ); 873 double miny = Double.parseDouble( s ); 874 s = st.nextToken().replace( ' ', '+' ); 875 double maxx = Double.parseDouble( s ); 876 s = st.nextToken().replace( ' ', '+' ); 877 double maxy = Double.parseDouble( s ); 878 879 if ( minx >= maxx ) { 880 throw new InvalidFormatException( "minx must be lesser than maxx" ); 881 } 882 883 if ( miny >= maxy ) { 884 throw new InvalidFormatException( "miny must be lesser than maxy" ); 885 } 886 887 CoordinateSystem crs = CRSFactory.create( srs ); 888 bbox = GeometryFactory.createEnvelope( minx, miny, maxx, maxy, crs ); 889 } 890 891 return bbox; 892 } 893 894 /** 895 * Parse 'SRS' Parameter. 896 * 897 * @param model 898 * @return String 899 * @throws InconsistentRequestException 900 */ 901 private static String retrieveSRSParameter( Map model ) 902 throws InconsistentRequestException { 903 904 String srs = null; 905 if ( model.containsKey( "SRS" ) ) { 906 srs = (String) model.remove( "SRS" ); 907 } 908 if ( srs == null ) { 909 throw new InconsistentRequestException( "SRS-value must be set" ); 910 } 911 912 return srs; 913 } 914 915 /** 916 * Parse 'Layer' and 'Style' Parameter. 917 * 918 * @param model 919 * @return Layer[] 920 * @throws InconsistentRequestException 921 */ 922 private static Layer[] retrieveLayerAndStyleParameters( Map model ) 923 throws InconsistentRequestException { 924 925 String layersstring = null; 926 if ( model.containsKey( "LAYERS" ) ) { 927 layersstring = (String) model.remove( "LAYERS" ); 928 } 929 String stylesstring = null; 930 if ( model.containsKey( "STYLES" ) ) { 931 stylesstring = (String) model.remove( "STYLES" ); 932 } 933 934 // normalize styles parameter 935 if ( ( stylesstring == null ) || stylesstring.trim().equals( "" ) ) { 936 stylesstring = "$DEFAULT"; 937 } 938 if ( stylesstring.startsWith( "," ) ) { 939 stylesstring = "$DEFAULT" + stylesstring; 940 } 941 String tmp = ",$DEFAULT,"; 942 stylesstring = StringTools.replace( stylesstring, ",,", tmp, true ); 943 if ( stylesstring.endsWith( "," ) ) { 944 stylesstring = stylesstring + "$DEFAULT"; 945 } 946 List<String> layers = new ArrayList<String>(); 947 List<String> styles = new ArrayList<String>(); 948 GetMap.Layer[] ls = null; 949 if ( ( layersstring != null ) && !layersstring.trim().equals( "" ) ) { 950 StringTokenizer st = new StringTokenizer( layersstring, "," ); 951 int a = 0; 952 while ( st.hasMoreTokens() ) { 953 String s = st.nextToken(); 954 layers.add( s ); 955 } 956 st = new StringTokenizer( stylesstring, "," ); 957 for ( int i = 0; i < layers.size(); i++ ) { 958 styles.add( "$DEFAULT" ); 959 } 960 a = 0; 961 while ( st.hasMoreTokens() ) { 962 String s = st.nextToken(); 963 styles.set( a++, s ); 964 } 965 966 // At last, build up the Layer object 967 ls = new GetMap.Layer[layers.size()]; 968 969 for ( int i = 0; i < layers.size(); i++ ) { 970 try { 971 String l = URLDecoder.decode( layers.get( i ), CharsetUtils.getSystemCharset() ); 972 ls[i] = PrintMap.createLayer( l, styles.get( i ) ); 973 } catch ( UnsupportedEncodingException e2 ) { 974 e2.printStackTrace(); 975 } 976 } 977 } 978 979 if ( ( ls == null || ls.length == 0 ) ) { 980 throw new InconsistentRequestException( "No layers defined in PrintMapRequest request" ); 981 } 982 983 return ls; 984 } 985 986 /** 987 * Parse the Request parameter to check if the request is actually a 'PrintMapRequest' request 988 * 989 * @param model 990 * @throws InconsistentRequestException 991 */ 992 private static void retrieveRequestParameter( Map model ) 993 throws InconsistentRequestException { 994 995 String request = null; 996 if ( model.containsKey( "REQUEST" ) ) { 997 request = (String) model.remove( "REQUEST" ); 998 } else { 999 throw new InconsistentRequestException( "Unable to create a PrintMapRequest operation. " 1000 + "The request parameter is missing." ); 1001 } 1002 if ( request == null || !( request.equals( "PrintMap" ) ) ) { 1003 throw new InconsistentRequestException( "Unable to create a PrintMapRequest operation for request '" 1004 + request + "'." ); 1005 } 1006 1007 } 1008 1009 /** 1010 * Parse 'Version' Parameter. 1011 * 1012 * @param model 1013 * @return String version (default=1.0.0) 1014 */ 1015 private static String retrieveVersionParameter( Map model ) { 1016 1017 String version = null; 1018 if ( model.containsKey( "VERSION" ) ) { 1019 version = (String) model.remove( "VERSION" ); 1020 } 1021 if ( version == null ) { 1022 /** default value set as per the WMPS draft specifications. */ 1023 version = "1.0.0"; 1024 } 1025 1026 return version; 1027 } 1028 1029 /** 1030 * Get TimeStamp 1031 * 1032 * @return TimeStamp 1033 */ 1034 public Timestamp getTimestamp() { 1035 return this.timestamp; 1036 } 1037 1038 /** 1039 * Get SRS 1040 * 1041 * @return String 1042 */ 1043 public String getSRS() { 1044 return this.srs; 1045 } 1046 1047 /** 1048 * Get bounding box 1049 * 1050 * @return Envelope maybe null 1051 */ 1052 public Envelope getBBOX() { 1053 return this.boundingBox; 1054 } 1055 1056 /** 1057 * Get center 1058 * 1059 * @return Point maybe null 1060 */ 1061 public Point getCenter() { 1062 return this.center; 1063 } 1064 1065 /** 1066 * Get ScaleDenominator 1067 * 1068 * @return String maybe null 1069 */ 1070 public int getScaleDenominator() { 1071 return this.scaleDenominator; 1072 } 1073 1074 /** 1075 * Get Transparency 1076 * 1077 * @return boolean 1078 */ 1079 public boolean getTransparent() { 1080 return this.transparent; 1081 } 1082 1083 /** 1084 * Get BGColor 1085 * 1086 * @return Color default is White. 1087 */ 1088 public Color getBGColor() { 1089 return this.bgColor; 1090 } 1091 1092 /** 1093 * Get Map Title 1094 * 1095 * @return String maybe null 1096 */ 1097 public String getTitle() { 1098 return this.title; 1099 } 1100 1101 /** 1102 * Get Copyright 1103 * 1104 * @return String maybe null 1105 */ 1106 public String getCopyright() { 1107 return this.copyright; 1108 } 1109 1110 /** 1111 * Get Legend 1112 * 1113 * @return boolean 1114 */ 1115 public boolean getLegend() { 1116 return this.legend; 1117 } 1118 1119 /** 1120 * Get Scale Bar 1121 * 1122 * @return boolean 1123 */ 1124 public boolean getScaleBar() { 1125 return this.scaleBar; 1126 } 1127 1128 /** 1129 * Get Note (extra descriptive text) 1130 * 1131 * @return String maybe null 1132 */ 1133 public String getNote() { 1134 return this.note; 1135 } 1136 1137 /** 1138 * Get Template 1139 * 1140 * @return String 1141 */ 1142 public String getTemplate() { 1143 return this.template; 1144 } 1145 1146 /** 1147 * Get Email Address 1148 * 1149 * @return String 1150 */ 1151 public String getEmailAddress() { 1152 return this.emailaddress; 1153 } 1154 1155 /** 1156 * Get Text Areas 1157 * 1158 * @return TextArea[] 1159 */ 1160 public TextArea[] getTextAreas() { 1161 return this.textAreas; 1162 } 1163 1164 /** 1165 * Retrieve ( if available ) the current text area identified by 'name' from the list of text 1166 * areas defined. May return null. 1167 * 1168 * @param name 1169 * @return TextArea 1170 */ 1171 public TextArea getTextArea( String name ) { 1172 1173 TextArea textArea = null; 1174 if ( this.textAreas != null && this.textAreas.length > 0 ) { 1175 for ( int i = 0; i < this.textAreas.length; i++ ) { 1176 TextArea tmp = this.textAreas[i]; 1177 if ( tmp.getName().equalsIgnoreCase( name ) ) { 1178 textArea = tmp; 1179 break; 1180 } 1181 } 1182 } 1183 1184 return textArea; 1185 } 1186 1187 /** 1188 * creates a Layer object beacuse of the inner class construct. 1189 * 1190 * @param name 1191 * the name of the layer 1192 * @param style 1193 * the corresponding style of the layer 1194 * @return Layer a layer object constaining name and style 1195 */ 1196 public static Layer createLayer( String name, String style ) { 1197 return new Layer( name, style ); 1198 } 1199 1200 /** 1201 * Returns a new PrintMap instance. 1202 * 1203 * @param id 1204 * @param version 1205 * @param layers 1206 * @param srs 1207 * @param bbox 1208 * @param center 1209 * @param scaleDenominator 1210 * @param transparent 1211 * @param bgColor 1212 * @param title 1213 * @param copyright 1214 * @param legend 1215 * @param scaleBar 1216 * @param note 1217 * @param template 1218 * @param emailAddress 1219 * @param timestamp 1220 * @param textAreas 1221 * @param vendorSpecificParameters 1222 * @return PrintMap 1223 */ 1224 public static PrintMap create( String id, String version, Layer[] layers, String srs, Envelope bbox, Point center, 1225 int scaleDenominator, boolean transparent, Color bgColor, String title, 1226 String copyright, boolean legend, boolean scaleBar, String note, String template, 1227 String emailAddress, Timestamp timestamp, TextArea[] textAreas, 1228 Map<String, String> vendorSpecificParameters ) { 1229 1230 return new PrintMap( id, version, layers, srs, bbox, center, scaleDenominator, transparent, bgColor, title, 1231 copyright, legend, scaleBar, note, template, emailAddress, timestamp, textAreas, 1232 vendorSpecificParameters ); 1233 } 1234 1235 /** 1236 * Overwrite the toString() method to export the current request as a readable statement. 1237 * Currently only the id, version and layer names will be given out. TODO the rest 1238 * 1239 * @return String 1240 */ 1241 @Override 1242 public String toString() { 1243 1244 StringBuffer sb = new StringBuffer( 200 ); 1245 sb.append( "id: " ); 1246 sb.append( getId() ); 1247 sb.append( "\n" ); 1248 sb.append( "version: " ); 1249 sb.append( getVersion() ); 1250 sb.append( "\n" ); 1251 if ( this.layers != null ) { 1252 sb.append( "layer(s): " ); 1253 for ( int i = 0; i < this.layers.size(); i++ ) { 1254 sb.append( this.layers.get( i ).getName() ); 1255 sb.append( "\n" ); 1256 } 1257 } 1258 return sb.toString(); 1259 } 1260 }