service/OGC/WMTSCapabilities.js Source
import {
  Zondy
} from '../common/Base';
import {
  boundingExtent
} from './util/extent';
import OWS from './util/OWS';
import {
  readHref
} from './util/XLink';
import XML from './util/XML';
import {
  readString,
  readNonNegativeInteger,
  readDecimal
} from './util/xsd';
import {
  pushParseAndPop,
  makeStructureNS,
  makeObjectPropertySetter,
  makeObjectPropertyPusher,
  makeArrayPusher
} from './util/base/xml';

/**
 * @private
 * @const NAMESPACE_URIS 命名空间标识符
 * @type {Array<null|string>}
 */
const NAMESPACE_URIS = [
  null,
  'http://www.opengis.net/wmts/1.0'
];

/**
 * @private
 * @const OWS_NAMESPACE_URIS OWS命名空间标识符
 * @type {Array<null|string>}
 */
const OWS_NAMESPACE_URIS = [
  null,
  'http://www.opengis.net/ows/1.1'
];

/**
 * @private
 * @const PARSERS
 * @type {Object<string, Object<string>>}
 */
const PARSERS = makeStructureNS(
  NAMESPACE_URIS, {
    'Contents': makeObjectPropertySetter(readContents)
  });

/**
 * @author 基础平台/产品2部 龚跃健
 * @class Zondy.Format.WMTSCapabilities
 * @classdesc  用于读取WMTS capabilities数据的类
 * @extends  Zondy.Format.XML
 * @example
 * var parser = new Zondy.Format.WMTSCapabilities();
 * var result = parser.read(doc);
 */
class WMTSCapabilities extends XML {
  constructor() {
    super();

      /**
       * @private
       * @member Zondy.Format.WMTSCapabilities.prototype.owsParser_
       * @type {OWS}
       */
    this.owsParser_ = new OWS();
  }

    /**
     * @private
     * @function Zondy.Format.WMTSCapabilities.prototype.readFromDocument
     * @description 从文档中读取信息,继承于父类XML
     * @return {WMTSCapabilityObject|null}
     */
  readFromDocument(doc) {
    for (let n = doc.firstChild; n; n = n.nextSibling) {
      if (n.nodeType == Node.ELEMENT_NODE) {
        return this.readFromNode(n);
      }
    }
    return null;
  }

    /**
     * @private
     * @function Zondy.Format.WMTSCapabilities.prototype.readFromNode
     * @description 从文档节点中读取信息,继承于父类XML
     * @return {WMTSCapabilityObject|null}
     */
  readFromNode(node) {
    const version = node.getAttribute('version').trim();
    let WMTSCapabilityObject = this.owsParser_.readFromNode(node);
    if (!WMTSCapabilityObject) {
      return null;
    }
    WMTSCapabilityObject['version'] = version;
    WMTSCapabilityObject = pushParseAndPop(WMTSCapabilityObject, PARSERS, node, []);
    return WMTSCapabilityObject ? WMTSCapabilityObject : null;
  }
}

/**
 * @private
 * @const CONTENTS_PARSERS
 * @type {Object<string, Object<string>>}
 */
const CONTENTS_PARSERS = makeStructureNS(
  NAMESPACE_URIS, {
    'Layer': makeObjectPropertyPusher(readLayer),
    'TileMatrixSet': makeObjectPropertyPusher(readTileMatrixSet)
  });

/**
 * @private
 * @const LAYER_PARSERS
 * @type {Object<string, Object<string>>}
 */
const LAYER_PARSERS = makeStructureNS(
  NAMESPACE_URIS, {
    'Style': makeObjectPropertyPusher(readStyle),
    'Format': makeObjectPropertyPusher(readString),
    'TileMatrixSetLink': makeObjectPropertyPusher(readTileMatrixSetLink),
    'Dimension': makeObjectPropertyPusher(readDimensions),
    'ResourceURL': makeObjectPropertyPusher(readResourceUrl)
  }, makeStructureNS(OWS_NAMESPACE_URIS, {
    'Title': makeObjectPropertySetter(readString),
    'Abstract': makeObjectPropertySetter(readString),
    'BoundingBox': makeObjectPropertySetter(readBoundingBox),
    'WGS84BoundingBox': makeObjectPropertySetter(readBoundingBox),
    'Identifier': makeObjectPropertySetter(readString)
  }));

/**
 * @private
 * @const STYLE_PARSERS
 * @type {Object<string, Object<string>>}
 */
const STYLE_PARSERS = makeStructureNS(
  NAMESPACE_URIS, {
    'LegendURL': makeObjectPropertyPusher(readLegendUrl)
  }, makeStructureNS(OWS_NAMESPACE_URIS, {
    'Title': makeObjectPropertySetter(readString),
    'Identifier': makeObjectPropertySetter(readString)
  }));

/**
 * @private
 * @const TMS_LINKS_PARSERS
 * @type {Object<string, Object<string>>}
 */
