Source: ogc/wmts/WmtsCapabilities.js

  1. /*
  2. * Copyright 2003-2006, 2009, 2017, 2020 United States Government, as represented
  3. * by the Administrator of the National Aeronautics and Space Administration.
  4. * All rights reserved.
  5. *
  6. * The NASAWorldWind/WebWorldWind platform is licensed under the Apache License,
  7. * Version 2.0 (the "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License
  9. * at http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software distributed
  12. * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  13. * CONDITIONS OF ANY KIND, either express or implied. See the License for the
  14. * specific language governing permissions and limitations under the License.
  15. *
  16. * NASAWorldWind/WebWorldWind also contains the following 3rd party Open Source
  17. * software:
  18. *
  19. * ES6-Promise – under MIT License
  20. * libtess.js – SGI Free Software License B
  21. * Proj4 – under MIT License
  22. * JSZip – under MIT License
  23. *
  24. * A complete listing of 3rd Party software notices and licenses included in
  25. * WebWorldWind can be found in the WebWorldWind 3rd-party notices and licenses
  26. * PDF found in code directory.
  27. */
  28. /**
  29. * @exports WmtsCapabilities
  30. */
  31. define([
  32. '../../error/ArgumentError',
  33. '../../util/Logger',
  34. '../../ogc/ows/OwsDescription',
  35. '../../ogc/ows/OwsLanguageString',
  36. '../../ogc/ows/OwsOperationsMetadata',
  37. '../../ogc/ows/OwsServiceIdentification',
  38. '../../ogc/ows/OwsServiceProvider',
  39. '../../ogc/wms/WmsCapabilities',
  40. '../../ogc/wmts/WmtsLayerCapabilities'
  41. ],
  42. function (ArgumentError,
  43. Logger,
  44. OwsDescription,
  45. OwsLanguageString,
  46. OwsOperationsMetadata,
  47. OwsServiceIdentification,
  48. OwsServiceProvider,
  49. WmsCapabilities,
  50. WmtsLayerCapabilities) {
  51. "use strict";
  52. /**
  53. * Constructs an OGC WMTS capabilities document from an XML DOM.
  54. * @alias WmtsCapabilities
  55. * @constructor
  56. * @classdesc Represents an OGC WMTS capabilities document.
  57. * This object holds as properties all the fields specified in the OGC WMTS capabilities document.
  58. * Most fields can be accessed as properties named according to their document names converted to camel case.
  59. * For example, "serviceIdentification" and "contents".
  60. * @param {{}} xmlDom An XML DOM representing the OGC WMTS capabilities document.
  61. * @throws {ArgumentError} If the specified XML DOM is null or undefined.
  62. */
  63. var WmtsCapabilities = function (xmlDom) {
  64. if (!xmlDom) {
  65. throw new ArgumentError(
  66. Logger.logMessage(Logger.LEVEL_SEVERE, "WmtsCapabilities", "constructor", "No XML DOM specified."));
  67. }
  68. this.assembleDocument(xmlDom);
  69. };
  70. /**
  71. * Provides all of the layers associated with this WMTS. This method is for convienence and returns the layer
  72. * array captured in the contents of this WmtsCapabilities object.
  73. * @returns {WmtsLayerCapabilities[]}
  74. */
  75. WmtsCapabilities.prototype.getLayers = function () {
  76. return this.contents.layer;
  77. };
  78. /**
  79. * Retrieve the WmtsLayerCapabilities object for the provided identifier.
  80. * @param identifier
  81. * @returns {WmtsLayerCapabilities} object for the provided identifier or null if no identifier was found in the
  82. * WmtsCapabilities object.
  83. * @throws {ArgumentError} If the specified identifier is null or undefined.
  84. */
  85. WmtsCapabilities.prototype.getLayer = function (identifier) {
  86. if (!identifier) {
  87. throw new ArgumentError(
  88. Logger.logMessage(Logger.LEVEL_SEVERE, "WmtsCapabilities", "getLayer", "empty identifier"));
  89. }
  90. for (var i = 0, len = this.contents.layer.length; i < len; i++) {
  91. var wmtsLayerCapabilities = this.contents.layer[i];
  92. if (wmtsLayerCapabilities.identifier === identifier) {
  93. return wmtsLayerCapabilities;
  94. }
  95. }
  96. return null;
  97. };
  98. WmtsCapabilities.prototype.assembleDocument = function (dom) {
  99. var root = dom.documentElement;
  100. this.version = root.getAttribute("version");
  101. this.updateSequence = root.getAttribute("updateSequence");
  102. var children = root.children || root.childNodes;
  103. for (var c = 0; c < children.length; c++) {
  104. var child = children[c];
  105. if (child.localName === "ServiceIdentification") {
  106. this.serviceIdentification = new OwsServiceIdentification(child);
  107. } else if (child.localName === "ServiceProvider") {
  108. this.serviceProvider = new OwsServiceProvider(child);
  109. } else if (child.localName === "OperationsMetadata") {
  110. this.operationsMetadata = new OwsOperationsMetadata(child);
  111. } else if (child.localName === "Contents") {
  112. this.contents = this.assembleContents(child);
  113. } else if (child.localName === "Themes") {
  114. this.themes = WmtsCapabilities.assembleThemes(child);
  115. } else if (child.localName === "ServiceMetadataURL") {
  116. this.serviceMetadataUrls = this.serviceMetadataUrls || [];
  117. this.serviceMetadataUrls.push(WmtsCapabilities.assembleServiceMetadataURL(child));
  118. }
  119. }
  120. };
  121. WmtsCapabilities.prototype.assembleContents = function (element) {
  122. var contents = {};
  123. var children = element.children || element.childNodes;
  124. for (var c = 0; c < children.length; c++) {
  125. var child = children[c];
  126. if (child.localName === "Layer") {
  127. contents.layer = contents.layer || [];
  128. try {
  129. contents.layer.push(new WmtsLayerCapabilities(child, this));
  130. } catch (e) {
  131. Logger.logMessage(Logger.LEVEL_SEVERE, "WmtsCapabilities", "constructor",
  132. "Exception reading WMTS layer description: " + e.message);
  133. }
  134. } else if (child.localName === "TileMatrixSet") {
  135. contents.tileMatrixSet = contents.tileMatrixSet || [];
  136. try {
  137. contents.tileMatrixSet.push(WmtsCapabilities.assembleTileMatrixSet(child));
  138. } catch (e) {
  139. Logger.logMessage(Logger.LEVEL_SEVERE, "WmtsCapabilities", "constructor",
  140. "Exception reading WMTS tile matrix set description: " + e.message);
  141. }
  142. }
  143. // TODO: OtherSource
  144. }
  145. return contents;
  146. };
  147. WmtsCapabilities.assembleTileMatrixSet = function (element) {
  148. var tileMatrixSet = new OwsDescription(element);
  149. var children = element.children || element.childNodes;
  150. for (var c = 0; c < children.length; c++) {
  151. var child = children[c];
  152. if (child.localName === "Identifier") {
  153. tileMatrixSet.identifier = child.textContent;
  154. } else if (child.localName === "SupportedCRS") {
  155. tileMatrixSet.supportedCRS = child.textContent;
  156. } else if (child.localName === "WellKnownScaleSet") {
  157. tileMatrixSet.wellKnownScaleSet = child.textContent;
  158. } else if (child.localName === "BoundingBox") {
  159. tileMatrixSet.boundingBox = WmtsLayerCapabilities.assembleBoundingBox(child);
  160. } else if (child.localName === "TileMatrix") {
  161. tileMatrixSet.tileMatrix = tileMatrixSet.tileMatrix || [];
  162. tileMatrixSet.tileMatrix.push(WmtsCapabilities.assembleTileMatrix(child));
  163. }
  164. }
  165. WmtsCapabilities.sortTileMatrices(tileMatrixSet);
  166. for (var i = 0; i < tileMatrixSet.tileMatrix.length; i++) {
  167. tileMatrixSet.tileMatrix[i].levelNumber = i;
  168. }
  169. return tileMatrixSet;
  170. };
  171. WmtsCapabilities.assembleTileMatrix = function (element) {
  172. var tileMatrix = new OwsDescription(element);
  173. var children = element.children || element.childNodes;
  174. for (var c = 0; c < children.length; c++) {
  175. var child = children[c];
  176. if (child.localName === "Identifier") {
  177. tileMatrix.identifier = child.textContent;
  178. } else if (child.localName === "ScaleDenominator") {
  179. tileMatrix.scaleDenominator = parseFloat(child.textContent);
  180. } else if (child.localName === "TileWidth") {
  181. tileMatrix.tileWidth = parseFloat(child.textContent);
  182. } else if (child.localName === "TileHeight") {
  183. tileMatrix.tileHeight = parseFloat(child.textContent);
  184. } else if (child.localName === "MatrixWidth") {
  185. tileMatrix.matrixWidth = parseFloat(child.textContent);
  186. } else if (child.localName === "MatrixHeight") {
  187. tileMatrix.matrixHeight = parseFloat(child.textContent);
  188. } else if (child.localName === "TopLeftCorner") {
  189. var values = child.textContent.split(" ");
  190. tileMatrix.topLeftCorner = [parseFloat(values[0]), parseFloat(values[1])];
  191. }
  192. }
  193. return tileMatrix;
  194. };
  195. WmtsCapabilities.assembleThemes = function (element) {
  196. var themes;
  197. var children = element.children || element.childNodes;
  198. for (var c = 0; c < children.length; c++) {
  199. var child = children[c];
  200. if (child.localName === "Theme") {
  201. themes = themes || [];
  202. themes.push(WmtsCapabilities.assembleTheme(child));
  203. }
  204. }
  205. return themes;
  206. };
  207. WmtsCapabilities.assembleTheme = function (element) {
  208. var theme = new OwsDescription(element);
  209. var children = element.children || element.childNodes;
  210. for (var c = 0; c < children.length; c++) {
  211. var child = children[c];
  212. if (child.localName === "Identifier") {
  213. theme.identifier = child.textContent;
  214. } else if (child.localName === "LayerRef") {
  215. theme.layerRef = theme.layerRef || [];
  216. theme.layerRef.push(child.textContent);
  217. } else if (child.localName === "Theme") {
  218. theme.themes = theme.themes || [];
  219. theme.themes.push(WmtsCapabilities.assembleTheme(child));
  220. }
  221. }
  222. return theme;
  223. };
  224. WmtsCapabilities.assembleServiceMetadataURL = function (element) {
  225. var result = {};
  226. var link = element.getAttribute("xlink:href");
  227. if (link) {
  228. result.url = link;
  229. }
  230. return result;
  231. };
  232. /**
  233. * Sorts a tile matrix set by the tile matrices scale denominator.
  234. * @param tileMatrixSet
  235. */
  236. WmtsCapabilities.sortTileMatrices = function (tileMatrixSet) {
  237. // This operation is not required by the WMTS specification. The WMTS specification assumes Tile Matrix
  238. // selection based on a scale denominator value. Web WorldWind currently matches the tile's Level to the
  239. // corresponding Tile Matrix index in the Tile Matrix Set. If the Tile Matrices are not ordered in a
  240. // typical pyramid fashion, this could result in undefined behavior. Sorting the matrices by the scale
  241. // denominator should ensure the WorldWind Level will match the Tile Matrix index. This operation will not
  242. // be required once a system which matches the scale denominator is implemented.
  243. tileMatrixSet.tileMatrix.sort(function (a, b) {
  244. return b.scaleDenominator - a.scaleDenominator;
  245. });
  246. };
  247. WmtsCapabilities.prototype.getGetTileKvpAddress = function () {
  248. for (var i = 0; i < this.operationsMetadata.operation.length; i++) {
  249. var operation = this.operationsMetadata.operation[i];
  250. if (operation.name === "GetTile") {
  251. return operation.dcp[0].getMethods[0].url;
  252. }
  253. }
  254. return null;
  255. };
  256. return WmtsCapabilities;
  257. })
  258. ;