Source: formats/kml/util/KmlElementsFactoryCached.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. define([
  29. './KmlAttribute',
  30. './KmlElementsFactory',
  31. './KmlTreeKeyValueCache',
  32. '../../../util/WWUtil'
  33. ], function (
  34. Attribute,
  35. KmlElementsFactory,
  36. TreeKeyValueCache,
  37. WWUtil
  38. ) {
  39. "use strict";
  40. /**
  41. * More complex factory, which retrieves the values from cache and in case the value isn't present there it
  42. * stores the value in cache.
  43. * @constructor
  44. * @alias KmlElementsFactoryCached
  45. */
  46. var KmlElementsFactoryCached = function(options) {
  47. this.internalFactory = new KmlElementsFactory(options);
  48. this.cache = TreeKeyValueCache.applicationLevelCache();
  49. };
  50. /**
  51. * It adds caching functionality on top of the KmlElementsFactory all method.
  52. * @param element {KmlObject} Element whose children are considered
  53. * @returns {KmlObject[]} All objects among the elements children
  54. * @see KmlElementsFactory.prototype.all
  55. */
  56. KmlElementsFactoryCached.prototype.all = function(element){
  57. var parentNode = element.node;
  58. var children = this.cache.level(this.cacheKey(element.node, "All"));
  59. if (children) {
  60. var results = [];
  61. for(var key in children) {
  62. if(children.hasOwnProperty(key)) {
  63. results.push(children[key]);
  64. }
  65. }
  66. return results;
  67. }
  68. var elements = this.internalFactory.all(element);
  69. if(elements && elements.length) {
  70. var self = this;
  71. elements.forEach(function (pElement) {
  72. self.cache.add(self.cacheKey(parentNode, "All"), self.cacheKey(pElement.node), pElement);
  73. });
  74. }
  75. return elements;
  76. };
  77. /**
  78. * It adds caching functionality on top of the KmlElementsFactory specific method.
  79. * @param element {KmlObject} Element whose children are considered
  80. * @param options {Object}
  81. * @param options.name {String} Name of the element to retrieve from the element
  82. * @param options.transformer {Function} Function returning correct value. It accepts the node and returns value.
  83. * This mechanism can be used for the attributes as well.
  84. * @returns Relevant value.
  85. * @see KmlElementsFactory.prototype.specific
  86. */
  87. KmlElementsFactoryCached.prototype.specific = function(element, options){
  88. var parentNode = element.node;
  89. var name = options.name;
  90. if(options.attribute) {
  91. name = options.attribute + name;
  92. }
  93. var child = this.cache.value(this.cacheKey(parentNode), name);
  94. if (child) {
  95. return child;
  96. }
  97. var result = this.internalFactory.specific(element, options);
  98. if(result && result.node) {
  99. this.cache.add(this.cacheKey(parentNode), this.cacheKey(result.node), result);
  100. } else if(result) {
  101. this.cache.add(this.cacheKey(parentNode), name, result);
  102. }
  103. return result;
  104. };
  105. /**
  106. * It adds caching functionality on top of the KmlElementsFactory any method.
  107. * @param element {KmlObject} Element whose children are considered
  108. * @param options {Object}
  109. * @param options.name {String[]} Array of the names among which should be the one we are looking for.
  110. * @returns {KmlObject|null} KmlObject if there is one with the passed in name.
  111. * @see KmlElementsFactory.prototype.any
  112. */
  113. KmlElementsFactoryCached.prototype.any = function(element, options){
  114. var parentNode = element.node;
  115. var self = this;
  116. var child = null;
  117. var potentialChild;
  118. options.name.forEach(function(name){
  119. potentialChild = self.cache.value(self.cacheKey(parentNode), name);
  120. if(potentialChild) {
  121. child = potentialChild;
  122. }
  123. });
  124. if (child) {
  125. return child;
  126. }
  127. var result = this.internalFactory.any(element, options);
  128. if(result) {
  129. this.cache.add(self.cacheKey(parentNode), self.cacheKey(result.node), result);
  130. }
  131. return result;
  132. };
  133. /**
  134. * It creates cache key based on the node. In case the node doesn't have any id, it also creates id for this
  135. * element. This id is used for storing the value in the cache.
  136. * @param node {Node} Node for which generate the key.
  137. * @param prefix {String|undefined} Prefix for the level
  138. * @returns {String} Value representing the key.
  139. */
  140. KmlElementsFactoryCached.prototype.cacheKey = function(node, prefix) {
  141. var idAttribute = new Attribute(node, "id");
  142. if (!idAttribute.exists()) {
  143. idAttribute.save(WWUtil.guid());
  144. }
  145. var result = node.nodeName + "#" + idAttribute.value();
  146. if(prefix) {
  147. result = prefix + result;
  148. }
  149. return result;
  150. };
  151. var applicationWide = new KmlElementsFactoryCached();
  152. /**
  153. * It returns application wide instance of the factory.
  154. * @returns {KmlElementsFactoryCached} Singleton instance of factory for Application.
  155. */
  156. KmlElementsFactoryCached.applicationWide = function(){
  157. return applicationWide;
  158. };
  159. return KmlElementsFactoryCached;
  160. });