const TMS_LINKS_PARSERS = makeStructureNS(
  NAMESPACE_URIS, {
    'TileMatrixSet': makeObjectPropertySetter(readString),
    'TileMatrixSetLimits': makeObjectPropertySetter(readTileMatrixLimitsList)
  });

/**
 * @private
 * @const TMS_LIMITS_LIST_PARSERS
 * @type {Object<string, Object<string>>}
 */
const TMS_LIMITS_LIST_PARSERS = makeStructureNS(
  NAMESPACE_URIS, {
    'TileMatrixLimits': makeArrayPusher(readTileMatrixLimits)
  });

/**
 * @private
 * @const TMS_LIMITS_PARSERS
 * @type {Object<string, Object<string>>}
 */
const TMS_LIMITS_PARSERS = makeStructureNS(
  NAMESPACE_URIS, {
    'TileMatrix': makeObjectPropertySetter(readString),
    'MinTileRow': makeObjectPropertySetter(readNonNegativeInteger),
    'MaxTileRow': makeObjectPropertySetter(readNonNegativeInteger),
    'MinTileCol': makeObjectPropertySetter(readNonNegativeInteger),
    'MaxTileCol': makeObjectPropertySetter(readNonNegativeInteger)
  });

/**
 * @private
 * @const DIMENSION_PARSERS
 * @type {Object<string, Object<string>>}
 */
const DIMENSION_PARSERS = makeStructureNS(
  NAMESPACE_URIS, {
    'Default': makeObjectPropertySetter(readString),
    'Value': makeObjectPropertyPusher(readString)
  }, makeStructureNS(OWS_NAMESPACE_URIS, {
    'Identifier': makeObjectPropertySetter(readString)
  }));

/**
 * @private
 * @const BBOX_READERS
 * @type {Object<string, Object<string>>}
 */
const BBOX_READERS = makeStructureNS(
  OWS_NAMESPACE_URIS, {
    'LowerCorner': makeArrayPusher(readCoordinates),
    'UpperCorner': makeArrayPusher(readCoordinates)
  });

/**
 * @private
 * @const TMS_PARSERS
 * @type {Object<string, Object<string>>}
 */
const TMS_PARSERS = makeStructureNS(
  NAMESPACE_URIS, {
    'WellKnownScaleSet': makeObjectPropertySetter(readString),
    'TileMatrix': makeObjectPropertyPusher(readTileMatrix)
  }, makeStructureNS(OWS_NAMESPACE_URIS, {
    'SupportedCRS': makeObjectPropertySetter(readString),
    'Identifier': makeObjectPropertySetter(readString)
  }));

/**
 * @private
 * @const TM_PARSERS
 * @type {Object<string, Object<string>>}
 */
const TM_PARSERS = makeStructureNS(
  NAMESPACE_URIS, {
    'TopLeftCorner': makeObjectPropertySetter(readCoordinates),
    'ScaleDenominator': makeObjectPropertySetter(readDecimal),
    'TileWidth': makeObjectPropertySetter(readNonNegativeInteger),
    'TileHeight': makeObjectPropertySetter(readNonNegativeInteger),
    'MatrixWidth': makeObjectPropertySetter(readNonNegativeInteger),
    'MatrixHeight': makeObjectPropertySetter(readNonNegativeInteger)
  }, makeStructureNS(OWS_NAMESPACE_URIS, {
    'Identifier': makeObjectPropertySetter(readString)
  }));

/**
 * @private
 * @function Zondy.Format.WMTSCapabilities.prototype.readContents
 * @description 读取Contents
 * @param {Element} node 节点.
 * @param {Array<*>} objectStack 对象堆栈.
 * @return {Object|undefined} Attribution对象.
 */
function readContents(node, objectStack) {
  return pushParseAndPop({}, CONTENTS_PARSERS, node, objectStack);
}

/**
 * @private
 * @function Zondy.Format.WMTSCapabilities.prototype.readLayer
 * @description 读取Layer
 * @param {Element} node 节点.
 * @param {Array<*>} objectStack 对象堆栈.
 * @return {Object|undefined} Layer对象.
 */
function readLayer(node, objectStack) {
  return pushParseAndPop({}, LAYER_PARSERS, node, objectStack);
}

/**
 * @private
 * @function Zondy.Format.WMTSCapabilities.prototype.readTileMatrixSet
 * @description 读取TileMatrixSet
 * @param {Element} node 节点.
 * @param {Array<*>} objectStack 对象堆栈.
 * @return {Object|undefined} Tile Matrix Set 对象.
 */
function readTileMatrixSet(node, objectStack) {
  return pushParseAndPop({}, TMS_PARSERS, node, objectStack);
}

/**
 * @private
 * @function Zondy.Format.WMTSCapabilities.prototype.readStyle
 * @description 读取Style
 * @param {Element} node 节点.
 * @param {Array<*>} objectStack 对象堆栈.
 * @return {Object|undefined} Style 对象.
 */
