Source: ogc/wms/WmsCapabilities.js

/*
 * Copyright 2003-2006, 2009, 2017, United States Government, as represented by the Administrator of the
 * National Aeronautics and Space Administration. All rights reserved.
 *
 * The NASAWorldWind/WebWorldWind platform is licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/**
 * @exports WmsCapabilities
 */
define([
        '../../error/ArgumentError',
        '../../util/Logger',
        '../../ogc/wms/WmsLayerCapabilities'
    ],
    function (ArgumentError,
              Logger,
              WmsLayerCapabilities) {
        "use strict";

        /**
         * Constructs an WMS Capabilities instance from an XML DOM.
         * @alias WMSCapabilities
         * @constructor
         * @classdesc Represents a WMS Capabilities document. This object holds as properties all the fields
         * specified in the given WMS Capabilities document. Most fields can be accessed as properties named
         * according to their document names converted to camel case. For example, "version", "service.title",
         * "service.contactInformation.contactPersonPrimary". The exceptions are online resources, whose property
         * path has been shortened. For example "capability.request.getMap.formats" and "capability.request.getMap.getUrl".
         * @param {{}} xmlDom An XML DOM representing the WMS Capabilities document.
         * @throws {ArgumentError} If the specified XML DOM is null or undefined.
         */
        var WmsCapabilities = function (xmlDom) {
            if (!xmlDom) {
                throw new ArgumentError(
                    Logger.logMessage(Logger.LEVEL_SEVERE, "WmsCapabilities", "constructor", "No XML DOM specified."));
            }

            this.assembleDocument(xmlDom);
        };

        /**
         * Finds all named layers documented in this WMS capabilities document. Will recursively search sub-layers for
         * named layers.
         * @returns {WmsLayerCapabilities[]}
         */
        WmsCapabilities.prototype.getNamedLayers = function () {
            return this.accumulateNamedLayers(this.capability.layers);
        };

        WmsCapabilities.prototype.accumulateNamedLayers = function (startLayers, namedLayersArray) {
            var namedLayers = namedLayersArray || [];
            
            if (!startLayers) {
                return namedLayers;
            }

            for (var i = 0, len = startLayers.length; i < len; i++) {
                var layer = startLayers[i];
                if (layer.name) {
                    namedLayers.push(layer);
                }
                if (layer.layers) {
                    this.accumulateNamedLayers(layer.layers, namedLayers);
                }
            }

            return namedLayers;
        };

        /**
         * Searches for a named layer matching the provided name and returns the WmsLayerCapabilities object representing 
         * the named layer.
         * @param {String} name the layer name to find
         * @returns {WmsLayerCapabilities} if a matching named layer is found or null
         * @throws {ArgumentError} If the specified name is null or empty.
         */
        WmsCapabilities.prototype.getNamedLayer = function (name) {
            if (!name || (name.length === 0)) {
                throw new ArgumentError(
                    Logger.logMessage(Logger.LEVEL_SEVERE, "WmsCapabilities", "getNamedLayer", "No WMS layer name provided."));
            }

            var namedLayers = this.getNamedLayers();

            for (var i = 0, len = namedLayers.length; i < len; i++) {
                if (name === namedLayers[i].name) {
                    return namedLayers[i];
                }
            }

            return null;
        };

        WmsCapabilities.prototype.assembleDocument = function (dom) {
            var root = dom.documentElement;

            this.version = root.getAttribute("version");
            this.updateSequence = root.getAttribute("updateSequence");

            var children = root.children || root.childNodes;
            for (var c = 0; c < children.length; c++) {
                var child = children[c];

                if (child.localName === "Service") {
                    this.service = this.assembleService(child);
                } else if (child.localName === "Capability") {
                    this.capability = this.assembleCapability(child);
                }
            }
        };

        WmsCapabilities.prototype.assembleService = function (element) {
            var service = {
                capsDoc: this
            };

            var children = element.children || element.childNodes;
            for (var c = 0; c < children.length; c++) {
                var child = children[c];

                if (child.localName === "Name") {
                    service.name = child.textContent;
                } else if (child.localName === "Title") {
                    service.title = child.textContent;
                } else if (child.localName === "Abstract") {
                    service.abstract = child.textContent;
                } else if (child.localName === "KeywordList") {
                    service.keywordList = this.assembleKeywordList(child);
                } else if (child.localName === "OnlineResource") {
                    service.url = child.getAttribute("xlink:href");
                } else if (child.localName === "Fees") {
                    service.fees = child.textContent;
                } else if (child.localName === "AccessConstraints") {
                    service.accessConstraints = child.textContent;
                } else if (child.localName == "LayerLimit") {
                    service.layerLimit = parseInt(child.textContent);
                } else if (child.localName == "MaxWidth") {
                    service.maxWidth = parseInt(child.textContent);
                } else if (child.localName == "MaxHeight") {
                    service.maxHeight = parseInt(child.textContent);
                } else if (child.localName === "ContactInformation") {
                    service.contactInformation = this.assembleContactInformation(child);
                }
            }

            return service;
        };

        WmsCapabilities.prototype.assembleKeywordList = function (element) {
            var keywords = [];

            var children = element.children || element.childNodes;
            for (var c = 0; c < children.length; c++) {
                var child = children[c];

                if (child.localName === "Keyword") {
                    keywords.push(child.textContent);
                }
            }

            return keywords;
        };

        WmsCapabilities.prototype.assembleContactInformation = function (element) {
            var contactInfo = {};

            var children = element.children || element.childNodes;
            for (var c = 0; c < children.length; c++) {
                var child = children[c];

                if (child.localName === "ContactPersonPrimary") {
                    contactInfo.contactPersonPrimary = this.assembleContactPersonPrimary(child);
                } else if (child.localName === "ContactPosition") {
                    contactInfo.contactPosition = child.textContent;
                } else if (child.localName === "ContactVoiceTelephone") {
                    contactInfo.contactVoiceTelephone = child.textContent;
                } else if (child.localName === "ContactFacsimileTelephone") {
                    contactInfo.contactFacsimileTelephone = child.textContent;
                } else if (child.localName === "ContactElectronicMailAddress") {
                    contactInfo.contactElectronicMailAddress = child.textContent;
                } else if (child.localName === "ContactAddress") {
                    contactInfo.contactAddress = this.assembleContactAddress(child);
                }
            }

            return contactInfo;
        };

        WmsCapabilities.prototype.assembleContactPersonPrimary = function (element) {
            var info = {};

            var children = element.children || element.childNodes;
            for (var c = 0; c < children.length; c++) {
                var child = children[c];

                if (child.localName === "ContactPerson") {
                    info.contactPerson = child.textContent;
                } else if (child.localName === "ContactOrganization") {
                    info.contactOrganization = child.textContent;
                }
            }

            return info;
        };

        WmsCapabilities.prototype.assembleContactAddress = function (element) {
            var address = {};

            var children = element.children || element.childNodes;
            for (var c = 0; c < children.length; c++) {
                var child = children[c];

                if (child.localName === "AddressType") {
                    address.addressType = child.textContent;
                } else if (child.localName === "Address") {
                    address.address = child.textContent;
                } else if (child.localName === "City") {
                    address.city = child.textContent;
                } else if (child.localName === "StateOrProvince") {
                    address.stateOrProvince = child.textContent;
                } else if (child.localName === "PostCode") {
                    address.postCode = child.textContent;
                } else if (child.localName === "Country") {
                    address.country = child.textContent;
                }
            }

            return address;
        };

        WmsCapabilities.prototype.assembleCapability = function (element) {
            var capability = {
                capsDoc: this
            };

            var children = element.children || element.childNodes;
            for (var c = 0; c < children.length; c++) {
                var child = children[c];

                if (child.localName === "Request") {
                    capability.request = this.assembleRequests(child);
                } else if (child.localName === "Exception") {
                    capability.exception = this.assembleException(child);
                } else if (child.localName === "Layer") {
                    capability.layers = capability.layers || [];
                    capability.layers.push(new WmsLayerCapabilities(child, capability));
                }
            }

            return capability;
        };

        WmsCapabilities.prototype.assembleRequests = function (element) {
            var requests = {};

            var children = element.children || element.childNodes;
            for (var c = 0; c < children.length; c++) {
                var child = children[c];

                if (child.localName === "GetCapabilities") {
                    requests.getCapabilities = this.assembleRequest(child);
                } else if (child.localName === "GetMap") {
                    requests.getMap = this.assembleRequest(child);
                } else if (child.localName === "GetFeatureInfo") {
                    requests.getFeatureInfo = this.assembleRequest(child);
                }
            }

            return requests;
        };

        WmsCapabilities.prototype.assembleRequest = function (element) {
            var request = {
                name: element.localName
            };

            var children = element.children || element.childNodes;
            for (var c = 0; c < children.length; c++) {
                var child = children[c];

                if (child.localName === "Format") {
                    request.formats = request.formats || [];
                    request.formats.push(child.textContent);
                } else if (child.localName === "DCPType") {
                    var children2 = child.children || child.childNodes;
                    for (var c2 = 0; c2 < children2.length; c2++) {
                        var child2 = children2[c2];
                        if (child2.localName === "HTTP") {
                            var children3 = child2.children || child2.childNodes;
                            for (var c3 = 0; c3 < children3.length; c3++) {
                                var child3 = children3[c3];
                                if (child3.localName === "Get") {
                                    var children4 = child3.children || child3.childNodes;
                                    for (var c4 = 0; c4 < children4.length; c4++) {
                                        var child4 = children4[c4];
                                        if (child4.localName === "OnlineResource") {
                                            request.getUrl = child4.getAttribute("xlink:href");
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            return request;
        };

        WmsCapabilities.prototype.assembleException = function (element) {
            var exception = {};

            var children = element.children || element.childNodes;
            for (var c = 0; c < children.length; c++) {
                var child = children[c];

                if (child.localName === "Format") {
                    exception.formats = exception.formats || [];
                    exception.formats.push(child.textContent);
                }
            }

            return exception;
        };

        return WmsCapabilities;
    });