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 }