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