2955e550372eafd12ca2816019cd75fbd9d519ff
[osm/UI.git] / skyquake / plugins / composer / src / src / libraries / model / DescriptorModelMetaProperty.js
1 /*
2 *
3 * Copyright 2016 RIFT.IO Inc
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18 /**
19 * Created by onvelocity on 1/27/16.
20 *
21 * This class provides utility methods for interrogating an instance of model uiState object.
22 */
23
24 'use strict';
25
26 import _includes from 'lodash/includes'
27 import _isArray from 'lodash/isArray'
28 import guid from './../guid'
29 import changeCase from 'change-case'
30 import InstanceCounter from './../InstanceCounter'
31 import DescriptorModelFields from './DescriptorModelFields'
32 import DescriptorTemplateFactory from './DescriptorTemplateFactory'
33 import utils from '../utils'
34
35 export default {
36 isBoolean(property = {}) {
37 return (typeof(property['data-type']) == 'string') && (property['data-type'].toLowerCase() == 'boolean')
38 },
39 isLeaf(property = {}) {
40 return /leaf|choice/.test(property.type);
41 },
42 isList(property = {}) {
43 return /list|leaf_list/.test(property.type);
44 },
45 isLeafList(property = {}) {
46 return property.type === 'leaf_list';
47 },
48 isLeafRef(property = {}) {
49 const type = property['data-type'] || {};
50 return type.hasOwnProperty('leafref');
51 },
52 isArray(property = {}) {
53 // give '1' or '0..N' or '0..1' or '0..5' determine if represents an array
54 // '0..1' is not an array
55 // '0..2' is an array
56 // '0..N' is an array
57 const cardinality = String(property.cardinality).toUpperCase();
58 const pos = cardinality.lastIndexOf('.') + 1;
59 const val = cardinality.substr(pos);
60 return val === 'N' || parseInt(val, 10) > 1;
61 },
62 isEnumeration(property = {}) {
63 const type = property['data-type'] || {};
64 return type.hasOwnProperty('enumeration');
65 },
66 isRequired(property = {}) {
67 return /^1/.test(property.cardinality);
68 },
69 isObject(property = {}) {
70 return !/^(leaf|leaf_list)$/.test(property.type);
71 },
72 isSimpleList(property = {}) {
73 return _includes(DescriptorModelFields.simpleList, property.name);
74 },
75 isPrimativeDataType(property = {}) {
76 const Property = this;
77 return /string|int/.test(property['data-type']) || Property.isEnumeration(property) || Property.isGuid(property);
78 },
79 defaultValue(property = {}) {
80 if (property.defaultValue) {
81 return property.defaultValue;
82 }
83 if (this.isObject(property)) {
84 return {};
85 }
86 return '';
87 },
88 getContainerMethod(property, container, methodName) {
89 const name = changeCase.camel(methodName + '-' + property.name);
90 if (typeof container[name] === 'function') {
91 return container[name].bind(container);
92 }
93 },
94 getContainerCreateMethod(property, container) {
95 const name = changeCase.camel('create-' + property.name);
96 if (typeof container[name] === 'function') {
97 return container[name].bind(container);
98 }
99 },
100 containerHasCreateMethod(container, property = {}) {
101 const find = changeCase.camel('create-' + property.name);
102 return typeof container[find] === 'function';
103 },
104 getEnumeration(property = {}, value) {
105 const enumeration = property['data-type'].enumeration.enum;
106 if (typeof enumeration === 'string') {
107 return [{name: enumeration, value: enumeration, isSelected: String(value) === enumeration}];
108 }
109 return Object.keys(enumeration).map(enumName => {
110 let enumValue = enumName;
111 // warn we only support named enums and systematically ignore enum values
112 //const enumObj = enumeration[enumName];
113 //if (enumObj) {
114 // enumValue = enumObj.value || enumName;
115 //}
116 return {name: enumName, value: enumValue, isSelected: String(enumValue) === String(value)};
117 });
118 },
119 getLeafRef(property = {}, path, value, fullFieldKey, transientCatalogs, container) {
120 const leafRefPath = property['data-type']['leafref']['path'];
121
122 const transientCatalogHash = {};
123
124 transientCatalogs.map((catalog) => {
125 transientCatalogHash[catalog.type + '-catalog'] = {};
126 transientCatalogHash[catalog.type + '-catalog'][catalog.type] = catalog['descriptors'];
127 });
128
129 let leafRefPathValues = utils.resolveLeafRefPath(transientCatalogHash, leafRefPath, fullFieldKey, path, container);
130
131 let leafRefObjects = [];
132
133 leafRefPathValues && leafRefPathValues.map((leafRefPathValue) => {
134 leafRefObjects.push({
135 name: leafRefPathValue,
136 value: leafRefPathValue,
137 isSelected: String(leafRefPathValue) === String(value)
138 });
139 });
140
141 return leafRefObjects;
142 },
143 isGuid(property = {}) {
144 const type = property['data-type'];
145 if (typeof type === 'object' && type.leafref && type.leafref.path) {
146 return /\bid$/.test(type.leafref.path);
147 }
148 return /uuid/.test(property['data-type']);
149 },
150 /**
151 * Create a new instance of the indicated property and, if relevent, use the given
152 * unique name for the instance's key (see generateItemUniqueName)
153 *
154 * @param {Object} typeOrPath - property definition
155 * @param {any} uniqueName
156 * @returns
157 */
158 createModelInstance(property, uniqueName) {
159 const Property = this;
160 const defaultValue = Property.defaultValue.bind(this);
161 function createModel(uiState, parentMeta, uniqueName) {
162 const model = {};
163 if (Property.isLeaf(uiState)) {
164 if (uiState.name === 'name') {
165 return uniqueName || (changeCase.param(parentMeta.name) + '-' + InstanceCounter.count(parentMeta[':qualified-type']));
166 }
167 if (_isArray(parentMeta.key) && _includes(parentMeta.key, uiState.name)) {
168 if (/uuid/.test(uiState['data-type'])) {
169 return guid();
170 }
171 if (uiState['data-type'] === 'string') {
172 // if there is only one key property and we were given a
173 // unique name (probably because creating a list entry
174 // property) then use the unique name otherwise make one up.
175 if (parentMeta.key.length > 1 || !uniqueName) {
176 const prefix = uiState.name.replace('id', '');
177 uniqueName = (prefix ? changeCase.param(prefix) + '-' : '') + guid(5);
178 }
179 return uniqueName;
180 }
181 if (/int/.test(uiState['data-type'])) {
182 return InstanceCounter.count(uiState[':qualified-type']);
183 }
184 }
185 return defaultValue(uiState);
186 } else if (Property.isList(uiState)) {
187 return [];
188 } else {
189 uiState.properties.forEach(p => {
190 model[p.name] = createModel(p, uiState, uniqueName);
191 });
192 }
193 return model;
194 }
195 if (property) {
196 if (Property.isPrimativeDataType(property)) {
197 return defaultValue(property);
198 }
199 if (property.type === 'leaf') {
200 return defaultValue(property);
201 }
202 if (/list/.test(property.type)) {
203 property.type = 'container';
204 }
205 const modelInstance = createModel(property, property, uniqueName);
206 modelInstance.uiState = {type: property.name};
207 const modelFragment = DescriptorTemplateFactory.createModelForType(property[':qualified-type'] || property.name) || {};
208 Object.assign(modelInstance, modelFragment);
209 return modelInstance;
210 }
211 }
212 }