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 }