All Downloads are FREE. Search and download functionalities are using the official Maven repository.

gov.nasa.worldwind.ogc.wms.WMSCapabilities Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2012 United States Government as represented by the Administrator of the
 * National Aeronautics and Space Administration.
 * All Rights Reserved.
 */

package gov.nasa.worldwind.ogc.wms;

import gov.nasa.worldwind.ogc.*;
import gov.nasa.worldwind.util.*;
import gov.nasa.worldwind.util.xml.*;
import gov.nasa.worldwind.wms.CapabilitiesRequest;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.XMLEvent;
import java.net.*;
import java.text.*;
import java.util.*;

/**
 * @author tag
 * @version $Id: WMSCapabilities.java 2072 2014-06-21 21:20:25Z tgaskins $
 */
public class WMSCapabilities extends OGCCapabilities
{
    protected static final QName ROOT_ELEMENT_NAME_1_1_1 = new QName("WMT_MS_Capabilities");
    protected static final QName ROOT_ELEMENT_NAME_1_3_0 = new QName("WMS_Capabilities");

    /**
     * Retrieves the WMS capabilities document from a specified WMS server.
     *
     * @param uri The URI of the server.
     *
     * @return The WMS capabilities document for the specified server.
     *
     * @throws IllegalArgumentException if the specified URI is invalid.
     * @throws gov.nasa.worldwind.exception.WWRuntimeException
     *                                  if an error occurs retrieving the document.
     */
    public static WMSCapabilities retrieve(URI uri) throws Exception
    {
        try
        {
            CapabilitiesRequest request = new CapabilitiesRequest(uri);

            return new WMSCapabilities(request);
        }
        catch (URISyntaxException e)
        {
            e.printStackTrace();
        }
        catch (MalformedURLException e)
        {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * Parses a WMS capabilities document.
     *
     * @param docSource the XML source. May be a filename, file, stream or other type allowed by {@link
     *                  gov.nasa.worldwind.util.WWXML#openEventReader(Object)}.
     *
     * @throws IllegalArgumentException if the document source is null.
     */
    public WMSCapabilities(Object docSource)
    {
        super(OGCConstants.WMS_NAMESPACE_URI, docSource);

        this.initialize();
    }

    public WMSCapabilities(CapabilitiesRequest docSource) throws URISyntaxException, MalformedURLException
    {
        super(OGCConstants.WMS_NAMESPACE_URI, docSource.getUri().toURL());

        this.initialize();
    }

    private void initialize()
    {
        this.getParserContext().registerParser(new QName(this.getDefaultNamespaceURI(), "Service"),
            new WMSServiceInformation(this.getNamespaceURI()));
        this.getParserContext().registerParser(new QName("Capability"),
            new WMSCapabilityInformation(this.getNamespaceURI()));
    }

    @Override
    public String getDefaultNamespaceURI()
    {
        return OGCConstants.WMS_NAMESPACE_URI;
    }

    public boolean isRootElementName(QName candidate)
    {
        return this.getParserContext().isSameName(candidate, ROOT_ELEMENT_NAME_1_1_1)
            || this.getParserContext().isSameName(candidate, ROOT_ELEMENT_NAME_1_3_0);
    }

    public XMLEventParser allocate(XMLEventParserContext ctx, XMLEvent event)
    {
        if (ctx.isStartElement(event, CAPABILITY))
            return ctx.allocate(event, new WMSCapabilityInformation(this.getNamespaceURI()));
        else
            return super.allocate(ctx, event);
    }

    @Override
    public WMSCapabilities parse(Object... args) throws XMLStreamException
    {
        return (WMSCapabilities) super.parse(args);
    }

    /**
     * Returns all named layers in the capabilities document.
     *
     * @return an unordered list of the document's named layers.
     */
    public List getNamedLayers()
    {
        if (this.getCapabilityInformation() == null || this.getCapabilityInformation().getLayerCapabilities() == null)
            return null;

        List namedLayers = new ArrayList();

        for (WMSLayerCapabilities layer : this.getCapabilityInformation().getLayerCapabilities())
        {
            namedLayers.addAll(layer.getNamedLayers());
        }

        return namedLayers;
    }

    public WMSLayerCapabilities getLayerByName(String name)
    {
        if (WWUtil.isEmpty(name))
            return null;

        List namedLayers = this.getNamedLayers();
        for (WMSLayerCapabilities layer : namedLayers)
        {
            if (layer.getName().equals(name))
                return layer;
        }

        return null;
    }

    public WMSCapabilityInformation getCapabilityInformation()
    {
        return (WMSCapabilityInformation) super.getCapabilityInformation();
    }

    public Set getImageFormats()
    {
        Set requestDescriptions = this.getCapabilityInformation().getRequestDescriptions();
        for (OGCRequestDescription rd : requestDescriptions)
        {
            if (rd.getRequestName().equals("GetMap"))
                return rd.getFormats();
        }

        return null;
    }

    public Long getLayerLatestLastUpdateTime(String[] layerNames)
    {
        if (layerNames == null)
        {
            String message = Logging.getMessage("nullValue.WMSLayerNames");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        String lastUpdate = null;

        for (String name : layerNames)
        {
            WMSLayerCapabilities layer = this.getLayerByName(name);
            if (layer == null)
                continue;

            String update = this.getLayerLastUpdate(layer);
            if (update != null && update.length() > 0 && (lastUpdate == null || update.compareTo(lastUpdate) > 0))
                lastUpdate = update;
        }

        if (lastUpdate != null)
        {
            try
            {
                return Long.parseLong(lastUpdate);
            }
            catch (NumberFormatException e)
            {
                String message = Logging.getMessage("generic.ConversionError", lastUpdate);
                Logging.logger().warning(message);
            }
        }

        return null;
    }

    /**
     * Checks the WMS layer capabilities for a LastUpdate entry, either an explicit element by that name or a layer
     * keyword.
     *
     * @param layerCaps The layer's capabilities taken from the server's capabilities document.
     *
     * @return A string representation of the epoch time for the last update string, if any, otherwise null.
     */
    protected String getLayerLastUpdate(WMSLayerCapabilities layerCaps)
    {
        // See if there's an explicit element. This is what the original WW servers contained in their caps docs.
        String update = layerCaps.getLastUpdate();
        if (update != null)
            return update;

        // See if there's a last-update keyword. This is the new mechanism for WW servers passing a last-update.
        Set keywords = layerCaps.getKeywords();
        for (String keyword : keywords)
        {
            if (keyword.startsWith("LastUpdate="))
            {
                return parseLastUpdate(keyword);
            }
        }

        return null;
    }

    /**
     * Parse a LastUpdate string.
     *
     * @param lastUpdateString The string containing the LastUpdate string in the format "LastUpdate=yyyy-MM-dd'T'HH:mm:ssZ"
     *
     * @return A string representation of the epoch time for the last update string, of null if the string can't be
     *         parsed as a date.
     */
    protected String parseLastUpdate(String lastUpdateString)
    {
        String[] splitKeyword = lastUpdateString.split("=");
        if (splitKeyword.length != 2)
            return null;

        String dateString = splitKeyword[1];
        if (dateString == null || dateString.length() == 0)
            return null;

        try
        {
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); // ISO 8601:2000 format
            dateString = dateString.replaceAll("Z", "-0000"); // replace the UTC designator
            return Long.toString(dateFormat.parse(dateString).getTime());
        }
        catch (ParseException e)
        {
            String message = Logging.getMessage("WMS.LastUpdateFormatUnrecognized", dateString);
            Logging.logger().info(message);
            return null;
        }
    }

    public Double[] getLayerExtremeElevations(String[] layerNames)
    {
        if (layerNames == null)
        {
            String message = Logging.getMessage("nullValue.WMSLayerNames");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        Double extremeMin = null;
        Double extremeMax = null;

        for (String name : layerNames)
        {
            WMSLayerCapabilities layer = this.getLayerByName(name);
            if (layer == null)
                continue;

            Double min = layer.getExtremeElevationMin();
            if (min != null && (extremeMin == null || min.compareTo(min) > 0))
                extremeMin = min;

            Double max = layer.getExtremeElevationMax();
            if (max != null && (extremeMax == null || max.compareTo(max) > 0))
                extremeMax = max;
        }

        if (extremeMin != null || extremeMax != null)
        {
            Double[] extremes = new Double[] {null, null};

            if (extremeMin != null)
                extremes[0] = extremeMin;
            if (extremeMax != null)
                extremes[1] = extremeMax;

            return extremes;
        }

        return null;
    }

    public OGCRequestDescription getRequestDescription(String requestName)
    {
        for (OGCRequestDescription rd : this.getCapabilityInformation().getRequestDescriptions())
        {
            if (rd.getRequestName().equalsIgnoreCase(requestName))
                return rd;
        }

        return null;
    }

    public String getRequestURL(String requestName, String protocol, String requestMethod)
    {
        OGCRequestDescription rd = this.getRequestDescription(requestName);
        if (rd != null)
        {
            OGCOnlineResource ol = rd.getOnlineResouce(protocol, requestMethod);
            return ol != null ? ol.getHref() : null;
        }

        return null;
    }

    /**
     * Indicates whether the layers corresponding to a specified list of layer names support a specified coordinate
     * system. If any of the named layers are not in this capabilities document, false is returned.
     *
     * @param layerNames The names of the layers to check.
     * @param coordSys   The coordinate system to search for, e.g., "EPSG:4326".
     *
     * @return true if all the layers support the specified coordinate system, otherwise false.
     *
     * @throws IllegalArgumentException if the layer names array is null or empty or the specified coordinate system is
     *                                  null or the empty string.
     */
    public boolean layerHasCoordinateSystem(String[] layerNames, String coordSys)
    {
        if (layerNames == null || layerNames.length == 0)
        {
            String message = Logging.getMessage("nullValue.WMSLayerNames");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        if (WWUtil.isEmpty(coordSys))
        {
            String message = Logging.getMessage("nullValue.WMSCoordSys");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        for (String name : layerNames)
        {
            WMSLayerCapabilities layerCaps = this.getLayerByName(name);
            if (layerCaps == null || !layerCaps.hasCoordinateSystem(coordSys))
                return false;
        }

        return true;
    }

    @Override
    public String toString() // TODO: Complete this method
    {
        StringBuilder sb = new StringBuilder(super.toString());

        sb.append("LAYERS\n");

        for (WMSLayerCapabilities layerCaps : this.getNamedLayers())
        {
            sb.append(layerCaps.toString()).append("\n");
        }

        return sb.toString();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy