From: JvD_Ericsson Date: Thu, 27 Oct 2022 11:47:28 +0000 (+0100) Subject: Support addition of scalar type constraints X-Git-Tag: 1.12.1~62 X-Git-Url: https://gerrit.onap.org/r/gitweb?p=sdc.git;a=commitdiff_plain;h=0d708e3bb2502abe50e1ed4069b43536b538ceef Support addition of scalar type constraints this also supports the addition of the in_range and the valid_values constraints, and supports delete and editing of current and added constraints Issue-ID: SDC-4223 Change-Id: I5ffb4d17d9f8c2730f650153fb4ff89eccfdd474 Signed-off-by: JvD_Ericsson --- diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/PropertyOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/PropertyOperation.java index cd87dd4fe7..b54b401eb0 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/PropertyOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/PropertyOperation.java @@ -33,8 +33,10 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; import com.google.gson.JsonParser; +import com.google.gson.JsonPrimitive; import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; +import com.google.gson.JsonSyntaxException; import fj.data.Either; import java.io.IOException; import java.lang.reflect.InvocationTargetException; @@ -2143,6 +2145,10 @@ public class PropertyOperation extends AbstractOperation implements IPropertyOpe GreaterThanConstraint greaterThanConstraint = (GreaterThanConstraint) src; jsonArray.add(JsonParser.parseString(greaterThanConstraint.getGreaterThan())); result.add("greaterThan", jsonArray); + } else if (src instanceof LessThanConstraint) { + LessThanConstraint lessThanConstraint = (LessThanConstraint) src; + jsonArray.add(JsonParser.parseString(lessThanConstraint.getLessThan())); + result.add("lessThan", jsonArray); } else if (src instanceof LessOrEqualConstraint) { LessOrEqualConstraint lessOrEqualConstraint = (LessOrEqualConstraint) src; jsonArray.add(JsonParser.parseString(lessOrEqualConstraint.getLessOrEqual())); @@ -2185,8 +2191,9 @@ public class PropertyOperation extends AbstractOperation implements IPropertyOpe if (value != null) { if (value instanceof JsonArray) { JsonArray rangeArray = (JsonArray) value; - if (rangeArray.size() != 2) { + if (rangeArray.size() != 2 || rangeArray.contains(new JsonPrimitive(""))) { log.error("The range constraint content is invalid. value = {}", value); + throw new JsonSyntaxException("The range constraint content is invalid"); } else { InRangeConstraint rangeConstraint = new InRangeConstraint(); String minValue = rangeArray.get(0).getAsString(); @@ -2248,8 +2255,9 @@ public class PropertyOperation extends AbstractOperation implements IPropertyOpe case VALID_VALUES: if (value != null) { JsonArray rangeArray = (JsonArray) value; - if (rangeArray.size() == 0) { + if (rangeArray.size() == 0 || rangeArray.contains(new JsonPrimitive(""))) { log.error("The valid values constraint content is invalid. value = {}", value); + throw new JsonSyntaxException("The valid values constraint content is invalid"); } else { ValidValuesConstraint vvConstraint = new ValidValuesConstraint(); List validValues = new ArrayList<>(); @@ -2426,7 +2434,6 @@ public class PropertyOperation extends AbstractOperation implements IPropertyOpe return null; } - } } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/LessThanConstraint.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/LessThanConstraint.java index d0bea82157..740ee8b544 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/LessThanConstraint.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/LessThanConstraint.java @@ -35,7 +35,6 @@ import org.openecomp.sdc.be.model.tosca.constraints.exception.PropertyConstraint public class LessThanConstraint extends AbstractComparablePropertyConstraint { @NotNull - @Getter private String lessThan; @Override diff --git a/catalog-ui/src/app/directives/property-types/type-map/type-map-directive.html b/catalog-ui/src/app/directives/property-types/type-map/type-map-directive.html index 139f1f4220..d84ec821de 100644 --- a/catalog-ui/src/app/directives/property-types/type-map/type-map-directive.html +++ b/catalog-ui/src/app/directives/property-types/type-map/type-map-directive.html @@ -15,7 +15,7 @@ --> -
+
diff --git a/catalog-ui/src/app/directives/property-types/type-map/type-map-directive.less b/catalog-ui/src/app/directives/property-types/type-map/type-map-directive.less index 6dc481dd26..9c2984e3ce 100644 --- a/catalog-ui/src/app/directives/property-types/type-map/type-map-directive.less +++ b/catalog-ui/src/app/directives/property-types/type-map/type-map-directive.less @@ -86,3 +86,7 @@ } } } + +.type-map { + display: inline-block; +} diff --git a/catalog-ui/src/app/models/properties.ts b/catalog-ui/src/app/models/properties.ts index e292a6ceef..91245967b0 100644 --- a/catalog-ui/src/app/models/properties.ts +++ b/catalog-ui/src/app/models/properties.ts @@ -61,6 +61,7 @@ export class PropertyModel extends PropertyBEModel implements IPropertyModel { uniqueId:string; name:string; constraints:Array; + propertyConstraints:Array; defaultValue:string; description:string; password:boolean; diff --git a/catalog-ui/src/app/modules/directive-module.ts b/catalog-ui/src/app/modules/directive-module.ts index e339b5d471..adc88cbc6d 100644 --- a/catalog-ui/src/app/modules/directive-module.ts +++ b/catalog-ui/src/app/modules/directive-module.ts @@ -327,7 +327,7 @@ directiveModule.directive('toscaFunction', downgradeComponent({ directiveModule.directive('appConstraints', downgradeComponent({ component: ConstraintsComponent, - inputs: ['property', 'isViewOnly'], + inputs: ['propertyConstraints', 'isViewOnly', 'propertyType'], outputs: ['onConstraintChange'] }) as angular.IDirectiveFactory); diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/constraints/constraints.component.html b/catalog-ui/src/app/ng2/pages/properties-assignment/constraints/constraints.component.html index 301d196d41..6272a4529f 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/constraints/constraints.component.html +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/constraints/constraints.component.html @@ -21,7 +21,7 @@
-
+
@@ -44,13 +46,13 @@
@@ -62,11 +64,11 @@ [ngClass]="{'disabled': isViewOnly}" (click)="addToList(constraintIndex)">Add to List
-
+
+ (input)="onChangeConstrainValueIndex(constraintIndex, $event.target.value, valueIndex)"/>
@@ -76,7 +78,7 @@
@@ -89,9 +91,8 @@
-
Add Constraint
-
- +
Add Constraint
+
diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/constraints/constraints.component.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/constraints/constraints.component.ts index ef4d6fd954..2e56ce1580 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/constraints/constraints.component.ts +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/constraints/constraints.component.ts @@ -18,7 +18,7 @@ */ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; -import { PropertyBEModel } from "app/models"; +import { PROPERTY_DATA, PROPERTY_TYPES } from "app/utils/constants" @Component({ selector: 'app-constraints', @@ -27,24 +27,31 @@ import { PropertyBEModel } from "app/models"; }) export class ConstraintsComponent implements OnInit { - @Input() set property(property: PropertyBEModel) { + @Input() set propertyConstraints(propertyConstraints: any[]) { this.constraints = new Array(); - if(property.constraints) { - this._property = property; - property.constraints.forEach((constraint: any) => { + if(propertyConstraints) { + propertyConstraints.forEach((constraint: any) => { this.constraints.push(this.getConstraintFromPropertyBEModel(constraint)); }); } } + @Input() set propertyType(propertyType: string) { + if (!this._propertyType || propertyType == this._propertyType) { + this._propertyType = propertyType; + return; + } + this.constraints = new Array(); + this._propertyType = propertyType; + this.emitOnConstraintChange(); + } @Input() isViewOnly: boolean = false; - @Output() onConstraintChange: EventEmitter = new EventEmitter(); + @Output() onConstraintChange: EventEmitter = new EventEmitter(); - constraints: Constraint[]; + constraints: Constraint[] = new Array(); constraintTypes: string[]; ConstraintTypesMapping = ConstraintTypesMapping; - newConstraintType: any = ConstraintTypes.equal; - newConstraintValue: any = null; - _property: PropertyBEModel; + valid: boolean = true; + _propertyType: string; ngOnInit() { this.constraintTypes = Object.keys(ConstraintTypes).map(key => ConstraintTypes[key]); @@ -53,37 +60,43 @@ export class ConstraintsComponent implements OnInit { private getConstraintFromPropertyBEModel(constraint: any):Constraint { let constraintType: ConstraintTypes; let constraintValue: any; - if(constraint.validValues){ + if (!constraint) { + constraintType = ConstraintTypes.null; + constraintValue = ""; + } else if(constraint.hasOwnProperty(ConstraintTypes.valid_values)){ constraintType = ConstraintTypes.valid_values; constraintValue = constraint.validValues; - } else if(constraint.equal) { + } else if(constraint.hasOwnProperty(ConstraintTypes.equal)) { constraintType = ConstraintTypes.equal; constraintValue = constraint.equal; - } else if(constraint.greaterThan) { + } else if(constraint.hasOwnProperty(ConstraintTypes.greater_than)) { constraintType = ConstraintTypes.greater_than; constraintValue = constraint.greaterThan; - } else if(constraint.greaterOrEqual) { + } else if(constraint.hasOwnProperty(ConstraintTypes.greater_or_equal)) { constraintType = ConstraintTypes.greater_or_equal; constraintValue = constraint.greaterOrEqual; - } else if(constraint.lessThan) { + } else if(constraint.hasOwnProperty(ConstraintTypes.less_than)) { constraintType = ConstraintTypes.less_than; constraintValue = constraint.lessThan; - } else if(constraint.lessOrEqual) { + } else if(constraint.hasOwnProperty(ConstraintTypes.less_or_equal)) { constraintType = ConstraintTypes.less_or_equal; constraintValue = constraint.lessOrEqual; - } else if(constraint.rangeMinValue && constraint.rangeMaxValue) { + } else if(constraint.hasOwnProperty(ConstraintTypes.in_range)) { + constraintType = ConstraintTypes.in_range; + constraintValue = new Array(constraint.inRange[0], constraint.inRange[1]); + } else if(constraint.rangeMaxValue || constraint.rangeMinValue) { constraintType = ConstraintTypes.in_range; constraintValue = new Array(constraint.rangeMinValue, constraint.rangeMaxValue); - } else if(constraint.length) { + } else if(constraint.hasOwnProperty(ConstraintTypes.length)) { constraintType = ConstraintTypes.length; constraintValue = constraint.length; - } else if(constraint.minLength) { + } else if(constraint.hasOwnProperty(ConstraintTypes.min_length)) { constraintType = ConstraintTypes.min_length; constraintValue = constraint.minLength; - } else if(constraint.maxLength) { + } else if(constraint.hasOwnProperty(ConstraintTypes.max_length)) { constraintType = ConstraintTypes.max_length; constraintValue = constraint.maxLength; - } else if(constraint.pattern) { + } else if(constraint.hasOwnProperty(ConstraintTypes.pattern)) { constraintType = ConstraintTypes.pattern; constraintValue = constraint.pattern; } @@ -101,7 +114,7 @@ export class ConstraintsComponent implements OnInit { return constraintArray; } - private getConstraintFormat(constraint: Constraint) { + private getConstraintFormat(constraint: Constraint): any { switch (constraint.type) { case ConstraintTypes.equal: return { @@ -152,8 +165,34 @@ export class ConstraintsComponent implements OnInit { } } + private validateConstraints(): void { + this.valid = this.constraints.every((constraint: Constraint) => { + if (Array.isArray(constraint.value)) { + return !(constraint.value.length == 0 || this.doesArrayContaintEmptyValues(constraint.value)); + } + return constraint.value && constraint.type != ConstraintTypes.null + }); + } + + private doesArrayContaintEmptyValues(arr) { + for(const element of arr) { + if(element === "") return true; + } + return false; + } + + private emitOnConstraintChange(): void { + this.validateConstraints(); + const newConstraints = this.getConstraintsFormat(); + this.onConstraintChange.emit({ + constraints: newConstraints, + valid: this.valid + }); + } + removeFromList(constraintIndex: number, valueIndex: number){ this.constraints[constraintIndex].value.splice(valueIndex, 1); + this.emitOnConstraintChange() } addToList(constraintIndex: number){ @@ -161,6 +200,7 @@ export class ConstraintsComponent implements OnInit { this.constraints[constraintIndex].value = new Array(); } this.constraints[constraintIndex].value.push(""); + this.emitOnConstraintChange() } onChangeConstraintType(constraintIndex: number, newType: ConstraintTypes) { @@ -168,10 +208,12 @@ export class ConstraintsComponent implements OnInit { if ((newType == ConstraintTypes.in_range || newType == ConstraintTypes.valid_values) && !Array.isArray(this.constraints[constraintIndex].value)) { this.constraints[constraintIndex].value = new Array() } + this.emitOnConstraintChange(); } onChangeConstraintValue(constraintIndex: number, newValue: any) { this.constraints[constraintIndex].value = newValue; + this.emitOnConstraintChange(); } onChangeConstrainValueIndex(constraintIndex: number, newValue: any, valueIndex: number) { @@ -179,21 +221,21 @@ export class ConstraintsComponent implements OnInit { this.constraints[constraintIndex].value = new Array(); } this.constraints[constraintIndex].value[valueIndex] = newValue; + this.emitOnConstraintChange(); } removeConstraint(constraintIndex: number) { this.constraints.splice(constraintIndex, 1); - this.onConstraintChange.emit(this.getConstraintsFormat()); + this.emitOnConstraintChange(); } addConstraint() { let newConstraint: Constraint = { - type:this.newConstraintType, - value: this.newConstraintValue + type: ConstraintTypes.null, + value: "" } this.constraints.push(newConstraint); - this.newConstraintValue = null; - this.onConstraintChange.emit(this.getConstraintsFormat()); + this.emitOnConstraintChange(); } getInRangeValue(constraintIndex: number, valueIndex: number): string { @@ -203,9 +245,62 @@ export class ConstraintsComponent implements OnInit { return this.constraints[constraintIndex].value[valueIndex]; } + disableConstraint(optionConstraintType: ConstraintTypes): boolean { + const invalid = this.notAllowedConstraint(optionConstraintType); + return invalid ? invalid : this.getConstraintTypeIfPresent(optionConstraintType) ? true : false; + } + + notAllowedConstraint(optionConstraintType: ConstraintTypes): boolean { + switch (optionConstraintType) { + case ConstraintTypes.less_or_equal: + case ConstraintTypes.less_than: + case ConstraintTypes.greater_or_equal: + case ConstraintTypes.greater_than: + case ConstraintTypes.in_range: + if (this.isComparable(this._propertyType)){ + return false; + } + break; + case ConstraintTypes.length: + case ConstraintTypes.max_length: + case ConstraintTypes.min_length: + if (this._propertyType == PROPERTY_TYPES.STRING || this._propertyType == PROPERTY_TYPES.MAP || this._propertyType == PROPERTY_TYPES.LIST){ + return false; + } + break; + case ConstraintTypes.pattern: + if (this._propertyType == PROPERTY_TYPES.STRING){ + return false; + } + break; + case ConstraintTypes.valid_values: + case ConstraintTypes.equal: + return false; + } + return true; + } + + getConstraintTypeIfPresent(constraintType: ConstraintTypes): Constraint { + return this.constraints.find((constraint) => { + return constraint.type == constraintType ? true : false; + }) + } + + trackByFn(index) { + return index; + } + + isComparable(propType: string): boolean { + if (PROPERTY_DATA.COMPARABLE_TYPES.indexOf(propType) >= 0) { + return true; + } + return false; + } + } export enum ConstraintTypes { + null = "", equal= "equal", greater_than = "greaterThan", greater_or_equal = "greaterOrEqual", @@ -236,5 +331,4 @@ export const ConstraintTypesMapping = { export interface Constraint { type:ConstraintTypes, value:any - } \ No newline at end of file diff --git a/catalog-ui/src/app/utils/constants.ts b/catalog-ui/src/app/utils/constants.ts index c8fb1966b4..173486c2f0 100644 --- a/catalog-ui/src/app/utils/constants.ts +++ b/catalog-ui/src/app/utils/constants.ts @@ -162,6 +162,7 @@ export class PROPERTY_DATA { public static OPENECOMP_ROOT = "org.openecomp.datatypes.Root"; public static SUPPLEMENTAL_DATA = "supplemental_data"; public static SOURCES = [SOURCES.A_AND_AI, SOURCES.ORDER, SOURCES.RUNTIME]; + public static COMPARABLE_TYPES = [PROPERTY_TYPES.STRING, PROPERTY_TYPES.INTEGER, PROPERTY_TYPES.FLOAT, PROPERTY_TYPES.TIMESTAMP, PROPERTY_TYPES.SCALAR, PROPERTY_TYPES.SCALAR_FREQUENCY, PROPERTY_TYPES.SCALAR_SIZE, PROPERTY_TYPES.SCALAR_TIME]; } export class PROPERTY_VALUE_CONSTRAINTS { diff --git a/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view-model.ts b/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view-model.ts index 614f1583cb..eda5efcd49 100644 --- a/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view-model.ts +++ b/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view-model.ts @@ -69,6 +69,7 @@ interface IPropertyFormViewModelScope extends ng.IScope { constraints:string[]; modelNameFilter:string; isGetFunctionValueType: boolean; + invalidMandatoryFields: boolean; validateJson(json:string):boolean; save(doNotCloseModal?:boolean):void; @@ -404,17 +405,21 @@ export class PropertyFormViewModel { this.$scope.$watch("forms.editForm.$invalid", (newVal) => { if (this.$scope.editPropertyModel.hasGetFunctionValue) { - this.$scope.footerButtons[0].disabled = newVal || !this.$scope.editPropertyModel.property.toscaFunction || this.isViewOnly; + this.$scope.invalidMandatoryFields = !newVal || !this.$scope.editPropertyModel.property.toscaFunction || this.isViewOnly; + this.$scope.footerButtons[0].disabled = this.$scope.invalidMandatoryFields; } else { - this.$scope.footerButtons[0].disabled = newVal || this.isViewOnly; + this.$scope.invalidMandatoryFields = !newVal || this.isViewOnly; + this.$scope.footerButtons[0].disabled = this.$scope.invalidMandatoryFields; } }); this.$scope.$watch("forms.editForm.$valid", (newVal) => { if (this.$scope.editPropertyModel.hasGetFunctionValue) { - this.$scope.footerButtons[0].disabled = !newVal || !this.$scope.editPropertyModel.property.toscaFunction || this.isViewOnly; + this.$scope.invalidMandatoryFields = !newVal || !this.$scope.editPropertyModel.property.toscaFunction || this.isViewOnly; + this.$scope.footerButtons[0].disabled = this.$scope.invalidMandatoryFields; } else { - this.$scope.footerButtons[0].disabled = !newVal || this.isViewOnly; + this.$scope.invalidMandatoryFields = !newVal || this.isViewOnly; + this.$scope.footerButtons[0].disabled = this.$scope.invalidMandatoryFields; } }); @@ -460,6 +465,21 @@ export class PropertyFormViewModel { } } + this.$scope.onConstraintChange = (constraints: any): void => { + if (!this.$scope.invalidMandatoryFields) { + this.$scope.footerButtons[0].disabled = !constraints.valid; + } else { + this.$scope.footerButtons[0].disabled = this.$scope.invalidMandatoryFields; + } + if (!constraints.constraints || constraints.constraints.length == 0) { + this.$scope.editPropertyModel.property.propertyConstraints = null; + this.$scope.editPropertyModel.property.constraints = null; + return; + } + this.$scope.editPropertyModel.property.propertyConstraints = this.serializePropertyConstraints(constraints.constraints); + this.$scope.editPropertyModel.property.constraints = constraints.constraints; + } + this.$scope.onGetFunctionValidFunction = (toscaGetFunction: ToscaGetFunction): void => { this.$scope.editPropertyModel.property.toscaFunction = toscaGetFunction; } @@ -471,9 +491,19 @@ export class PropertyFormViewModel { } this.$scope.editPropertyModel.isGetFunctionValid = undefined; } - }; + private serializePropertyConstraints(constraints: any[]): string[] { + if (constraints) { + let stringConstrsints = new Array(); + constraints.forEach((constraint) => { + stringConstrsints.push(JSON.stringify(constraint)); + }) + return stringConstrsints; + } + return null; + } + private setEmptyValue() { const property1 = this.$scope.editPropertyModel.property; property1.value = undefined; diff --git a/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view.html b/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view.html index 35e3932586..2f67474d4f 100644 --- a/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view.html +++ b/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view.html @@ -264,8 +264,9 @@
-