001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/ogcwebservices/wms/capabilities/Layer.java $ 002 /*---------------- FILE HEADER ------------------------------------------ 003 004 This file is part of deegree. 005 Copyright (C) 2001-2006 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: aschmitz $ 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 } 1113 /*************************************************************************************************** 1114 * Changes to this class. What the people have been up to: $Log$ Revision 1.19 2006/09/29 15:27:43 1115 * poth bug fix - getting styles 1116 * 1117 * Revision 1.18 2006/09/22 11:37:24 mays getStyle method enhanced 1118 * 1119 * Revision 1.17 2006/09/18 08:33:10 poth bug fix - use List implementation that supports remove 1120 * operation for storing layers 1121 * 1122 * Revision 1.16 2006/09/08 08:42:02 schmitz Updated the WMS to be 1.1.1 conformant once again. 1123 * Cleaned up the WMS code. Added cite WMS test data. 1124 * 1125 * Revision 1.15 2006/08/01 19:37:49 poth comments added 1126 * 1127 * Revision 1.14 2006/07/12 14:46:18 poth comment footer added 1128 * 1129 **************************************************************************************************/