RIFT-14705 - UI Composer: Add IVLD to VNFD is broken
[osm/UI.git] / skyquake / plugins / composer / src / src / libraries / model / DescriptorModel.js
1
2 /*
3 *
4 * Copyright 2016 RIFT.IO Inc
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * 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 */
19 /**
20 * Created by onvelocity on 8/23/15.
21 */
22
23 import _ from 'lodash'
24 import guid from '../guid'
25 import Position from '../graph/Position'
26 import IconFactory from './IconFactory'
27 import SelectionManager from '../SelectionManager'
28 import DescriptorModelMetaFactory from './DescriptorModelMetaFactory'
29
30 /**
31 * Abstract base class for the CONFD MANO Descriptors as defined by the Rift.ware YANG configuration files.
32 *
33 * Sub-classes should specify the type and qualified-type properties.
34 */
35 export default class DescriptorModel {
36
37 constructor(model = {uiState: {}}, parent = null) {
38 // when our instance has no more strong references
39 // then our properties will get garbage collected.
40 this._props_ = new WeakMap();
41 this._props_.set(this, {
42 position: new Position(),
43 children: new Set(),
44 values: {},
45 model: model
46 });
47 this.className = 'DescriptorModel';
48 this.uid = this.uid || guid();
49 if (parent instanceof DescriptorModel) {
50 parent.addChild(this);
51 }
52 }
53
54 get fieldNames() {
55 return DescriptorModelMetaFactory.getModelFieldNamesForType(this.uiState['qualified-type'] || this.type);
56 }
57
58 get property() {
59 return DescriptorModelMetaFactory.getModelMetaForType(this.uiState['qualified-type'] || this.type);
60 }
61
62 get model() {
63 let model = this._props_.get(this).model;
64 if (!model) {
65 model = this.model = {uiState: {}};
66 }
67 return model;
68 }
69
70 set model(model) {
71 this._props_.get(this).model = model;
72 return this;
73 }
74
75 get uiState() {
76 return this.model.uiState = this.model.uiState || {};
77 }
78
79 set uiState(uiState) {
80 this.model.uiState = uiState;
81 return this;
82 }
83
84 get uid() {
85 return this.uiState[':uid'];
86 }
87
88 set uid(uid) {
89 this.uiState[':uid'] = uid;
90 return this;
91 }
92
93 get key() {
94 return this.id;
95 }
96
97 // key is read only by design
98
99 get id() {
100 return this.model.id;
101 }
102
103 set id(id) {
104 this.model.id = id;
105 return this;
106 }
107
108 get title() {
109 return this.model['short-name'] || this.model.name || this.key;
110 }
111
112 // title is read only by design
113
114 get name() {
115 return this.model.name;
116 }
117
118 set name(name) {
119 this.model.name = name;
120 }
121
122 get 'short-name'() {
123 return this.model['short-name'];
124 }
125
126 set 'short-name'(name) {
127 this.model['short-name'] = name;
128 }
129
130 get type() {
131 return this.uiState.type;
132 }
133
134 set type(type) {
135 this.uiState.type = type;
136 return this;
137 }
138
139 get qualifiedType() {
140 return this.uiState['qualified-type'] || this.type;
141 }
142
143 set qualifiedType(type) {
144 this.uiState['qualified-type'] = type;
145 }
146
147 get position() {
148 return this._props_.get(this).position;
149 }
150
151 set position(position) {
152 if (!(position instanceof Position)) {
153
154 }
155 this._props_.get(this).position = position;
156 return this;
157 }
158
159 get location() {
160 return this.uiState.location;
161 }
162
163 set location(v) {
164 this.uiState.location = v;
165 }
166
167 get children() {
168 return Array.from(this._props_.get(this).children);
169 }
170
171 addProp(name, value) {
172 this._props_.get(this).values[name] = value;
173 return this;
174 }
175
176 getProp(name) {
177 return this._props_.get(this).values[name];
178 }
179
180 addChild(child) {
181 if (!child instanceof DescriptorModel) {
182 throw new ReferenceError('child must be an instance of DescriptorModel class');
183 }
184 if (this.findChildByUid(child.uid)) {
185 console.warn('Child already exists');
186 // NOTE: Commented out this line because it was causing issues with Internal VLD.
187 // TODO: Check why it caused issues with Internal VLD
188 // throw new ReferenceError('child already exists');
189 }
190 if (child.parent instanceof DescriptorModel) {
191 throw new ReferenceError('child already has a parent');
192 }
193 child.parent = this;
194 this._props_.get(this).children.add(child);
195 }
196
197 findChildByUid(uid) {
198 // uid can be a DescriptorModel instance, JSON model object, or a uid string
199 if (typeof uid === 'object') {
200 uid = uid.uiState && uid.uiState[':uid'];
201 }
202 if (typeof uid === 'string') {
203 return this.children.filter(d => d.uid === uid)[0];
204 }
205 }
206
207 removeChild(child) {
208 let uid;
209 // warn don't clear parent so that removed ones can get to root for updating the catalog json model
210 //child.parent = null;
211 // uid can be a DescriptorModel instance, JSON model object, or a uid string
212 if (typeof uid === 'object') {
213 uid = uid.uiState && uid.uiState[':uid'];
214 }
215 if (typeof uid === 'string') {
216 this.children.filter(d => d.uid === uid).forEach(d => this._props_.get(this).children.delete(d));
217 } else {
218 this._props_.get(this).children.delete(child);
219 }
220 }
221
222 getRoot() {
223 let root = this;
224 while (root && root.parent) {
225 root = root.parent;
226 }
227 return root;
228 }
229
230 getRootNSDContainer() {
231 let container = this.parent;
232 while(container) {
233 if (container.type === 'nsd') {
234 return container;
235 }
236 container = container.parent;
237 }
238 }
239
240 setPosition(position) {
241 this.position = new Position(position);
242 }
243
244 get selected() {
245 return SelectionManager.isSelected(this);
246 }
247
248 get colors() {
249 return this.uiState.colors || {primary: 'black', secondary: 'white'};
250 }
251
252 set colors(colors) {
253 this.uiState.colors = colors;
254 }
255
256 get icon() {
257 return IconFactory.getIconForType(this.type);
258 }
259
260 get width() {
261 return this.position.width;
262 }
263
264 get height() {
265 return this.position.height;
266 }
267
268 get displayData() {
269 return {
270 title: this.title,
271 type: this.model.type,
272 cpNumber: this.cpNumber
273 };
274 }
275
276 valueOf() {
277 return this.model;
278 }
279
280 updateModelList(modelFieldName, modelFieldValue, descriptorClass = DescriptorModel, newItemAddedSuccessCallback = () => {}) {
281 // value can be Array of (DescriptorModel | json model), DescriptorModel, or json model
282 if (_.isArray(modelFieldValue)) {
283 this.model[modelFieldName] = modelFieldValue.map(d => d instanceof descriptorClass ? d.model : d);
284 return true;
285 }
286 const size = this.model[modelFieldName].length;
287 if (modelFieldValue instanceof descriptorClass) {
288 this.model[modelFieldName].push(modelFieldValue.valueOf());
289 newItemAddedSuccessCallback(modelFieldValue);
290 } else if (typeof modelFieldValue === 'object') {
291 this.model[modelFieldName].push(modelFieldValue);
292 newItemAddedSuccessCallback(new descriptorClass(modelFieldValue, this));
293 } else {
294 throw new ReferenceError(`expect object to be either an Array, ${descriptorClass.name} or JSON object`);
295 }
296 return size !== this.model[modelFieldName].length;
297 }
298
299 removeModelListItem(propertyName, child) {
300 // ensure child is a DescriptorModel instance
301 child = this.findChildByUid(child) || child;
302 if (!child) {
303 return false;
304 }
305 this.removeChild(child);
306 const uid = child.uid;
307 const length = this[propertyName].length;
308 this[propertyName] = this[propertyName].filter(d => d.uid !== uid);
309 return length !== this[propertyName].length;
310 }
311
312 }