function readStyle(node, objectStack) {
  const style = pushParseAndPop({}, STYLE_PARSERS, node, objectStack);
  if (!style) {
    return undefined;
  }
  const isDefault = node.getAttribute('isDefault') === 'true';
  style['isDefault'] = isDefault;
  return style;

}

/**
 * @private
 * @function Zondy.Format.WMTSCapabilities.prototype.readTileMatrixSetLink
 * @description 读取TileMatrixSetLink
 * @param {Element} node 节点.
 * @param {Array<*>} objectStack 对象堆栈.
 * @return {Object|undefined} Tile Matrix Set Link 对象.
 */
function readTileMatrixSetLink(node, objectStack) {
  return pushParseAndPop({}, TMS_LINKS_PARSERS, node, objectStack);
}

/**
 * @private
 * @function Zondy.Format.WMTSCapabilities.prototype.readDimensions
 * @description 读取Dimensions
 * @param {Element} node 节点.
 * @param {Array<*>} objectStack 对象堆栈.
 * @return {Object|undefined} Dimension 对象.
 */
function readDimensions(node, objectStack) {
  return pushParseAndPop({}, DIMENSION_PARSERS, node, objectStack);
}

/**
 * @private
 * @function Zondy.Format.WMTSCapabilities.prototype.readResourceUrl
 * @description 读取ResourceUrl
 * @param {Element} node 节点.
 * @param {Array<*>} objectStack 对象堆栈.
 * @return {Object|undefined} Resource URL 对象.
 */
function readResourceUrl(node, objectStack) {
  const format = node.getAttribute('format');
  const template = node.getAttribute('template');
  const resourceType = node.getAttribute('resourceType');
  const resource = {};
  if (format) {
    resource['format'] = format;
  }
  if (template) {
    resource['template'] = template;
  }
  if (resourceType) {
    resource['resourceType'] = resourceType;
  }
  return resource;
}

/**
 * @private
 * @function Zondy.Format.WMTSCapabilities.prototype.readBoundingBox
 * @description 读取BoundingBox和Wgs84BoundingBox
 * @param {Element} node 节点.
 * @param {Array<*>} objectStack 对象堆栈.
 * @return {Object|undefined} BBox对象.
 */
function readBoundingBox(node, objectStack) {
  const coordinates = pushParseAndPop([], BBOX_READERS, node, objectStack);
  if (coordinates.length != 2) {
    return undefined;
  }
  return boundingExtent(coordinates);
}

/**
 * @private
 * @function Zondy.Format.WMTSCapabilities.prototype.readLegendUrl
 * @description 读取LegendUrl
 * @param {Element} node 节点.
 * @param {Array<*>} objectStack 对象堆栈.
 * @return {Object|undefined} Legend对象.
 */
function readLegendUrl(node, objectStack) {
  const legend = {};
  legend['format'] = node.getAttribute('format');
  legend['href'] = readHref(node);
  return legend;
}

/**
 * @private
 * @function Zondy.Format.WMTSCapabilities.prototype.readCoordinates
 * @description 读取Coordinates
 * @param {Node} node 节点.
 * @param {Array<*>} objectStack 对象堆栈.
 * @return {Object|undefined} Coordinates对象.
 */
function readCoordinates(node, objectStack) {
  const coordinates = readString(node).split(/\s+/);
  if (!coordinates || coordinates.length != 2) {
    return undefined;
  }
  const x = +coordinates[0];
  const y = +coordinates[1];
  if (isNaN(x) || isNaN(y)) {
    return undefined;
  }
  return [x, y];
}

/**
 * @private
 * @function Zondy.Format.WMTSCapabilities.prototype.readTileMatrix
 * @description 读取TileMatrix
 * @param {Element} node 节点.
 * @param {Array<*>} objectStack 对象堆栈.
 * @return {Object|undefined} TileMatrix对象.
 */
function readTileMatrix(node, objectStack) {
  return pushParseAndPop({}, TM_PARSERS, node, objectStack);
}

/**
 * @private
 * @function Zondy.Format.WMTSCapabilities.prototype.readTileMatrixLimitsList
 * @description 读取TileMatrixLimitsList
 * @param {Element} node 节点.
 * @param {Array<*>} objectStack 对象堆栈.
 * @return {Object|undefined} TileMatrixSetLimits对象.
 */
function readTileMatrixLimitsList(node, objectStack) {
  return pushParseAndPop([], TMS_LIMITS_LIST_PARSERS, node, objectStack);
}

/**
 * @private
 * @function Zondy.Format.WMTSCapabilities.prototype.readTileMatrixLimits
 * @description 读取TileMatrixLimits
 * @param {Element} node 节点.
 * @param {Array<*>} objectStack 对象堆栈.
 * @return {Object|undefined} TileMatrixLimits Array.
 */
function readTileMatrixLimits(node, objectStack) {
  return pushParseAndPop({}, TMS_LIMITS_PARSERS, node, objectStack);
}

export {
  WMTSCapabilities
};
Zondy.Format.WMTSCapabilities = WMTSCapabilities;