5488e7767e1256d5a59d3936ba3ebbfe05343a2b
[osm/UI.git] / skyquake / plugins / composer / src / src / libraries / model / DescriptorModelMetaFactory.js
1 /**
2 * Created by onvelocity on 1/27/16.
3 *
4 * This class provides methods to get the metadata about descriptor models.
5 */
6
7 'use strict';
8
9 import _cloneDeep from 'lodash/cloneDeep'
10 import utils from './../utils'
11 import DescriptorModelMetaProperty from './DescriptorModelMetaProperty'
12 import CommonUtils from 'utils/utils';
13 const assign = Object.assign;
14
15 const exportInnerTypesMap = {
16 'constituent-vnfd': 'nsd.constituent-vnfd',
17 'vdu': 'vnfd.vdu'
18 };
19
20 function getPathForType(type) {
21 if (exportInnerTypesMap[type]) {
22 return exportInnerTypesMap[type];
23 }
24 return type;
25 }
26
27 let modelMetaByPropertyNameMap = [];
28
29 let cachedDescriptorModelMetaRequest = null;
30
31 export default {
32 init() {
33 if (!cachedDescriptorModelMetaRequest) {
34 cachedDescriptorModelMetaRequest = new Promise(function(resolve, reject) {
35 CommonUtils.getDescriptorModelMeta().then(function(data) {
36 let DescriptorModelMetaJSON = data;
37 modelMetaByPropertyNameMap = Object.keys(DescriptorModelMetaJSON).reduce((map, key) => {
38 function mapProperties(parentMap, parentObj) {
39 parentMap[':meta'] = parentObj;
40 const properties = parentObj && parentObj.properties ? parentObj.properties : [];
41 properties.forEach(p => {
42 parentMap[p.name] = mapProperties({}, assign(p, {':qualified-type': parentObj[':qualified-type'] + '.' + p.name}));
43 return map;
44 }, parentMap);
45 return parentMap;
46 }
47 map[key] = mapProperties({}, assign(DescriptorModelMetaJSON[key], {':qualified-type': key}));
48 return map;
49 }, {});
50
51 (() => {
52 // initialize the UI centric properties that CONFD could care less about
53 utils.assignPathValue(modelMetaByPropertyNameMap, 'nsd.meta.:meta.preserve-line-breaks', true);
54 utils.assignPathValue(modelMetaByPropertyNameMap, 'vnfd.meta.:meta.preserve-line-breaks', true);
55 utils.assignPathValue(modelMetaByPropertyNameMap, 'vnfd.vdu.cloud-init.:meta.preserve-line-breaks', true);
56 utils.assignPathValue(modelMetaByPropertyNameMap, 'nsd.constituent-vnfd.vnf-configuration.config-template.:meta.preserve-line-breaks', true);
57 })();
58 resolve();
59 }, function(error) {
60 cachedDescriptorModelMetaRequest = null;
61 })
62 })
63 }
64
65 return cachedDescriptorModelMetaRequest;
66 },
67 /**
68 * Create a new instance of the indicated property and, if relevent, use the given
69 * unique name for the instance's key (see generateItemUniqueName)
70 *
71 * @param {Object | string} typeOrPath a property definition object or a path to a property
72 * @param [{string}] uniqueName optional
73 * @returns
74 */
75 createModelInstanceForType(typeOrPath, uniqueName) {
76 const modelMeta = this.getModelMetaForType(typeOrPath);
77 return DescriptorModelMetaProperty.createModelInstance(modelMeta, uniqueName);
78 },
79 getModelMetaForType(typeOrPath, filterProperties = () => true) {
80 // resolve paths like 'nsd' or 'vnfd.vdu' or 'nsd.constituent-vnfd'
81 const found = utils.resolvePath(modelMetaByPropertyNameMap, getPathForType(typeOrPath));
82 if (found) {
83 const uiState = _cloneDeep(found[':meta']);
84 uiState.properties = uiState.properties.filter(filterProperties);
85 return uiState;
86 }
87 console.warn('no model uiState found for type', typeOrPath);
88 },
89 getModelFieldNamesForType(typeOrPath) {
90 // resolve paths like 'nsd' or 'vnfd.vdu' or 'nsd.constituent-vnfd'
91 const found = utils.resolvePath(modelMetaByPropertyNameMap, getPathForType(typeOrPath));
92 if (found) {
93 let result = [];
94 found[':meta'].properties.map((p) => {
95 // if(false) {
96 if(p.type == 'choice') {
97 result.push(p.name)
98 return p.properties.map(function(q){
99 result.push(q.properties[0].name);
100 })
101
102 } else {
103 return result.push(p.name);
104 }
105 })
106 return result;
107 }
108 console.warn('no model uiState found for type', typeOrPath);
109 },
110 /**
111 * For a list with a single valued key that is of type string, generate a unique name
112 * for a new entry to be added to the indicated list. This name will use the provided
113 * prefix (or the list's name) followed by a number. The number will be based on the
114 * current length of the array but will insure there is no collision with an existing
115 * name.
116 *
117 * @param {Array} list the list model data
118 * @param {prooerty} property the schema definition of the list
119 * @param [{any} prefix] the perferred prefix for the name. If not provide property.name
120 * will be used.
121 * @returns {string}
122 */
123 generateItemUniqueName (list, property, prefix) {
124 if ( property.type !== 'list'
125 || property.key.length !== 1
126 || property.properties.find(prop => prop.name === property.key[0])['data-type'] !== 'string') {
127 // only support list with a single key of type string
128 return null;
129 }
130 if (!prefix) {
131 prefix = property.name;
132 }
133 let key = property.key[0];
134 let suffix = list ? list.length + 1 : 1
135 let keyValue = prefix + '-' + suffix;
136 function makeUniqueName() {
137 if (list) {
138 for (let i = 0; i < list.length; i = ++i) {
139 if (list[i][key] === keyValue) {
140 keyValue = keyValue + '-' + (i+1);
141 makeUniqueName(); // not worried about recursing too deep (chances ??)
142 break;
143 }
144 }
145 }
146 }
147 makeUniqueName();
148 return keyValue;
149 }
150
151 }