Support instance count on node template 60/127260/6
authorJvD_Ericsson <jeff.van.dam@est.tech>
Thu, 17 Feb 2022 15:48:20 +0000 (15:48 +0000)
committerMichael Morris <michael.morris@est.tech>
Mon, 14 Mar 2022 14:38:48 +0000 (14:38 +0000)
Issue-ID: SDC-3887
Signed-off-by: JvD_Ericsson <jeff.van.dam@est.tech>
Change-Id: I45593ee2e0e3eea358ae9344d7432e37e1467915

catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java
catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java
catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaNodeTemplate.java
catalog-ui/src/app/models/componentsInstances/componentInstance.ts
catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component.html
catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/properties-tab/properties-tab.component.ts
catalog-ui/src/app/ng2/services/component-services/topology-template.service.ts
common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/ComponentInstanceDataDefinition.java
common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/JsonPresentationFields.java

index 2f712e1..60e2501 100644 (file)
@@ -1265,6 +1265,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
         oldComponentInstance.setDirectives(newComponentInstance.getDirectives());
         oldComponentInstance.setMaxOccurrences(newComponentInstance.getMaxOccurrences());
         oldComponentInstance.setMinOccurrences(newComponentInstance.getMinOccurrences());
+        oldComponentInstance.setInstanceCount(newComponentInstance.getInstanceCount());
         if (oldComponentInstance.getGroupInstances() != null) {
             oldComponentInstance.getGroupInstances().forEach(group -> group.setName(getNewGroupName(oldComponentInstance.getNormalizedName(),
                 ValidationUtils.normalizeComponentInstanceName(newComponentInstance.getName()), group.getName())));
index 5c30d09..586b9f6 100644 (file)
@@ -27,7 +27,13 @@ import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_ATTRIBUTE;
 import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_INPUT;
 import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_PROPERTY;
 
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.gson.JsonParser;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.stream.JsonReader;
 import fj.data.Either;
+import java.io.StringReader;
 import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -104,6 +110,7 @@ import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter;
 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
 import org.openecomp.sdc.be.model.operations.impl.ModelOperation;
+import org.openecomp.sdc.be.model.tosca.converters.ToscaMapValueConverter;
 import org.openecomp.sdc.be.tosca.PropertyConvertor.PropertyType;
 import org.openecomp.sdc.be.tosca.builder.ToscaRelationshipBuilder;
 import org.openecomp.sdc.be.tosca.exception.ToscaConversionException;
@@ -130,6 +137,7 @@ import org.openecomp.sdc.be.tosca.utils.InputConverter;
 import org.openecomp.sdc.be.tosca.utils.OutputConverter;
 import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
 import org.openecomp.sdc.common.log.wrappers.Logger;
+import org.openecomp.sdc.tosca.datatypes.ToscaFunctions;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.yaml.snakeyaml.DumperOptions;
 import org.yaml.snakeyaml.DumperOptions.FlowStyle;
@@ -914,11 +922,19 @@ public class ToscaExportHandler {
                 nodeTemplate.setArtifacts(convertToNodeTemplateArtifacts(componentInstance.getToscaArtifacts()));
             }
             if (componentInstance.getMinOccurrences() != null && componentInstance.getMaxOccurrences()!= null){
-                List<Object> occur = new ArrayList<Object>();
+                List<Object> occur = new ArrayList<>();
                 occur.add(parseToIntIfPossible(componentInstance.getMinOccurrences()));
                 occur.add(parseToIntIfPossible(componentInstance.getMaxOccurrences()));
                 nodeTemplate.setOccurrences(occur);
             }
+            if (componentInstance.getInstanceCount() != null){
+                ObjectMapper objectMapper = new ObjectMapper();
+                Object obj = convertToToscaObject(componentInstance.getInstanceCount());
+                if(obj != null) {
+                    Map<String, String> map = objectMapper.convertValue(obj, Map.class);
+                    nodeTemplate.setInstance_count(map);
+                }
+            }
             nodeTemplate.setType(componentInstance.getToscaComponentName());
             nodeTemplate.setDirectives(componentInstance.getDirectives());
             nodeTemplate.setNode_filter(convertToNodeTemplateNodeFilterComponent(componentInstance.getNodeFilter()));
@@ -1022,12 +1038,33 @@ public class ToscaExportHandler {
         log.debug("finish convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType());
         return convertNodeTemplatesRes;
     }
-  
+
+    public Object convertToToscaObject(String value) {
+        try {
+            ToscaMapValueConverter mapConverterInst = ToscaMapValueConverter.getInstance();
+            JsonParser jsonParser = new JsonParser();
+            StringReader reader = new StringReader(value);
+            JsonReader jsonReader = new JsonReader(reader);
+            jsonReader.setLenient(true);
+            JsonElement jsonElement = jsonParser.parse(jsonReader);
+            if (jsonElement.isJsonObject()) {
+                JsonObject jsonObj = jsonElement.getAsJsonObject();
+                if (jsonObj.entrySet().size() == 1 && jsonObj.has(ToscaFunctions.GET_INPUT.getFunctionName())) {
+                    return mapConverterInst.handleComplexJsonValue(jsonElement);
+                }
+            }
+            return null;
+        } catch (Exception e) {
+            log.debug("convertToToscaValue failed to parse json value :", e);
+            return null;
+        }
+    }
+
     private Object parseToIntIfPossible(final String value) {
         final Integer intValue = Ints.tryParse(value);
         return intValue == null ? value : intValue;
     }
-  
+
     private void handleInstanceInterfaces(
         Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces,
         ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes, ToscaNodeTemplate nodeTemplate,
index 0a75870..6fd660e 100644 (file)
@@ -35,6 +35,7 @@ public class ToscaNodeTemplate {
 
     private String type;
     private List<Object> occurrences;
+    private Map<String, String> instance_count;
     private List<String> directives;
     private Map<String, String> metadata;
     private String description;
index 86411b2..e79c30e 100644 (file)
@@ -96,6 +96,7 @@ export class ComponentInstance implements IComponentInstance{
     public sourceModelUuid:string;
     public minOccurrences: string;
     public maxOccurrences: string;
+    public instanceCount: string;
     //custom properties
     public certified:boolean;
     public iconSprite:string;
@@ -141,6 +142,7 @@ export class ComponentInstance implements IComponentInstance{
             this.interfaces = componentInstance.interfaces;
             this.minOccurrences = componentInstance.minOccurrences;
             this.maxOccurrences = componentInstance.maxOccurrences;
+            this.instanceCount = componentInstance.instanceCount;
         }
     }
 
index 358c910..f7cc937 100644 (file)
                             </div>
                         </div>
                     </div>
-                    <div *ngIf="!isViewOnly && isOccurrencesEnabled" class="i-sdc-designer-sidebar-section-content-item-property-and-attribute">
+                    <div *ngIf="isOccurrencesEnabled" class="i-sdc-designer-sidebar-section-content-item-property-and-attribute">
+                        <div class="sdc-input">
+                            <span class="i-sdc-designer-sidebar-section-content-item-property-and-attribute-label">Instance Count</span>
+                            <div class="instance-count-value">
+                                <ui-element-dropdown
+                                    [testId]="'instanceCount'"
+                                    class="cell link-selector"
+                                    [values]="selectInputs"
+                                    [(value)]="component.instanceCount">
+                                </ui-element-dropdown>
+                            </div>
+                        </div>
+                    </div>
+                    <div *ngIf="!isViewOnly" class="i-sdc-designer-sidebar-section-content-item-property-and-attribute">
                         <button class="tlv-btn blue" (click)="saveOccurrences()" [disabled]="!isOccurrencesFormValid(component)">Save</button>
                     </div>
                 </div>
index 99bd5e8..b6999e6 100644 (file)
@@ -8,14 +8,18 @@ import {
     ComponentMetadata,
     FullComponentInstance,
     PropertiesGroup,
-    PropertyModel
+    PropertyModel,
+    InputsGroup,
+    InputModel
 } from 'app/models';
+import {ToscaGetFunctionType} from "app/models/tosca-get-function-type.enum";
 import { CompositionService } from 'app/ng2/pages/composition/composition.service';
 import { WorkspaceService } from 'app/ng2/pages/workspace/workspace.service';
 import { GroupByPipe } from 'app/ng2/pipes/groupBy.pipe';
 import { ResourceNamePipe } from 'app/ng2/pipes/resource-name.pipe';
 import { TopologyTemplateService } from 'app/ng2/services/component-services/topology-template.service';
 import { ComponentInstanceServiceNg2 } from "app/ng2/services/component-instance-services/component-instance.service";
+import { DropdownValue } from 'app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component';
 import { ComponentGenericResponse } from 'app/ng2/services/responses/component-generic-response';
 import { TranslateService } from 'app/ng2/shared/translator/translate.service';
 import { ModalsHandler } from 'app/utils';
@@ -37,6 +41,8 @@ export class PropertiesTabComponent implements OnInit {
     objectKeys = Object.keys;
     isUnboundedChecked: boolean;
     isOccurrencesEnabled: boolean = false;
+    inputs: InputsGroup;
+    selectInputs: DropdownValue[] = [];
     isLoading: boolean;
 
     @Input() isViewOnly: boolean;
@@ -118,12 +124,13 @@ export class PropertiesTabComponent implements OnInit {
     }
 
     private getComponentInstancesPropertiesAndAttributes = () => {
-        this.topologyTemplateService.getComponentInstanceAttributesAndProperties(
+        this.topologyTemplateService.getComponentInstanceAttributesAndPropertiesAndInputs(
             this.workspaceService.metadata.uniqueId,
             this.workspaceService.metadata.componentType)
             .subscribe((genericResponse: ComponentGenericResponse) => {
                 this.compositionService.componentInstancesAttributes = genericResponse.componentInstancesAttributes || new AttributesGroup();
                 this.compositionService.componentInstancesProperties = genericResponse.componentInstancesProperties;
+                this.inputs = genericResponse.inputs;
                 this.initPropertiesAndAttributes();
             });
     }
@@ -188,6 +195,19 @@ export class PropertiesTabComponent implements OnInit {
                 this.isOccurrencesEnabled = true;
             }
             this.isUnboundedChecked = this.component.maxOccurrences == "UNBOUNDED" ? true: false;
+
+            if(!this.component.instanceCount){
+                this.component.instanceCount = "";
+            }
+
+            _.forEach(this.inputs, (input: InputModel) => {
+                if(input.type === "integer"){
+                    this.selectInputs.push(new DropdownValue('{' + ToscaGetFunctionType.GET_INPUT.toLowerCase + ":" + input.name + '}', input.name));
+                    console.log('{' + ToscaGetFunctionType.GET_INPUT.toLowerCase + ":" + input.name + '}', input.name);
+                }
+            });
+
+            this.selectInputs.unshift(new DropdownValue('', 'Select Input...'));
         }
     }
 
@@ -240,6 +260,7 @@ export class PropertiesTabComponent implements OnInit {
             component = new ComponentInstance(updatedComponentInstance);
             this.compositionService.getComponentInstances().find((item) => item.uniqueId === component.uniqueId).maxOccurrences = component.maxOccurrences;
             this.compositionService.getComponentInstances().find((item) => item.uniqueId === component.uniqueId).minOccurrences = component.minOccurrences;
+            this.compositionService.getComponentInstances().find((item) => item.uniqueId === component.uniqueId).instanceCount = component.instanceCount;
             this.store.dispatch(new TogglePanelLoadingAction({isLoading: false}));
         }, (error:any) => {
             this.store.dispatch(new TogglePanelLoadingAction({isLoading: false}));
@@ -253,18 +274,21 @@ export class PropertiesTabComponent implements OnInit {
             if(!this.isOccurrencesEnabled){
                 this.component.minOccurrences = null;
                 this.component.maxOccurrences = null;
+                this.component.instanceCount = null;
             } else {
                 this.component.minOccurrences = "1";
                 this.component.maxOccurrences = "1";
+                this.component.instanceCount = "";
             }
-            this.updateComponentInstance(this.component);
         }
     }
 
     private isOccurrencesFormValid(component: FullComponentInstance) {
         if(
-            component.minOccurrences && parseInt(component.minOccurrences) >= 0 &&
-            component.maxOccurrences && (parseInt(component.maxOccurrences) >= parseInt(component.minOccurrences) || component.maxOccurrences === "UNBOUNDED")
+            (component.minOccurrences === null && component.maxOccurrences === null && !component.instanceCount) ||
+            (component.minOccurrences && parseInt(component.minOccurrences) >= 0 && component.maxOccurrences &&
+            (parseInt(component.maxOccurrences) >= parseInt(component.minOccurrences) || component.maxOccurrences === "UNBOUNDED") &&
+            component.instanceCount)
         ) {
             return true;
         } else {
@@ -274,6 +298,7 @@ export class PropertiesTabComponent implements OnInit {
 
     private saveOccurrences = () => {
         if(this.component instanceof FullComponentInstance && this.isOccurrencesFormValid(this.component)) {
+            console.log("this.component.instanceCount: " + this.component.instanceCount);
             this.updateComponentInstance(this.component);
         }
     }
index 49f273c..65dbdcc 100644 (file)
@@ -97,6 +97,10 @@ export class TopologyTemplateService {
         return this.getComponentDataByFieldsName(type, uniqueId, [COMPONENT_FIELDS.COMPONENT_INSTANCES_PROPERTIES, COMPONENT_FIELDS.COMPONENT_INSTANCES_ATTRIBUTES]);
     }
 
+    getComponentInstanceAttributesAndPropertiesAndInputs(uniqueId: string, type: string): Observable<ComponentGenericResponse> {
+        return this.getComponentDataByFieldsName(type, uniqueId, [COMPONENT_FIELDS.COMPONENT_INSTANCES_PROPERTIES, COMPONENT_FIELDS.COMPONENT_INSTANCES_ATTRIBUTES, COMPONENT_FIELDS.COMPONENT_INPUTS]);
+    }
+
     async getComponentAttributes(componentType: string, componentId: string): Promise<ComponentGenericResponse> {
         return this.getComponentDataByFieldsName(componentType, componentId, [COMPONENT_FIELDS.COMPONENT_ATTRIBUTES]).toPromise();
     }
index ce8dda0..2d493e4 100644 (file)
@@ -55,6 +55,7 @@ public class ComponentInstanceDataDefinition extends ToscaDataDefinition {
         setPosY(dataDefinition.getPosY());
         setMinOccurrences(dataDefinition.getMinOccurrences());
         setMaxOccurrences(dataDefinition.getMaxOccurrences());
+        setInstanceCount(dataDefinition.getInstanceCount());
         setPropertyValueCounter(dataDefinition.getPropertyValueCounter());
         setNormalizedName(dataDefinition.getNormalizedName());
         setOriginType(dataDefinition.getOriginType());
@@ -156,6 +157,14 @@ public class ComponentInstanceDataDefinition extends ToscaDataDefinition {
         setToscaPresentationValue(JsonPresentationFields.CI_MAX_OCCURRENCES, maxOccurrences);
     }
 
+    public String getInstanceCount() {
+        return (String) getToscaPresentationValue(JsonPresentationFields.CI_INSTANCE_COUNT);
+    }
+
+    public void setInstanceCount(String instanceCountInput) {
+        setToscaPresentationValue(JsonPresentationFields.CI_INSTANCE_COUNT, instanceCountInput);
+    }
+
     public String getComponentUid() {
         return (String) getToscaPresentationValue(JsonPresentationFields.CI_COMPONENT_UID);
     }
index e36e4ef..a3acb42 100644 (file)
@@ -202,6 +202,7 @@ public enum JsonPresentationFields {
     CI_ARTIFACTS("artifacts", null),
     CI_MAX_OCCURRENCES("maxOccurrences", null),
     CI_MIN_OCCURRENCES("minOccurrences", null),
+    CI_INSTANCE_COUNT("instanceCount", null),
 
     //path
     FORWARDING_PATH("forwardingPath", null),