3 * ============LICENSE_START=======================================================
4 * Copyright (C) 2022 Nordix Foundation.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * SPDX-License-Identifier: Apache-2.0
19 * ============LICENSE_END=========================================================
22 import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
23 import {DataTypeModel} from '../../../../../../../models/data-types';
24 import {SchemaPropertyGroupModel} from '../../../../../../../models/schema-property';
25 import {DerivedPropertyType, PropertyBEModel} from '../../../../../../../models/properties-inputs/property-be-model';
26 import {PROPERTY_DATA, PROPERTY_TYPES} from '../../../../../../../utils/constants';
27 import {ToscaFunction} from '../../../../../../../models/tosca-function';
28 import {ToscaFunctionValidationEvent} from "../../../../../../../ng2/pages/properties-assignment/tosca-function/tosca-function.component";
29 import {InstanceFeDetails} from "../../../../../../../models/instance-fe-details";
32 selector: 'app-input-list-item',
33 templateUrl: './input-list-item.component.html',
34 styleUrls: ['./input-list-item.component.less']
36 export class InputListItemComponent implements OnInit {
38 @Input() valueObjRef: any;
39 @Input() name: string;
40 @Input() dataTypeMap: Map<string, DataTypeModel>;
41 @Input() type: DataTypeModel;
42 @Input() schema: SchemaPropertyGroupModel;
43 @Input() nestingLevel: number;
44 @Input() isListChild: boolean = false;
45 @Input() isMapChild: boolean = false;
46 @Input() showToscaFunctionOption: boolean = false;
47 @Input() listIndex: number;
48 @Input() isViewOnly: boolean;
49 @Input() allowDeletion: boolean = false;
50 @Input() toscaFunction: ToscaFunction;
51 @Input() componentInstanceMap: Map<string, InstanceFeDetails> = new Map();
52 @Output('onValueChange') onValueChangeEvent: EventEmitter<any> = new EventEmitter<any>();
53 @Output('onDelete') onDeleteEvent: EventEmitter<string> = new EventEmitter<string>();
54 @Output('onChildListItemDelete') onChildListItemDeleteEvent: EventEmitter<number> = new EventEmitter<number>();
56 isExpanded: boolean = false;
58 isToscaFunction: boolean = false;
59 property: PropertyBEModel;
62 if (!this.nestingLevel) {
63 this.nestingLevel = 0;
65 if (this.type.properties) {
66 this.type.properties.forEach(property => {
67 this.initEmptyPropertyInValueObjRef(property);
71 this.property = new PropertyBEModel();
72 this.property.type = this.type.name;
74 this.property.schema = this.schema;
75 this.property.schemaType = this.schema.property.type;
77 if (this.toscaFunction) {
78 this.property.toscaFunction = this.toscaFunction;
79 this.valueObjRef = this.toscaFunction.value;
80 this.isToscaFunction = true;
84 private initEmptyPropertyInValueObjRef(property: PropertyBEModel) {
85 if (this.valueObjRef[property.name] == undefined) {
86 if (this.isTypeComplex(property.type) || this.isTypeMap(property.type)) {
87 this.valueObjRef[property.name] = {};
88 } else if (this.isTypeList(property.type) || this.isTypeRange(property.type)) {
89 this.valueObjRef[property.name] = [];
91 this.valueObjRef[property.name] = null;
96 getType(typeName: string): DerivedPropertyType {
97 if (PROPERTY_DATA.SIMPLE_TYPES.indexOf(typeName) > -1) {
98 return DerivedPropertyType.SIMPLE;
99 } else if (typeName === PROPERTY_TYPES.LIST) {
100 return DerivedPropertyType.LIST;
101 } else if (typeName === PROPERTY_TYPES.MAP) {
102 return DerivedPropertyType.MAP;
103 } else if (typeName === PROPERTY_TYPES.RANGE) {
104 return DerivedPropertyType.RANGE;
106 return DerivedPropertyType.COMPLEX;
110 isTypeWithoutProperties(typeName: string): boolean {
111 if (this.dataTypeMap.get(typeName) === undefined) {
114 return this.dataTypeMap.get(typeName).properties === undefined ||
115 this.dataTypeMap.get(typeName).properties.length == 0;
118 isTypeDerivedFromSimple(typeName: string): boolean {
119 if (typeName === undefined) {
122 if (this.dataTypeMap.get(typeName) !== undefined) {
123 if (this.isTypeRange(typeName)) {
126 if (this.dataTypeMap.get(typeName).derivedFromName == PROPERTY_DATA.ROOT_DATA_TYPE) {
128 } else if (PROPERTY_DATA.SIMPLE_TYPES.indexOf(this.dataTypeMap.get(typeName).derivedFromName) > -1) {
131 return this.isTypeDerivedFromSimple(this.dataTypeMap.get(typeName).derivedFromName);
137 isTypeSimple(typeName: string): boolean {
138 if (this.getType(typeName) == DerivedPropertyType.SIMPLE) {
141 return this.isTypeDerivedFromSimple(typeName) && (this.isTypeWithoutProperties(typeName));
144 isTypeRange(typeName: string): boolean {
145 return this.getType(typeName) == DerivedPropertyType.RANGE;
148 isTypeList(typeName: string): boolean {
149 return this.getType(typeName) == DerivedPropertyType.LIST;
152 isTypeMap(typeName: string): boolean {
153 return this.getType(typeName) == DerivedPropertyType.MAP;
156 isTypeComplex(typeName: string): boolean {
157 return !this.isTypeSimple(typeName) && !this.isTypeList(typeName) && !this.isTypeMap(typeName) && !this.isTypeRange(typeName);
160 expandAndCollapse() {
161 this.isExpanded = !this.isExpanded;
164 getDataType(type: string) {
165 return this.dataTypeMap.get(type);
168 onValueTypeChange () {
169 if ( !this.isToscaFunction ) {
170 this.onValueChange(this.valueObjRef);
174 onToscaFunctionValidityChange(validationEvent: ToscaFunctionValidationEvent):void {
175 if (validationEvent.isValid) {
176 this.emitValueChangeEvent(validationEvent.toscaFunction, true);
179 this.emitValueChangeEvent(undefined, true);
182 onValueChange(value: any): void {
183 if (this.isNumber(this.type.name)) {
184 this.emitValueChangeEvent(this.parseNumber(value));
187 if (this.type.name == PROPERTY_TYPES.BOOLEAN) {
188 this.emitValueChangeEvent(this.parseBoolean(value));
191 this.emitValueChangeEvent(value);
194 onListValueChange(): void {
195 this.emitValueChangeEvent(this.valueObjRef);
198 onPropertyValueChange($event: any) {
199 this.valueObjRef[$event.name] = $event.value;
200 this.emitValueChangeEvent(this.valueObjRef);
203 private emitValueChangeEvent(value: any, isToscaFunction=false) {
207 isToscaFunction:isToscaFunction
209 this.onValueChangeEvent.emit(emitValue);
213 return this.nestingLevel === 0;
216 showListItemDelete(): boolean {
217 return !this.isViewOnly && (this.isListChild && this.nestingLevel > 0);
220 showInputDelete(): boolean {
221 return this.allowDeletion && !this.isViewOnly && (this.isRoot() || this.isMapChild);
224 resolveType(): string {
225 if (this.isTypeList(this.type.name)) {
226 return `list of value type ${this.schema.property.type}`
228 if (this.isTypeMap(this.type.name)) {
229 return `map of 'string' keys and '${this.schema.property.type}' values`
231 return this.type.name;
235 this.onDeleteEvent.emit(this.name);
238 onListItemDelete(index: number): void {
239 this.valueObjRef.splice(index, 1);
240 this.emitValueChangeEvent(this.valueObjRef);
244 if (!this.valueObjRef) {
245 this.valueObjRef = [];
247 if (this.isTypeSimple(this.schema.property.type)) {
248 this.valueObjRef.push('');
249 } else if (this.isTypeComplex(this.schema.property.type) || this.isTypeMap(this.schema.property.type)) {
250 this.valueObjRef.push({});
251 } else if (this.isTypeList(this.schema.property.type)) {
252 this.valueObjRef.push([]);
256 trackByIndex(index: number, value: string): number {
260 onChildListItemDelete() {
261 this.onChildListItemDeleteEvent.emit(this.listIndex);
264 getObjectEntries(valueObjRef: object) {
265 return Object.keys(valueObjRef);
269 this.emitValueChangeEvent(this.valueObjRef);
272 onMapKeyDelete(key: string) {
273 delete this.valueObjRef[key]
274 this.emitValueChangeEvent(this.valueObjRef);
279 if (this.mapEntryName) {
280 newKey = this.mapEntryName.trim();
285 if (Object.keys(this.valueObjRef).indexOf(newKey) !== -1) {
288 this.mapEntryName = '';
289 if (this.isTypeSimple(this.schema.property.type)) {
290 this.valueObjRef[newKey] = '';
291 } else if (this.isTypeComplex(this.schema.property.type) || this.isTypeMap(this.schema.property.type)) {
292 this.valueObjRef[newKey] = {};
293 } else if (this.isTypeList(this.schema.property.type)) {
294 this.valueObjRef[newKey] = [];
296 this.emitValueChangeEvent(this.valueObjRef);
299 getSimpleValueInputType() {
300 if (this.isNumber(this.type.name)){
306 isNumber(type: string): boolean {
307 return type === PROPERTY_TYPES.INTEGER || type === PROPERTY_TYPES.FLOAT;
310 private parseBoolean(value: any) {
311 if (value === 'true') {
314 if (value === 'false') {
320 private parseNumber(value: any) {
321 const number = parseInt(value);
322 return isNaN(number) ? null : number;