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