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