config_recommendation_parser.js 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. var App = require('app');
  19. var validator = require('utils/validator');
  20. App.ConfigRecommendationParser = Em.Mixin.create(App.ConfigRecommendations, {
  21. stepConfigs: [],
  22. /**
  23. * Method that goes through all configs
  24. * and apply recommendations using callbacks
  25. *
  26. * @param recommendationObject
  27. * @param configs
  28. * @param parentProperties
  29. * @param configGroup
  30. * @param updateCallback
  31. * @param removeCallback
  32. * @param updateBoundariesCallback
  33. */
  34. parseRecommendations: function(recommendationObject, configs, parentProperties, configGroup,
  35. updateCallback, removeCallback, updateBoundariesCallback) {
  36. App.assertObject(recommendationObject);
  37. App.assertArray(configs);
  38. App.assertFunction(updateCallback);
  39. App.assertFunction(removeCallback);
  40. App.assertFunction(updateBoundariesCallback);
  41. var propertiesToDelete = [];
  42. configs.forEach(function (config) {
  43. var name = Em.get(config, 'name'), fileName = Em.get(config, 'filename'),
  44. recommendations = recommendationObject[App.config.getConfigTagFromFileName(fileName)];
  45. if (recommendations) {
  46. if (recommendations.properties) {
  47. var recommendedValue = App.config.formatValue(recommendations.properties[name]);
  48. if (!Em.isNone(recommendedValue)) {
  49. /** update config **/
  50. updateCallback(config, recommendedValue, parentProperties, configGroup);
  51. delete recommendations.properties[name];
  52. }
  53. }
  54. if (recommendations.property_attributes) {
  55. var propertyAttributes = recommendations.property_attributes[name];
  56. if (propertyAttributes) {
  57. var stackProperty = App.configsCollection.getConfigByName(name, fileName);
  58. for (var attr in propertyAttributes) {
  59. if (attr === 'delete' && this.allowUpdateProperty(parentProperties, name, fileName)) {
  60. propertiesToDelete.push(config);
  61. } else if ((attr === 'visible') || stackProperty) {
  62. /** update config boundaries **/
  63. updateBoundariesCallback(stackProperty, attr, propertyAttributes[attr], name, fileName, configGroup);
  64. }
  65. }
  66. }
  67. }
  68. }
  69. }, this);
  70. if (propertiesToDelete.length) {
  71. propertiesToDelete.forEach(function (property) {
  72. /** remove config **/
  73. removeCallback(property, configs, parentProperties, configGroup);
  74. }, this);
  75. }
  76. },
  77. /**
  78. * Method that goes through all configs
  79. * and apply recommendations to configs when it's needed
  80. *
  81. * @param {Object} recommendationObject
  82. * @param {Object[]} configs
  83. * @param {Object[]} parentProperties
  84. */
  85. updateConfigsByRecommendations: function (recommendationObject, configs, parentProperties) {
  86. this.parseRecommendations(recommendationObject, configs, parentProperties, null,
  87. this._updateConfigByRecommendation.bind(this), this._removeConfigByRecommendation.bind(this), this._updateBoundaries.bind(this));
  88. },
  89. /**
  90. * This method goes through all config recommendations
  91. * and trying to add new properties
  92. *
  93. * @param {Object} recommendationObject
  94. * @param {Object[]} parentProperties
  95. */
  96. addByRecommendations: function (recommendationObject, parentProperties) {
  97. App.assertObject(recommendationObject);
  98. for (var site in recommendationObject) {
  99. var properties = recommendationObject[site].properties;
  100. if (properties && Object.keys(properties).length) {
  101. var stepConfig = App.config.getStepConfigForProperty(this.get('stepConfigs'), site), configs = [];
  102. if (stepConfig) {
  103. for (var propertyName in properties) {
  104. if (this.allowUpdateProperty(parentProperties, propertyName, site)) {
  105. configs.pushObject(this._createNewProperty(propertyName, site, stepConfig.get('serviceName'), properties[propertyName], parentProperties));
  106. }
  107. }
  108. if (configs.length) {
  109. var mergedConfigs = configs.concat(stepConfig.get('configs'));
  110. stepConfig.set('configs', mergedConfigs);
  111. }
  112. }
  113. }
  114. }
  115. },
  116. /**
  117. * Update config based on recommendations
  118. *
  119. * @param {recommendation} config
  120. * @param {String} recommendedValue
  121. * @param {String[]} [parentProperties]
  122. * @returns {recommendation}
  123. * @protected
  124. */
  125. _updateConfigByRecommendation: function (config, recommendedValue, parentProperties) {
  126. App.assertObject(config);
  127. Em.set(config, 'recommendedValue', recommendedValue);
  128. if (this.allowUpdateProperty(parentProperties, Em.get(config, 'name'), Em.get(config, 'filename'))) {
  129. Em.set(config, 'value', recommendedValue);
  130. this.applyRecommendation(Em.get(config, 'name'), Em.get(config, 'filename'), Em.get(config, 'group.name'), recommendedValue, this._getInitialValue(config), parentProperties);
  131. }
  132. if (this.updateInitialOnRecommendations(Em.get(config, 'serviceName'))) {
  133. Em.set(config, 'initialValue', recommendedValue);
  134. }
  135. return config;
  136. },
  137. /**
  138. * Add config based on recommendations
  139. *
  140. * @param name
  141. * @param fileName
  142. * @param serviceName
  143. * @param recommendedValue
  144. * @param parentProperties
  145. * @protected
  146. */
  147. _createNewProperty: function (name, fileName, serviceName, recommendedValue, parentProperties) {
  148. App.assertExists(name, 'name');
  149. App.assertExists(fileName, 'fileName');
  150. App.assertExists(serviceName, 'serviceName');
  151. var coreObject = this._getCoreProperties(serviceName, recommendedValue, this._getInitialFromRecommendations(name, fileName)),
  152. newConfig = App.config.getDefaultConfig(name, fileName, coreObject),
  153. addedPropertyObject = App.ServiceConfigProperty.create(newConfig);
  154. this.applyRecommendation(name, fileName, "Default",
  155. recommendedValue, null, parentProperties);
  156. return addedPropertyObject;
  157. },
  158. /**
  159. *
  160. * @param serviceName
  161. * @param recommendedValue
  162. * @param initialValue
  163. * @returns {{value: *, recommendedValue: *, initialValue: *, savedValue: *}}
  164. * @private
  165. */
  166. _getCoreProperties: function(serviceName, recommendedValue, initialValue) {
  167. return {
  168. "value": recommendedValue,
  169. "recommendedValue": recommendedValue,
  170. "initialValue": this.updateInitialOnRecommendations(serviceName) ? recommendedValue : initialValue,
  171. "savedValue": !this.useInitialValue(serviceName) ? initialValue : null
  172. }
  173. },
  174. /**
  175. * Remove config based on recommendations
  176. *
  177. * @param config
  178. * @param configsCollection
  179. * @param parentProperties
  180. * @protected
  181. */
  182. _removeConfigByRecommendation: function (config, configsCollection, parentProperties) {
  183. App.assertObject(config);
  184. App.assertArray(configsCollection);
  185. configsCollection.removeObject(config);
  186. this.applyRecommendation(Em.get(config, 'name'), Em.get(config, 'filename'), Em.get(config, 'group.name'),
  187. null, this._getInitialValue(config), parentProperties);
  188. },
  189. /**
  190. * Update config valueAttributes by recommendations
  191. *
  192. * @param {Object} stackProperty
  193. * @param {string} attr
  194. * @param {Number|String|Boolean} value
  195. * @param {String} name
  196. * @param {String} fileName
  197. * @protected
  198. */
  199. _updateBoundaries: function(stackProperty, attr, value, name, fileName) {
  200. if (attr === 'visible') {
  201. var p = App.config.findConfigProperty(this.get('stepConfigs'), name, App.config.getOriginalFileName(fileName));
  202. if (p) {
  203. p.set('isVisible', value);
  204. }
  205. }
  206. if (stackProperty) {
  207. if (!Em.get(stackProperty, 'valueAttributes')) {
  208. stackProperty.valueAttributes = {};
  209. }
  210. Em.set(stackProperty.valueAttributes, attr, value);
  211. }
  212. return stackProperty || null;
  213. },
  214. /**
  215. * Get initial config value that was before recommendations was applied
  216. *
  217. * @param name
  218. * @param fileName
  219. * @returns {*}
  220. * @protected
  221. */
  222. _getInitialFromRecommendations: function(name, fileName) {
  223. try {
  224. return this.getRecommendation(name, fileName).initialValue;
  225. } catch(e) {
  226. return null;
  227. }
  228. },
  229. /**
  230. * Get default config value
  231. * <code>savedValue<code> for installed services
  232. * <code>initialValue<code> for new services
  233. *
  234. * @param configProperty
  235. * @returns {*}
  236. * @protected
  237. */
  238. _getInitialValue: function (configProperty) {
  239. if (!configProperty) return null;
  240. return this.useInitialValue(Em.get(configProperty, 'serviceName')) ?
  241. Em.get(configProperty, 'initialValue') : Em.get(configProperty, 'savedValue');
  242. },
  243. /**
  244. * Update initial only when <code>initialValue<code> is used
  245. *
  246. * @param {string} serviceName
  247. * @returns {boolean}
  248. */
  249. updateInitialOnRecommendations: function(serviceName) {
  250. return this.useInitialValue(serviceName);
  251. },
  252. /**
  253. * Defines if initialValue of config can be used on current controller
  254. * if not savedValue is used instead
  255. *
  256. * @param {String} serviceName
  257. * @return {boolean}
  258. */
  259. useInitialValue: function (serviceName) {
  260. return false;
  261. },
  262. /**
  263. * Defines if recommendation allowed to be applied
  264. *
  265. * @param parentProperties
  266. * @param name
  267. * @param fileName
  268. * @param [configGroup]
  269. * @returns {boolean}
  270. */
  271. allowUpdateProperty: function (parentProperties, name, fileName, configGroup) {
  272. try {
  273. return Em.get(this.getRecommendation(name, fileName, configGroup), 'saveRecommended');
  274. } catch (e) {
  275. return true;
  276. }
  277. }
  278. });