Update to Worldwind release 0.4.0
[worldwind-tracker.git] / gov / nasa / worldwind / wms / Capabilities.java
blob048e57fb9f6c6d4a97d269ff16cf0e83ffe111ac
1 /*
2 Copyright (C) 2001, 2006 United States Government
3 as represented by the Administrator of the
4 National Aeronautics and Space Administration.
5 All Rights Reserved.
6 */
7 package gov.nasa.worldwind.wms;
9 import gov.nasa.worldwind.util.Logging;
10 import org.w3c.dom.*;
12 import javax.xml.XMLConstants;
13 import javax.xml.xpath.*;
14 import java.util.*;
15 import java.util.logging.Level;
17 /**
18 * @author tag
19 * @version $Id: Capabilities.java 3601 2007-11-21 03:23:23Z tgaskins $
21 public abstract class Capabilities
23 protected Document doc;
24 protected Element service;
25 protected Element capability;
26 protected XPath xpath;
28 public static Capabilities parse(Document doc)
30 XPathFactory xpFactory = XPathFactory.newInstance();
31 XPath xpath = xpFactory.newXPath();
33 SimpleNamespaceContext nsc = new SimpleNamespaceContext();
34 nsc.addNamespace(XMLConstants.DEFAULT_NS_PREFIX, "http://www.opengis.net/wms");
35 xpath.setNamespaceContext(new SimpleNamespaceContext());
37 try
39 String version = xpath.evaluate(altPaths("*/@wms:version"), doc);
40 if (version == null || version.length() == 0)
41 return null;
43 if (version.compareTo("1.3") < 0)
44 return new CapabilitiesV111(doc, xpath);
45 else
46 return new CapabilitiesV130(doc, xpath);
48 catch (XPathExpressionException e)
50 Logging.logger().log(Level.SEVERE, "WMS.ParsingError", e);
51 return null;
55 protected Capabilities(Document doc, XPath xpath)
57 this.doc = doc;
58 this.xpath = xpath;
60 try
62 this.service = (Element) this.xpath.evaluate(altPaths("*/wms:Service"), doc, XPathConstants.NODE);
63 if (this.service == null)
65 Logging.logger().severe("WMS.NoServiceElement");
66 throw new IllegalArgumentException(Logging.getMessage("WMS.NoServiceElement"));
69 this.capability = (Element) this.xpath.evaluate(altPaths("*/wms:Capability"), doc, XPathConstants.NODE);
70 if (this.capability == null)
72 Logging.logger().severe("WMS.NoCapabilityElement");
73 throw new IllegalArgumentException(Logging.getMessage("WMS.NoCapabilityElement"));
76 catch (XPathExpressionException e)
78 Logging.logger().log(Level.SEVERE, "WMS.ParsingError", e);
82 private static String altPaths(String path)
84 return path != null ? path + "|" + path.replaceAll("wms:", "") : null;
87 protected String getText(String path)
89 return this.getText(null, path);
92 protected String getText(Element context, String path)
94 try
96 return this.xpath.evaluate(altPaths(path), context != null ? context : doc);
98 catch (XPathExpressionException e)
100 return null;
104 protected String[] getTextArray(Element context, String path)
108 NodeList nodes = (NodeList) this.xpath.evaluate(altPaths(path), context != null ? context : doc,
109 XPathConstants.NODESET);
110 if (nodes == null || nodes.getLength() == 0)
111 return null;
113 String[] strings = new String[nodes.getLength()];
114 for (int i = 0; i < nodes.getLength(); i++)
116 strings[i] = nodes.item(i).getTextContent();
118 return strings;
120 catch (XPathExpressionException e)
122 return null;
126 protected String[] getUniqueText(Element context, String path)
128 String[] strings = this.getTextArray(context, path);
129 if (strings == null)
130 return null;
132 ArrayList<String> sarl = new ArrayList<String>();
133 for (String s : strings)
135 if (!sarl.contains(s))
136 sarl.add(s);
139 return sarl.toArray(new String[1]);
142 protected Element getElement(Element context, String path)
146 Node node = (Node) this.xpath.evaluate(altPaths(path), context != null ? context : doc,
147 XPathConstants.NODE);
148 if (node == null)
149 return null;
151 return node instanceof Element ? (Element) node : null;
153 catch (XPathExpressionException e)
155 return null;
159 protected Element[] getElements(Element context, String path)
163 NodeList nodes = (NodeList) this.xpath.evaluate(altPaths(path), context != null ? context : doc,
164 XPathConstants.NODESET);
165 if (nodes == null || nodes.getLength() == 0)
166 return null;
168 Element[] elements = new Element[nodes.getLength()];
169 for (int i = 0; i < nodes.getLength(); i++)
171 Node node = nodes.item(i);
172 if (node instanceof Element)
173 elements[i] = (Element) node;
175 return elements;
177 catch (XPathExpressionException e)
179 return null;
183 public Element[] getUniqueElements(Element context, String path, String uniqueTag)
185 Element[] elements = this.getElements(context, path);
186 if (elements == null)
187 return null;
189 HashMap<String, Element> styles = new HashMap<String, Element>();
190 for (Element e : elements)
192 String name = this.getText(e, uniqueTag);
193 if (name != null)
194 styles.put(name, e);
197 return styles.values().toArray(new Element[1]);
200 private HashMap<Element, Layer> namedLayerElements = new HashMap<Element, Layer>();
201 private HashMap<String, Layer> namedLayers = new HashMap<String, Layer>();
203 private void fillLayerList()
205 if (this.namedLayers.size() == 0)
207 Element[] nels = this.getElements(this.capability, "descendant::wms:Layer[wms:Name]");
208 if (nels == null || nels.length == 0)
209 return;
211 for (Element le : nels)
213 String name = this.getLayerName(le);
214 if (name != null)
216 Layer layer = new Layer(le);
217 this.namedLayers.put(name, layer);
218 this.namedLayerElements.put(le, layer);
224 public Element[] getNamedLayers()
226 if (this.namedLayerElements.size() == 0)
227 this.fillLayerList();
229 return this.namedLayerElements.keySet().toArray(new Element[this.namedLayerElements.size()]);
232 public Element getLayerByName(String layerName)
234 if (this.namedLayers.size() == 0)
235 this.fillLayerList();
237 Layer l = this.namedLayers.get(layerName);
238 return l != null ? l.element : null;
241 // ********* Document Items ********* //
243 public String getVersion()
245 return this.getText("*/@wms:version");
248 public String getUpdateSequence()
250 return this.getText("*/@wms:updateSequence");
253 // ********* Service Items ********* //
255 public String getAbstract()
257 return this.getText(this.service, "wms:Abstract");
260 public String getAccessConstraints()
262 return this.getText(this.service, "wms:AccessConstraints");
265 public String getContactOrganization()
267 return this.getText(
268 this.service, "wms:ContactInformation/wms:ContactPersonPrimary/wms:ContactOrganization");
271 public String getContactPerson()
273 return this.getText(
274 this.service, "wms:ContactInformation/wms:ContactPersonPrimary/wms:ContactPerson");
277 public String getFees()
279 return this.getText(this.service, "wms:Fees");
282 public String[] getKeywordList()
284 return this.getTextArray(this.service, "wms:KeywordList/wms:Keyword");
287 public String getLayerLimit()
289 return this.getText(this.service, "wms:LayerLimit");
292 public String getMaxWidth()
294 return this.getText(this.service, "wms:MaxWidth");
297 public String getMaxHeight()
299 return this.getText(this.service, "wms:MaxHeight");
302 public String getName()
304 return this.getText(this.service, "wms:Name");
307 public String getTitle()
309 return this.getText(this.service, "wms:Title");
312 // ********* Capability Items ********* //
314 public String getOnlineResource()
316 return this.getText(this.capability, "wms:OnlineResource/@xlink:href");
319 public String[] getGetCapabilitiesFormats()
321 return this.getTextArray(this.capability,
322 "wms:Request/wms:GetCapabilities/wms:Format");
325 public String getGetCapabilitiesRequestGetURL()
327 return this.getText(this.capability,
328 "wms:Request/wms:GetCapabilities/wms:DCPType/wms:HTTP/wms:Get/wms:OnlineResource/@xlink:href");
331 public String getGetCapabilitiesRequestPostURL()
333 return this.getText(this.capability,
334 "wms:Request/wms:GetCapabilities/wms:DCPType/wms:HTTP/wms:Post/wms:OnlineResource/@xlink:href");
337 public String[] getExceptionFormats()
339 return this.getTextArray(this.capability, "wms:Exception/wms:Format");
342 public String getFeatureInfoRequestGetURL()
344 return this.getText(this.capability,
345 "wms:Request/wms:GetFeatureInfo/wms:DCPType/wms:HTTP/wms:Get/wms:OnlineResource/@xlink:href");
348 public String getFeatureInfoRequestPostURL()
350 return this.getText(this.capability,
351 "wms:Request/wms:GetFeatureInfo/wms:DCPType/wms:HTTP/wms:Post/wms:OnlineResource/@xlink:href");
354 public String[] getGetMapFormats()
356 return this.getTextArray(this.capability,
357 "wms:Request/wms:GetMap/wms:Format");
360 public String getGetMapRequestGetURL()
362 return this.getText(this.capability,
363 "wms:Request/wms:GetMap/wms:DCPType/wms:HTTP/wms:Get/wms:OnlineResource/@xlink:href");
366 public String getGetMapRequestPostURL()
368 return this.getText(this.capability,
369 "wms:Request/wms:GetMap/wms:DCPType/wms:HTTP/wms:Post/wms:OnlineResource/@xlink:href");
372 public String getVendorSpecificCapabilities()
374 return this.getText(this.capability, "wms:VendorSpecificCapabilities");
377 public Element getLayer()
379 return this.getElement(this.capability, "wms:Layer");
382 // ********* Layer Items ********* //
384 protected static class Layer
386 protected HashMap<Element, Style> styleElements = new HashMap<Element, Style>();
387 protected final Element element;
388 protected Layer layer;
389 protected String name;
390 protected String title;
392 public Layer(Element element)
394 this.element = element;
398 public String getLayerAbstract(Element layer)
400 return this.getText(layer, "wms:Abstract");
403 public String getLayerAttributionTitle(Element layer)
405 return this.getText(layer, "ancestor-or-self::wms:Layer/wms:Attribution/wms:Title");
408 public String getLayerAttributionURL(Element layer)
410 return this.getText(layer, "ancestor-or-self::wms:Layer/wms:Attribution/wms:OnlineResource/@xlink:href");
413 public String getLayerAttributionLogoFormat(Element layer)
415 return this.getText(layer, "ancestor-or-self::wms:Layer/wms:Attribution/wms:LogoURL/wms:Format");
418 public String getLayerAttributionLogoHeight(Element layer)
420 return this.getText(layer, "ancestor-or-self::wms:Layer/wms:Attribution/wms:LogoURL/@wms:height");
423 public String getLayerAttributionLogoURL(Element layer)
425 return this.getText(layer,
426 "ancestor-or-self::wms:Layer/wms:Attribution/wms:LogoURL/wms:OnlineResource/@xlink:href");
429 public String getLayerAttributionLogoWidth(Element layer)
431 return this.getText(layer, "ancestor-or-self::wms:Layer/wms:Attribution/wms:LogoURL/@wms:width");
434 public Element[] getLayerAuthorityURLs(Element layer)
436 return this.getUniqueElements(layer, "ancestor-or-self::wms:Layer/wms:AuthorityURL", "@wms:type");
439 public abstract BoundingBox[] getLayerBoundingBoxes(Element layer);
441 public String getLayerCascaded(Element layer)
443 return this.getText(layer, "ancestor-or-self::wms:Layer/@cascaded");
446 public String[] getLayerCRS(Element layer)
448 return this.getUniqueText(layer, "ancestor-or-self::wms:Layer/wms:CRS");
451 public String getLayerDataURLFormat(Element layer)
453 return this.getText(layer, "wms:DataURL/wms:Format");
456 public String getLayerDataURL(Element layer)
458 return this.getText(layer, "wms:DataURL/wms:OnlineResource/@xlink:href");
461 public Element[] getLayerDimensions(Element layer)
463 Element[] dims = this.getElements(layer, "ancestor-or-self::wms:Layer/wms:Dimension");
465 if (dims == null || dims.length == 0)
466 return null;
468 ArrayList<Element> uniqueDims = new ArrayList<Element>();
469 ArrayList<String> dimNames = new ArrayList<String>();
470 for (Element e : dims)
472 // Filter out dimensions with same name.
473 // Keep all those with a null name, even though wms says they're invalid. Let the app decide.
474 String name = this.getDimensionName(e);
475 if (name != null && dimNames.contains(name))
476 continue;
478 uniqueDims.add(e);
479 dimNames.add(name);
482 return uniqueDims.toArray(new Element[uniqueDims.size()]);
485 public Element[] getLayerExtents(Element layer)
487 Element[] extents = this.getElements(layer, "ancestor-or-self::wms:Layer/wms:Extent");
489 if (extents == null || extents.length == 0)
490 return null;
492 ArrayList<Element> uniqueExtents = new ArrayList<Element>();
493 ArrayList<String> extentNames = new ArrayList<String>();
494 for (Element e : extents)
496 // Filter out dimensions with same name.
497 // Keep all those with a null name, even though wms says they're invalid. Let the app decide.
498 String name = this.getDimensionName(e);
499 if (name != null && extentNames.contains(name))
500 continue;
502 uniqueExtents.add(e);
503 extentNames.add(name);
506 return uniqueExtents.toArray(new Element[uniqueExtents.size()]);
509 public abstract BoundingBox getLayerGeographicBoundingBox(Element layer);
511 public String getLayerFeatureListFormat(Element layer)
513 return this.getText(layer, "wms:FeatureListURL/wms:Format");
516 public String getLayerFeatureListURL(Element layer)
518 return this.getText(layer, "wms:FeatureListURL/wms:OnlineResource/@xlink:href");
521 public String getLayerFixedHeight(Element layer)
523 return this.getText(layer, "ancestor-or-self::wms:Layer/@fixedHeight");
526 public String getLayerFixedWidth(Element layer)
528 return this.getText(layer, "ancestor-or-self::wms:Layer/@fixedWidth");
531 public Element[] getLayerIdentifiers(Element layer)
533 return this.getUniqueElements(layer, "wms:Identifier", "wms:authority");
536 public String[] getLayerKeywordList(Element layer)
538 return this.getTextArray(layer, "wms:KeywordList/wms:Keyword");
541 public abstract String getLayerMaxScaleDenominator(Element layer);
543 public Element[] getLayerMetadataURLs(Element layer)
545 return this.getElements(layer, "wms:MetadataURL");
548 public abstract String getLayerMinScaleDenominator(Element layer);
550 public String getLayerName(Element layerElement)
552 Layer layer = this.namedLayerElements.get(layerElement);
553 return layer != null && layer.name != null ? layer.name : this.getText(layerElement, "wms:Name");
556 public String getLayerNoSubsets(Element layer)
558 return this.getText(layer, "ancestor-or-self::wms:Layer/@noSubsets");
561 public String getLayerOpaque(Element layer)
563 return this.getText(layer, "ancestor-or-self::wms:Layer/@opaque");
566 public String getLayerQueryable(Element layer)
568 return this.getText(layer, "ancestor-or-self::wms:Layer/@queryable");
571 public String[] getLayerSRS(Element layer)
573 return this.getUniqueText(layer, "ancestor-or-self::wms:Layer/wms:SRS");
576 public Element[] getLayerStyles(Element layerElement)
578 Layer layer = this.namedLayerElements.get(layerElement);
579 if (layer == null)
580 return null;
582 if (layer.styleElements != null)
583 return layer.styleElements.keySet().toArray(new Element[1]);
585 Element[] styleElements = this.getUniqueElements(layerElement, "ancestor-or-self::wms:Layer/wms:Style", "Name");
586 if (styleElements == null)
587 return null;
589 layer.styleElements = new HashMap<Element, Style>();
590 for (Element se : styleElements)
592 Style style = new Style(se, layer);
593 layer.styleElements.put(se, style);
594 this.styleElements.put(se, style);
597 return layer.styleElements.keySet().toArray(new Element[1]);
600 public Element[] getLayerSubLayers(Element layer)
602 return this.getElements(layer, "wms:Layer");
605 public String getLayerTitle(Element layerElement)
607 Layer layer = this.namedLayerElements.get(layerElement);
608 if (layer == null)
609 return null;
611 return layer.title != null ? layer.title : (layer.title = this.getText(layerElement, "wms:Title"));
614 public Element getLayerStyleByName(Element layerElement, String styleName)
616 Layer layer = this.namedLayerElements.get(layerElement);
617 if (layer == null)
618 return null;
620 if (layer.styleElements == null || layer.styleElements.size() == 0)
622 // Initialize the layer's style list.
623 this.getLayerStyles(layerElement);
624 if (layer.styleElements == null || layer.styleElements.size() == 0)
625 return null;
628 Collection<Style> styles = layer.styleElements.values();
629 for (Style s : styles)
631 if (s != null && s.equals(styleName))
632 return s.element;
635 return null;
638 // ********* Style Items ********* //
640 protected HashMap<Element, Style> styleElements = new HashMap<Element, Style>();
642 protected static class Style
644 protected final Layer layer;
645 protected final Element element;
646 protected String name;
647 protected String title;
649 public Style(Element element, Layer layer)
651 this.element = element;
652 this.layer = layer;
656 public String getStyleAbstract(Element styleElement)
658 return this.getText(styleElement, "wms:Abstract");
661 public String getStyleLegendFormat(Element styleElement)
663 return this.getText(styleElement, "wms:LegendURL/wms:Format");
666 public String getStyleLegendHeight(Element styleElement)
668 return this.getText(styleElement, "wms:LegendURL/@height");
671 public String getStyleLegendURL(Element styleElement)
673 return this.getText(styleElement, "wms:LegendURL/wms:OnlineResource/@xlink:href");
676 public String getStyleLegendWidth(Element styleElement)
678 return this.getText(styleElement, "wms:LegendURL/@width");
681 public String getStyleName(Element styleElement)
683 Style style = this.styleElements.get(styleElement);
684 return style != null && style.title != null ? style.title : this.getText(styleElement, "wms:Name");
687 public String getStyleName(Element layerElement, Element styleElement)
689 Layer layer = this.namedLayerElements.get(layerElement);
690 if (layer == null || layer.styleElements == null)
691 return this.getStyleName(layerElement, styleElement);
693 Style style = layer.styleElements.get(styleElement);
695 return style != null && style.name != null ? style.title : this.getText(styleElement, "wms:Name");
698 public String getStyleSheetURLFormat(Element styleElement)
700 return this.getText(styleElement, "wms:StyleSheetURL/wms:Format");
703 public String getStyleSheetURL(Element styleElement)
705 return this.getText(styleElement, "wms:StyleSheetURL/wms:OnlineResource/@xlink:href");
708 public String getStyleTitle(Element styleElement)
710 Style style = this.styleElements.get(styleElement);
711 return style != null && style.title != null ? style.title : this.getText(styleElement, "wms:Title");
714 public String getStyleTitle(Element layerElement, Element styleElement)
716 Layer layer = this.namedLayerElements.get(layerElement);
717 if (layer == null || layer.styleElements == null)
718 return this.getStyleTitle(styleElement);
720 Style style = this.styleElements.get(styleElement);
721 return style != null && style.title != null ? style.title : this.getText(styleElement, "wms:Title");
724 public String getStyleURL(Element styleElement)
726 return this.getText(styleElement, "wms:StyleURL/wms:OnlineResource/@xlink:href");
729 public String getStyleURLFormat(Element styleElement)
731 return this.getText(styleElement, "wms:StyleURL/wms:Format");
734 // ********* Authority Items ********* //
736 public String getAuthorityName(Element authority)
738 return this.getText(authority, "@wms:name");
741 public String getAuthorityURL(Element authority)
743 return this.getText(authority, "wms:OnlineResource/@xlink:href");
746 // ********* Identifier Items ********* //
748 public String getIdentifier(Element identifier)
750 return this.getText(identifier, ".");
753 public String getIdentifierAuthority(Element identifier)
755 return this.getText(identifier, "@wms:authority");
758 // ********* Metadata Items ********* //
760 public String getMetadataFormat(Element metadata)
762 return this.getText(metadata, "wms:Format");
765 public String getMetadataURL(Element metadata)
767 return this.getText(metadata, "wms:OnlineResource/@xlink:href");
770 public String getMetadataType(Element metadata)
772 return this.getText(metadata, "@wms:type");
775 // ********* EX_GeographicBoundingBox Items ********* //
777 public String getWestBoundLongitude(Element bbox)
779 return this.getText(bbox, "wms:westBoundLongitude");
782 public String getEastBoundLongitude(Element bbox)
784 return this.getText(bbox, "wms:eastBoundLongitude");
787 public String getSouthBoundLatitude(Element bbox)
789 return this.getText(bbox, "wms:southBoundLatitude");
792 public String getNorthBoundLatitude(Element bbox)
794 return this.getText(bbox, "wms:northBoundLatitude");
797 // ********* BoundingBox Items ********* //
799 public String getBoundingBoxCRS(Element bbox)
801 return this.getText(bbox, "@wms:CRS");
804 public String getBoundingBoxMinx(Element bbox)
806 return this.getText(bbox, "@wms:minx");
809 public String getBoundingBoxMiny(Element bbox)
811 return this.getText(bbox, "@wms:miny");
814 public String getBoundingBoxMaxx(Element bbox)
816 return this.getText(bbox, "@wms:maxx");
819 public String getBoundingBoxMaxy(Element bbox)
821 return this.getText(bbox, "@wms:maxy");
824 public String getBoundingBoxResx(Element bbox)
826 return this.getText(bbox, "@wms:resx");
829 public String getBoundingBoxResy(Element bbox)
831 return this.getText(bbox, "@wms:resy");
834 public String getBoundingBoxSRS(Element bbox)
836 return this.getText(bbox, "@wms:SRS");
839 // ********* Dimension Items ********* //
841 public String getDimensionName(Element dimension)
843 return this.getText(dimension, "@wms:name");
846 public String getDimensionUnits(Element dimension)
848 return this.getText(dimension, "@wms:units");
851 public String getDimensionUnitSymbol(Element dimension)
853 return this.getText(dimension, "@wms:unitSymbol");
856 public String getDimensionDefault(Element dimension)
858 return this.getText(dimension, "@wms:default");
861 public String getDimensionMultipleValues(Element dimension)
863 return this.getText(dimension, "@wms:multipleValues");
866 public String getDimensionNearestValue(Element dimension)
868 return this.getText(dimension, "@wms:nearestValue");
871 public String getDimensionCurrent(Element dimension)
873 return this.getText(dimension, "@wms:current");
876 public String getDimensionExtent(Element dimension)
878 return this.getText(dimension, ".");
881 // ********* Extent Items, wms 1.1 only ********* //
883 public String getExtentName(Element dimension)
885 return this.getText(dimension, "@wms:name");
888 public String getExtentDefault(Element dimension)
890 return this.getText(dimension, "@wms:default");
893 public String getExtentMultipleValues(Element dimension)
895 return this.getText(dimension, "@wms:multipleValues");
898 public String getExtentNearestValue(Element dimension)
900 return this.getText(dimension, "@wms:nearestValue");
903 public String getExtentCurrent(Element dimension)
905 return this.getText(dimension, "@wms:current");
908 public String getExtentText(Element dimension)
910 return this.getText(dimension, ".");