001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/ogcwebservices/wms/capabilities/Layer.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.wms.capabilities;
045
046 import java.util.ArrayList;
047 import java.util.Arrays;
048 import java.util.HashMap;
049 import java.util.List;
050
051 import org.deegree.graphics.sld.UserStyle;
052 import org.deegree.model.spatialschema.Envelope;
053 import org.deegree.ogcwebservices.getcapabilities.MetadataURL;
054 import org.deegree.ogcwebservices.wms.configuration.AbstractDataSource;
055
056 /**
057 * Each available map is advertised by a <Layer> element in the Capabilities XML. A single
058 * parent Layer encloses any number of additional layers, which may be hierarchically nested as
059 * desired. Some properties defined in a parent layer are inherited by the children it encloses.
060 * These inherited properties may be either redefined or added to by the child.
061 * <p>
062 * A Map Server shall include at least one <Layer> element for each map layer offered. If
063 * desired, layers may be repeated in different categories when relevant. No controlled vocabulary
064 * has been defined, so at present Layer and Style Names, Titles and Keywords are arbitrary.
065 * </p>
066 * The <Layer> element can enclose child elements providing metadata about the Layer.
067 *
068 * @author <a href="mailto:k.lupp@web.de">Katharina Lupp </a>
069 * @author <a href="mailto:mschneider@lat-lon.de">Markus Schneider </a>
070 * @author last edited by: $Author: apoth $
071 * @version 2002-03-01
072 */
073 public class Layer {
074
075 private List<AuthorityURL> authorityURL;
076
077 private List<Envelope> boundingBox;
078
079 private List<AbstractDataSource> dataSource;
080
081 private List<DataURL> dataURL;
082
083 private List<Dimension> dimension;
084
085 private List<Extent> extent;
086
087 private List<FeatureListURL> featureListURL;
088
089 private List<Identifier> identifier;
090
091 private List<String> keywordList;
092
093 private List<Layer> layer;
094
095 private List<MetadataURL> metadataURL;
096
097 private List<String> srs;
098
099 private Attribution attribution;
100
101 private Envelope latLonBoundingBox;
102
103 private HashMap<String, Style> styles;
104
105 private Layer parent;
106
107 private ScaleHint scaleHint;
108
109 private String abstract_;
110
111 private String name;
112
113 private String title;
114
115 private boolean noSubsets = false;
116
117 private boolean opaque = false;
118
119 private boolean queryable = false;
120
121 private int cascaded = -1;
122
123 private int fixedHeight = -1;
124
125 private int fixedWidth = -1;
126
127 /**
128 * default constructor
129 */
130 private Layer() {
131 keywordList = new ArrayList<String>( 20 );
132 srs = new ArrayList<String>( 20 );
133 boundingBox = new ArrayList<Envelope>();
134 dimension = new ArrayList<Dimension>();
135 extent = new ArrayList<Extent>();
136 authorityURL = new ArrayList<AuthorityURL>();
137 identifier = new ArrayList<Identifier>();
138 metadataURL = new ArrayList<MetadataURL>();
139 dataURL = new ArrayList<DataURL>();
140 featureListURL = new ArrayList<FeatureListURL>();
141 styles = new HashMap<String, Style>();
142 layer = new ArrayList<Layer>( 50 );
143 dataSource = new ArrayList<AbstractDataSource>();
144 }
145
146 /**
147 * constructor initializing the class with the <Layer>
148 *
149 * @param queryable
150 * @param cascaded
151 * @param opaque
152 * @param noSubsets
153 * @param fixedWidth
154 * @param fixedHeight
155 * @param name
156 * @param title
157 * @param abstract_
158 * @param latLonBoundingBox
159 * @param attribution
160 * @param scaleHint
161 * @param keywordList
162 * @param srs
163 * @param boundingBoxes
164 * @param dimensions
165 * @param extents
166 * @param authorityURLs
167 * @param identifiers
168 * @param metadataURLs
169 * @param dataURLs
170 * @param featureListURLs
171 * @param styles
172 * @param layers
173 * @param dataSource
174 * @param parent
175 */
176 public Layer( boolean queryable, int cascaded, boolean opaque, boolean noSubsets,
177 int fixedWidth, int fixedHeight, String name, String title, String abstract_,
178 Envelope latLonBoundingBox, Attribution attribution, ScaleHint scaleHint,
179 String[] keywordList, String[] srs, LayerBoundingBox[] boundingBoxes,
180 Dimension[] dimensions, Extent[] extents, AuthorityURL[] authorityURLs,
181 Identifier[] identifiers, MetadataURL[] metadataURLs, DataURL[] dataURLs,
182 FeatureListURL[] featureListURLs, Style[] styles, Layer[] layers,
183 AbstractDataSource[] dataSource, Layer parent ) {
184 this();
185 this.queryable = queryable;
186 this.cascaded = cascaded;
187 this.opaque = opaque;
188 this.noSubsets = noSubsets;
189 this.fixedWidth = fixedWidth;
190 this.fixedHeight = fixedHeight;
191 setName( name );
192 setTitle( title );
193 setAbstract( abstract_ );
194 setLatLonBoundingBox( latLonBoundingBox );
195 setAttribution( attribution );
196 setScaleHint( scaleHint );
197 setKeywordList( keywordList );
198 setSrs( srs );
199 setBoundingBox( boundingBoxes );
200 setDimension( dimensions );
201 setExtent( extents );
202 setAuthorityURL( authorityURLs );
203 setIdentifier( identifiers );
204 setMetadataURL( metadataURLs );
205 setDataURL( dataURLs );
206 setFeatureListURL( featureListURLs );
207 setStyles( styles );
208 setLayer( layers );
209 setDataSource( dataSource );
210 setParent( parent );
211 }
212
213 /**
214 * If, and only if, a layer has a <Name>, then it is a map layer that can be requested by
215 * using that Name in the LAYERS parameter of a GetMap request. If the layer has a Title but no
216 * Name, then that layer is only a category title for all the layers nested within. A Map Server
217 * that advertises a Layer containing a Name element shall be able to accept that Name as the
218 * value of LAYERS argument in a GetMap request and return the corresponding map. A Client shall
219 * not attempt to request a layer that has a Title but no Name.
220 *
221 * @return the name
222 */
223 public String getName() {
224 return name;
225 }
226
227 /**
228 * sets the name of the layer
229 *
230 * @param name
231 */
232 public void setName( String name ) {
233 this.name = name;
234 }
235
236 /**
237 * A <Title> is required for all layers; it is a human-readable string for presentation in
238 * a menu. The Title is not inherited by child Layers.
239 *
240 * @return the title
241 */
242 public String getTitle() {
243 return title;
244 }
245
246 /**
247 * sets the title for the layer
248 *
249 * @param title
250 */
251 public void setTitle( String title ) {
252 this.title = title;
253 }
254
255 /**
256 * Abstract is a narrative description of the map layer. The Abstract elements are not inherited
257 * by child Layers.
258 *
259 * @return the abstract
260 */
261 public String getAbstract() {
262 return abstract_;
263 }
264
265 /**
266 * sets the a narrative description of the map layer
267 *
268 * @param abstract_
269 */
270 public void setAbstract( String abstract_ ) {
271 this.abstract_ = abstract_;
272 }
273
274 /**
275 * KeywordList contains zero or more Keywords to aid in catalog searches. The KeywordList
276 * elements are not inherited by child Layers.
277 *
278 * @return the keywords
279 */
280 public String[] getKeywordList() {
281 return keywordList.toArray( new String[keywordList.size()] );
282 }
283
284 /**
285 * adds the keywordList
286 *
287 * @param keyword
288 */
289 public void addKeyword( String keyword ) {
290 this.keywordList.add( keyword );
291 }
292
293 /**
294 * sets the keywordList
295 *
296 * @param keywordList
297 */
298 public void setKeywordList( String[] keywordList ) {
299 if ( keywordList == null )
300 this.keywordList.clear();
301 else
302 this.keywordList = Arrays.asList( keywordList );
303 }
304
305 /**
306 * Every Layer is available in one or more spatial reference systems Every Layer shall have at
307 * least one >SRS> element that is either stated explicitly or inherited from a parent
308 * Layer . The root <Layer> element shall include a sequence of zero or more SRS elements
309 * listing all SRSes that are common to all subsidiary layers. Use a single SRS element with
310 * empty content (like so: "<SRS></SRS> ") if there is no common SRS. Layers may
311 * optionally add to the global SRS list, or to the list inherited from a parent layer. Any
312 * duplication shall be ignored by clients. When a Layer is available in several Spatial
313 * Reference Systems, there are two ways to encode the list of SRS values. The first of these is
314 * new in this version of the specification, the second is deprecated but still included for
315 * backwards compatibility.
316 * <p>
317 * 1. Optional, recommended: Multiple single-valued <SRS> elements: a list of SRS values
318 * is represented as a sequence of <SRS> elements, each of which contains only a single
319 * SRS name. Example: <SRS>EPSG:1234</SRS> <SRS>EPSG:5678</SRS>.
320 * </p>
321 * 2. Deprecated: Single list-valued <SRS> element: a list of SRS values is represented
322 * asa whitespace-separated list of SRS names contained within a single <SRS> element.
323 * Example: <SRS>EPSG:1234 EPSG:5678</SRS>.
324 *
325 * @return the srs
326 */
327 public String[] getSrs() {
328 String[] pSrs = null;
329
330 if ( parent != null ) {
331 pSrs = parent.getSrs();
332 } else {
333 pSrs = new String[0];
334 }
335
336 List<String> list = new ArrayList<String>( srs.size() + pSrs.length );
337 list.addAll( srs );
338 for ( int i = 0; i < pSrs.length; i++ ) {
339 if ( !list.contains( pSrs[i] ) ) {
340 list.add( pSrs[i] );
341 }
342 }
343
344 return list.toArray( new String[list.size()] );
345 }
346
347 /**
348 * @param srs
349 * @return s true if the submitted srs (name) is supported by the layer
350 */
351 public boolean isSrsSupported( String srs ) {
352 String[] sr = getSrs();
353 for ( int i = 0; i < sr.length; i++ ) {
354 if ( sr[i].equals( srs ) ) {
355 return true;
356 }
357 }
358 return false;
359 }
360
361 /**
362 * adds the spatial reference system (srs)
363 *
364 * @param srs
365 */
366 public void addSrs( String srs ) {
367 this.srs.add( srs );
368 }
369
370 /**
371 * sets the srs
372 *
373 * @param srs
374 */
375 public void setSrs( String[] srs ) {
376 if ( srs == null )
377 this.srs.clear();
378 else
379 this.srs = Arrays.asList( srs );
380 }
381
382 /**
383 * Every Layer shall have exactly one <LatLonBoundingBox> element that is either stated
384 * explicitly or inherited from a parent Layer. LatLonBoundingBox states the minimum bounding
385 * rectangle of the map data in the EPSG:4326 geographic coordinate system. The
386 * LatLonBoundingBox attributes minx, miny, maxx, maxy indicate the edges of an enclosing
387 * rectangle in decimal degrees. LatLonBoundingBox shall be supplied regardless of what SRS the
388 * map server may support, but it may be approximate if EPSG:4326 is not supported. Its purpose
389 * is to facilitate geographic searches without requiring coordinate transformations by the
390 * search engine.
391 *
392 * @return the bbox
393 */
394 public Envelope getLatLonBoundingBox() {
395 if ( ( latLonBoundingBox == null ) && ( parent != null ) ) {
396 return parent.getLatLonBoundingBox();
397 }
398 return latLonBoundingBox;
399 }
400
401 /**
402 * sets the LatLonBoundingBox element that is either stated explicitly or inherited from a
403 * parent Layer.
404 *
405 * @param latLonBoundingBox
406 */
407 public void setLatLonBoundingBox( Envelope latLonBoundingBox ) {
408 this.latLonBoundingBox = latLonBoundingBox;
409 }
410
411 /**
412 * Layers may have zero or more <BoundingBox> elements that are either stated explicitly
413 * or inherited from a parent Layer. Each BoundingBox states the bounding rectangle of the map
414 * data in a particular spatial reference system; the attribute SRS indicates which SRS applies.
415 * If the data area is shaped irregularly then the BoundingBox gives the minimum enclosing
416 * rectangle. The attributes minx, miny, maxx, maxy indicate the edges of the bounding box in
417 * units of the specified SRS. Optional resx and resy attributes indicate the spatial resolution
418 * of the data in those same units.
419 * <p>
420 * A Layer may have multiple BoundingBox element, but each one shall state a different SRS. A
421 * Layer inherits any BoundingBox values defined by its parents. A BoundingBox inherited from
422 * the parent Layer for a particular SRS is replaced by any declaration for the same SRS in the
423 * child Layer. A BoundingBox in the child for a new SRS not already declared by the parent is
424 * added to the list of bounding boxes for the child Layer. A single Layer element shall not
425 * contain more than one BoundingBox for the same SRS.
426 * </p>
427 *
428 * @return bounding boxes
429 */
430 public LayerBoundingBox[] getBoundingBoxes() {
431 HashMap<String, LayerBoundingBox> list = new HashMap<String, LayerBoundingBox>( 100 );
432
433 if ( parent != null ) {
434 LayerBoundingBox[] plb = parent.getBoundingBoxes();
435
436 for ( int i = 0; i < plb.length; i++ ) {
437 list.put( plb[i].getSRS(), plb[i] );
438 }
439 }
440
441 for ( int i = 0; i < boundingBox.size(); i++ ) {
442 LayerBoundingBox lb = (LayerBoundingBox) boundingBox.get( i );
443 list.put( lb.getSRS(), lb );
444 }
445
446 LayerBoundingBox[] lbs = new LayerBoundingBox[list.size()];
447 return list.values().toArray( lbs );
448 }
449
450 /**
451 * adds the <BoundingBox>
452 *
453 * @param boundingBox
454 */
455 public void addBoundingBox( Envelope boundingBox ) {
456 this.boundingBox.add( boundingBox );
457 }
458
459 /**
460 * sets the boundingBox
461 *
462 * @param boundingBox
463 */
464 public void setBoundingBox( LayerBoundingBox[] boundingBox ) {
465 this.boundingBox.clear();
466
467 if ( boundingBox != null ) {
468 for ( int i = 0; i < boundingBox.length; i++ ) {
469 this.boundingBox.add( boundingBox[i] );
470 }
471 }
472 }
473
474 /**
475 * Dimension declarations are inherited from parent Layers. Any new Dimension declarations in
476 * the child are added to the list inherited from the parent. A child shall not redefine a
477 * Dimension with the same name attribute as one that was inherited.
478 *
479 * @return the dimensions
480 */
481 public Dimension[] getDimension() {
482 HashMap<String, Dimension> list = new HashMap<String, Dimension>();
483
484 if ( parent != null ) {
485 Dimension[] pDim = parent.getDimension();
486
487 for ( int i = 0; i < pDim.length; i++ ) {
488 list.put( pDim[i].getName(), pDim[i] );
489 }
490 }
491
492 for ( int i = 0; i < dimension.size(); i++ ) {
493 Dimension dim = dimension.get( i );
494
495 if ( list.get( dim.getName() ) == null ) {
496 list.put( dim.getName(), dim );
497 }
498 }
499
500 return list.values().toArray( new Dimension[list.size()] );
501 }
502
503 /**
504 * adds the dimension
505 *
506 * @param dimension
507 */
508 public void addDimension( Dimension dimension ) {
509 this.dimension.add( dimension );
510 }
511
512 /**
513 * sets the dimension
514 *
515 * @param dimension
516 */
517 public void setDimension( Dimension[] dimension ) {
518 if ( dimension == null )
519 this.dimension.clear();
520 else
521 this.dimension = Arrays.asList( dimension );
522 }
523
524 /**
525 * Extent declarations are inherited from parent Layers. Any Extent declarations in the child
526 * with the same name attribute as one inherited from the parent replaces the value declared by
527 * the parent. A Layer shall not declare an Extent unless a Dimension with the same name has
528 * been declared or inherited earlier in the Capabilities XML.
529 *
530 * @return the extents
531 */
532 public Extent[] getExtent() {
533 HashMap<String, Extent> list = new HashMap<String, Extent>();
534
535 if ( parent != null ) {
536 Extent[] pEx = parent.getExtent();
537
538 for ( int i = 0; i < pEx.length; i++ ) {
539 list.put( pEx[i].getName(), pEx[i] );
540 }
541 }
542
543 for ( int i = 0; i < extent.size(); i++ ) {
544 Extent ex = extent.get( i );
545 list.put( ex.getName(), ex );
546 }
547
548 return list.values().toArray( new Extent[list.size()] );
549 }
550
551 /**
552 * adds the extent declarations
553 *
554 * @param extent
555 */
556 public void addExtent( Extent extent ) {
557 this.extent.add( extent );
558 }
559
560 /**
561 * sets the extent
562 *
563 * @param extent
564 */
565 public void setExtent( Extent[] extent ) {
566 if ( extent == null )
567 this.extent.clear();
568 else
569 this.extent = Arrays.asList( extent );
570 }
571
572 /**
573 * The optional <Attribution> element provides a way to identify the source of the map
574 * data used in a Layer or collection of Layers. Attribution encloses several optional elements:
575 * <OnlineResource>states the data provider's URL; <Title> is a human-readable string
576 * naming the data provider; <LogoURL> is the URL of a logo image. Client applications may
577 * choose to display one or more of these items. A <Format> element in LogoURL indicates
578 * the MIME type of the logo image, and the attributes width and height state the size of the
579 * image in pixels.
580 *
581 * @return the attribution
582 */
583 public Attribution getAttribution() {
584 if ( ( parent != null ) && ( attribution == null ) ) {
585 return parent.getAttribution();
586 }
587 return attribution;
588 }
589
590 /**
591 * sets the optional <Attribution> element
592 *
593 * @param attribution
594 */
595 public void setAttribution( Attribution attribution ) {
596 this.attribution = attribution;
597 }
598
599 /**
600 * The authority attribute of the Identifier element corresponds to the name attribute of a
601 * separate <AuthorityURL> element. AuthorityURL encloses an <OnlineResource>
602 * element which states the URL of a document defining the meaning of the Identifier values.
603 *
604 * @return the authority url object
605 */
606 public AuthorityURL[] getAuthorityURL() {
607 HashMap<String, AuthorityURL> list = new HashMap<String, AuthorityURL>();
608
609 if ( parent != null ) {
610 AuthorityURL[] pAu = parent.getAuthorityURL();
611
612 for ( int i = 0; i < pAu.length; i++ ) {
613 list.put( pAu[i].getName(), pAu[i] );
614 }
615 }
616
617 for ( int i = 0; i < authorityURL.size(); i++ ) {
618 AuthorityURL au = authorityURL.get( i );
619
620 if ( list.get( au.getName() ) == null ) {
621 list.put( au.getName(), au );
622 }
623 }
624
625 AuthorityURL[] aus = new AuthorityURL[list.size()];
626 return list.values().toArray( aus );
627 }
628
629 /**
630 * adds the authority attribute of the Identifier element
631 *
632 * @param authorityURL
633 */
634 public void addAuthorityURL( AuthorityURL authorityURL ) {
635 this.authorityURL.add( authorityURL );
636 }
637
638 /**
639 * sets the authority attribute of the Identifier element
640 *
641 * @param authorityURL
642 */
643 public void setAuthorityURL( AuthorityURL[] authorityURL ) {
644 if ( authorityURL == null )
645 this.authorityURL.clear();
646 else
647 this.authorityURL = Arrays.asList( authorityURL );
648 }
649
650 /**
651 * A Map Server may use zero or more <Identifier> elements to list ID numbers or labels
652 * defined by a particular Authority. The text content of the Identifier element is the ID
653 * value.
654 *
655 * @return the identifiers
656 */
657 public Identifier[] getIdentifier() {
658 HashMap<String, Identifier> list = new HashMap<String, Identifier>();
659
660 if ( parent != null ) {
661 Identifier[] pIden = parent.getIdentifier();
662
663 for ( int i = 0; i < pIden.length; i++ ) {
664 list.put( pIden[i].getAuthority(), pIden[i] );
665 }
666 }
667
668 for ( int i = 0; i < identifier.size(); i++ ) {
669 Identifier iden = identifier.get( i );
670
671 if ( list.get( iden.getAuthority() ) == null ) {
672 list.put( iden.getAuthority(), iden );
673 }
674 }
675
676 Identifier[] ids = new Identifier[list.size()];
677 return list.values().toArray( ids );
678 }
679
680 /**
681 * adds the <Identifier>
682 *
683 * @param identifier
684 */
685 public void addIdentifier( Identifier identifier ) {
686 this.identifier.add( identifier );
687 }
688
689 /**
690 * sets the <Identifier>
691 *
692 * @param identifier
693 */
694 public void setIdentifier( Identifier[] identifier ) {
695 if ( identifier == null )
696 this.identifier.clear();
697 else
698 this.identifier = Arrays.asList( identifier );
699 }
700
701 /**
702 * A Map Server should use one or more <MetadataURL> elements to offer detailed,
703 * standardized metadata about the data underneath a particular layer. The type attribute
704 * indicates the standard to which the metadata complies. Two types are defined at present: the
705 * value 'TC211' refers to [ISO 19115]; the value 'FGDC' refers to [FGDC-STD-001-1988]. The
706 * MetadataURL element shall not be used to reference metadata in a non-standardized metadata
707 * format; see DataURL instead. The enclosed <Format> element indicates the file format
708 * MIME type of the metadata record.
709 *
710 * @return the metadata urls
711 */
712 public MetadataURL[] getMetadataURL() {
713 return metadataURL.toArray( new MetadataURL[metadataURL.size()] );
714 }
715
716 /**
717 * adds the metadataURL
718 *
719 * @param metadataURL
720 */
721 public void addMetadataURL( MetadataURL metadataURL ) {
722 this.metadataURL.add( metadataURL );
723 }
724
725 /**
726 * sets the metadataURL
727 *
728 * @param metadataURL
729 */
730 public void setMetadataURL( MetadataURL[] metadataURL ) {
731 if ( metadataURL == null )
732 this.metadataURL.clear();
733 else
734 this.metadataURL = Arrays.asList( metadataURL );
735 }
736
737 /**
738 * A Map Server may use DataURL to offer more information about the data represented by a
739 * particular layer. While the semantics are not well-defined, as long as the results of an HTTP
740 * GET request against the DataURL are properly MIME-typed, Viewer Clients and Cascading Map
741 * Servers can make use of this. Use 6lt;MetadataURL> instead for a precisely defined
742 * reference to standardized metadata records.
743 *
744 * @return the data URLs
745 */
746 public DataURL[] getDataURL() {
747 return dataURL.toArray( new DataURL[dataURL.size()] );
748 }
749
750 /**
751 * adds the dataURL
752 *
753 * @param dataURL
754 */
755 public void addDataURL( DataURL dataURL ) {
756 this.dataURL.add( dataURL );
757 }
758
759 /**
760 * sets the dataURL
761 *
762 * @param dataURL
763 */
764 public void setDataURL( DataURL[] dataURL ) {
765 if ( dataURL == null )
766 this.dataURL.clear();
767 else
768 this.dataURL = Arrays.asList( dataURL );
769 }
770
771 /**
772 * A Map Server may use a <FeatureListURL> element to point to a list of the features
773 * represented in a Layer.
774 *
775 * @return the feature list urls
776 */
777 public FeatureListURL[] getFeatureListURL() {
778 return featureListURL.toArray( new FeatureListURL[featureListURL.size()] );
779 }
780
781 /**
782 * adds the <FeatureListURL>
783 *
784 * @param featureListURL
785 */
786 public void addFeatureListURL( FeatureListURL featureListURL ) {
787 this.featureListURL.add( featureListURL );
788 }
789
790 /**
791 * sets the <FeatureListURL>
792 *
793 * @param featureListURL
794 */
795 public void setFeatureListURL( FeatureListURL[] featureListURL ) {
796 if ( featureListURL == null )
797 this.featureListURL.clear();
798 else
799 this.featureListURL = Arrays.asList( featureListURL );
800 }
801
802 /**
803 * @return a list of style that can be used form rendering the layer.
804 */
805 public Style[] getStyles() {
806 HashMap<String, Style> list = new HashMap<String, Style>();
807
808 if ( parent != null ) {
809 Style[] pStyle = parent.getStyles();
810
811 for ( int i = 0; i < pStyle.length; i++ ) {
812 list.put( pStyle[i].getName(), pStyle[i] );
813 }
814 }
815
816 for ( Style style : styles.values() ) {
817 if ( list.get( style.getName() ) == null ) {
818 list.put( style.getName(), style );
819 }
820 }
821
822 return list.values().toArray( new Style[list.size()] );
823 }
824
825 /**
826 * adds a list of style that can be used form rendering the layer.
827 *
828 * @param style
829 */
830 public void addStyles( Style style ) {
831 this.styles.put( style.getName(), style );
832 }
833
834 /**
835 * sets a list of style that can be used form rendering the layer.
836 *
837 * @param styles
838 */
839 public void setStyles( Style[] styles ) {
840 if ( styles == null ) {
841 this.styles.clear();
842 } else {
843 for ( Style style : styles ) {
844 this.styles.put( style.getName(), style );
845 }
846 }
847 }
848
849 /**
850 * returns the <tt>UserStyle</tt> (SLD) representation of the style identified by the
851 * submitted name.
852 *
853 * @param name
854 * of the requested style
855 * @return SLD - UserStyle
856 *
857 */
858 public UserStyle getStyle( String name ) {
859
860 Style style = styles.get( name );
861 UserStyle us = null;
862
863 if ( style == null ) {
864 if ( parent != null ) {
865 us = parent.getStyle( name );
866 }
867 } else {
868 us = style.getStyleContent();
869 }
870
871 return us;
872 }
873
874 /**
875 * returns the <tt>Style</tt> identified by the submitted name.
876 *
877 * @param name
878 * of the requested style
879 * @return Style
880 *
881 */
882 public Style getStyleResource( String name ) {
883
884 Style style = styles.get( name );
885
886 if ( style == null && name.length() == 0 ) {
887 String tmpName = "default";
888 style = styles.get( tmpName );
889 if ( style == null && name.length() == 0 ) {
890 tmpName = "default:" + this.name;
891 style = styles.get( tmpName );
892 }
893 } else if ( style == null && "default".equals( name ) ) {
894 String tmpName = "default:" + this.name;
895 style = styles.get( tmpName );
896 }
897
898 if ( style == null ) {
899 if ( parent != null ) {
900 style = parent.getStyleResource( name );
901 }
902 }
903
904 return style;
905 }
906
907 /**
908 * Layers may include a <ScaleHint> element that suggests minimum and maximum scales for
909 * which it is appropriate to display this layer. Because WMS output is destined for output
910 * devices of arbitrary size and resolution, the usual definition of scale as the ratio of map
911 * size to real-world size is not appropriate here. The following definition of Scale Hint is
912 * recommended. Consider a hypothetical map with a given Bounding Box, width and height. The
913 * central pixel of that map (or the pixel just to the northwest of center) will have some size,
914 * which can be expressed as the ground distance in meters of the southwest to northeast
915 * diagonal of that pixel. The two values in ScaleHint are the minimum and maximum recommended
916 * values of that diagonal. It is recognized that this definition is not geodetically precise,
917 * but at the same time the hope is that by including it conventions will develop that can be
918 * later specified more clearly.
919 *
920 * @return the scale hint
921 */
922 public ScaleHint getScaleHint() {
923 if ( ( parent != null ) && ( scaleHint == null ) ) {
924 return parent.getScaleHint();
925 }
926 return scaleHint;
927 }
928
929 /**
930 * sets the <ScaleHint>
931 *
932 * @param scaleHint
933 */
934 public void setScaleHint( ScaleHint scaleHint ) {
935 this.scaleHint = scaleHint;
936 }
937
938 /**
939 * returns a list of layers the are enclosed by this layer.
940 *
941 * @return the layers
942 */
943 public Layer[] getLayer() {
944 return layer.toArray( new Layer[layer.size()] );
945 }
946
947 /**
948 * removes a Layer identified by its name from the parent Layer. A reference to the removed
949 * layer will be returned. If no Layer matching the passed name can be found nothing happens and
950 * <tt>null</tt> will be returned.
951 *
952 * @param name
953 *
954 * @return removerd Layer
955 */
956 public Layer removeLayer( String name ) {
957 for ( int i = 0; i < layer.size(); i++ ) {
958 Layer ly = layer.get( i );
959 if ( ly.getName() != null ) {
960 if ( ly.getName().equals( name ) ) {
961 layer.remove( i );
962 return ly;
963 }
964 }
965 }
966 return null;
967 }
968
969 /**
970 * removes a Layer identified by its title from the parent Layer. A reference to the removed
971 * layer will be returned. If no Layer matching the passed title can be found nothing happens
972 * and <tt>null</tt> will be returned.
973 *
974 * @param title
975 *
976 * @return removerd Layer
977 */
978 public Layer removeLayerByTitle( String title ) {
979 for ( int i = 0; i < layer.size(); i++ ) {
980 Layer ly = layer.get( i );
981 if ( ly.getTitle().equals( title ) ) {
982 layer.remove( i );
983 return ly;
984 }
985 }
986 return null;
987 }
988
989 /**
990 * adds a list of layers the are enclosed by this layer.
991 *
992 * @param layer
993 */
994 public void addLayer( Layer layer ) {
995 this.layer.add( layer );
996 }
997
998 /**
999 * sets a list of layers the are enclosed by this layer.
1000 *
1001 * @param layer
1002 */
1003 public void setLayer( Layer[] layer ) {
1004 if ( layer == null ) {
1005 this.layer.clear();
1006 } else {
1007 this.layer = new ArrayList<Layer>( Arrays.asList( layer ) );
1008 }
1009 }
1010
1011 /**
1012 * source where the WMS can find the data of a layer.
1013 *
1014 * @return the data sources
1015 */
1016 public AbstractDataSource[] getDataSource() {
1017 return dataSource.toArray( new AbstractDataSource[dataSource.size()] );
1018 }
1019
1020 /**
1021 * source where the WMS can find the data of a layer.
1022 *
1023 * @param dataSource
1024 */
1025 public void setDataSource( AbstractDataSource[] dataSource ) {
1026 if ( dataSource == null )
1027 this.dataSource.clear();
1028 else
1029 this.dataSource = Arrays.asList( dataSource );
1030 }
1031
1032 /**
1033 * source where the WMS can find the data of a layer.
1034 *
1035 * @param dataSource
1036 */
1037 public void addDataSource( AbstractDataSource dataSource ) {
1038 this.dataSource.add( dataSource );
1039 }
1040
1041 /**
1042 * @return the parent layer of this layer. If the method returns <tt>null</tt> the current
1043 * layer is the root layer. In addition with the <tt>getLayer</tt> method this enables
1044 * a program to traverse the layer tree in both directions.
1045 */
1046 public Layer getParent() {
1047 return parent;
1048 }
1049
1050 /**
1051 * sets the parent layer of this layer.
1052 *
1053 * @param parent
1054 */
1055 public void setParent( Layer parent ) {
1056 this.parent = parent;
1057 }
1058
1059 /**
1060 * @return '0' if the layer is provided directly form the deegree WMS. other it returns the
1061 * number of cascaded WMS servers the is passed through
1062 *
1063 */
1064 public int getCascaded() {
1065 return cascaded;
1066 }
1067
1068 /**
1069 * @return '0' if the WMS can resize map to arbitrary height. nonzero: map has a fixed height
1070 * that cannot be changed by the WMS.
1071 *
1072 */
1073 public int getFixedHeight() {
1074 return fixedHeight;
1075 }
1076
1077 /**
1078 * @return '0' if the WMS can resize map to arbitrary width. nonzero: map has a fixed width that
1079 * cannot be changed by the WMS.
1080 *
1081 */
1082 public int getFixedWidth() {
1083 return fixedWidth;
1084 }
1085
1086 /**
1087 * @return false if the WMS can map a subset of the full bounding box.
1088 *
1089 */
1090 public boolean hasNoSubsets() {
1091 return noSubsets;
1092 }
1093
1094 /**
1095 * @return false if map data represents vector features that probably do not completely fill
1096 * space.
1097 *
1098 */
1099 public boolean isOpaque() {
1100 return opaque;
1101 }
1102
1103 /**
1104 * @return true if the layer is queryable. That means it can be targeted by a GetFeatureInfo
1105 * request.
1106 *
1107 */
1108 public boolean isQueryable() {
1109 return queryable;
1110 }
1111
1112 }