Support setting interfaces on instances
[sdc.git] / catalog-model / src / main / java / org / openecomp / sdc / be / model / jsonjanusgraph / operations / ToscaOperationFacade.java
index 31aea03..b6339e8 100644 (file)
  * limitations under the License.
  * ============LICENSE_END=========================================================
  */
+
 package org.openecomp.sdc.be.model.jsonjanusgraph.operations;
 
+import static java.util.Objects.requireNonNull;
+import static org.apache.commons.collections.CollectionUtils.isEmpty;
+import static org.apache.commons.collections.CollectionUtils.isNotEmpty;
+import static org.janusgraph.core.attribute.Text.REGEX;
+import static org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum.TOPOLOGY_TEMPLATE;
+
 import com.vdurmont.semver4j.Semver;
 import com.vdurmont.semver4j.Semver.SemverType;
 import fj.data.Either;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.function.BiPredicate;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang3.StringUtils;
@@ -111,31 +139,6 @@ import org.openecomp.sdc.common.log.wrappers.Logger;
 import org.openecomp.sdc.common.util.ValidationUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.EnumMap;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Set;
-import java.util.TreeSet;
-import java.util.function.BiPredicate;
-import java.util.stream.Collectors;
-
-import static java.util.Objects.requireNonNull;
-import static org.apache.commons.collections.CollectionUtils.isEmpty;
-import static org.apache.commons.collections.CollectionUtils.isNotEmpty;
-import static org.janusgraph.core.attribute.Text.REGEX;
-
 @org.springframework.stereotype.Component("tosca-operation-facade")
 public class ToscaOperationFacade {
 
@@ -143,9 +146,11 @@ public class ToscaOperationFacade {
     public static final String PROXY_SUFFIX = "_proxy";
     // region - Fields
     private static final String COULDNT_FETCH_A_COMPONENT_WITH_AND_UNIQUE_ID_ERROR = "Couldn't fetch a component with and UniqueId {}, error: {}";
-    private static final String FAILED_TO_FIND_RECENTLY_ADDED_PROPERTY_ON_THE_RESOURCE_STATUS_IS = "Failed to find recently added property {} on the resource {}. Status is {}. ";
+    private static final String FAILED_TO_FIND_RECENTLY_ADDED_PROPERTY_ON_THE_RESOURCE_STATUS_IS =
+        "Failed to find recently added property {} on the resource {}. Status is {}. ";
     private static final String FAILED_TO_GET_UPDATED_RESOURCE_STATUS_IS = "Failed to get updated resource {}. Status is {}. ";
-    private static final String FAILED_TO_ADD_THE_PROPERTY_TO_THE_RESOURCE_STATUS_IS = "Failed to add the property {} to the resource {}. Status is {}. ";
+    private static final String FAILED_TO_ADD_THE_PROPERTY_TO_THE_RESOURCE_STATUS_IS =
+        "Failed to add the property {} to the resource {}. Status is {}. ";
     private static final String SERVICE = "service";
     private static final String VF = "VF";
     private static final String NOT_SUPPORTED_COMPONENT_TYPE = "Not supported component type {}";
@@ -604,7 +609,7 @@ public class ToscaOperationFacade {
 
     public Either<Resource, StorageOperationStatus> getLatestResourceByToscaResourceName(String toscaResourceName) {
         if (toscaResourceName != null && toscaResourceName.contains("org.openecomp.resource.vf")) {
-            return getLatestResourceByToscaResourceName(toscaResourceName, VertexTypeEnum.TOPOLOGY_TEMPLATE, JsonParseFlagEnum.ParseMetadata);
+            return getLatestResourceByToscaResourceName(toscaResourceName, TOPOLOGY_TEMPLATE, JsonParseFlagEnum.ParseMetadata);
         } else {
             return getLatestResourceByToscaResourceName(toscaResourceName, VertexTypeEnum.NODE_TYPE, JsonParseFlagEnum.ParseMetadata);
         }
@@ -784,7 +789,7 @@ public class ToscaOperationFacade {
         return updateToscaElement(componentToUpdate, new ComponentParametersView());
     }
 
-    public <T extends Component> Either<T, StorageOperationStatus> updateToscaElement(T componentToUpdate, ComponentParametersView filterResult) {
+    private <T extends Component> Either<T, StorageOperationStatus> updateToscaElement(T componentToUpdate, ComponentParametersView filterResult) {
         String componentId = componentToUpdate.getUniqueId();
         Either<GraphVertex, JanusGraphOperationStatus> getVertexEither = janusGraphDao.getVertexById(componentId, JsonParseFlagEnum.ParseAll);
         if (getVertexEither.isRight()) {
@@ -848,44 +853,26 @@ public class ToscaOperationFacade {
         return getLatestByName(property, nodeName, JsonParseFlagEnum.ParseMetadata, modelName);
     }
 
-    public <T extends Component> Either<List<T>, StorageOperationStatus> getBySystemName(ComponentTypeEnum componentType, String systemName) {
-        Either<List<T>, StorageOperationStatus> result = null;
-        Either<T, StorageOperationStatus> getComponentRes;
-        List<T> components = new ArrayList<>();
-        List<GraphVertex> componentVertices;
-        Map<GraphPropertyEnum, Object> propertiesToMatch = new EnumMap<>(GraphPropertyEnum.class);
-        Map<GraphPropertyEnum, Object> propertiesNotToMatch = new EnumMap<>(GraphPropertyEnum.class);
+    public <T extends Component> Either<T, StorageOperationStatus> getBySystemNameAndVersion(final ComponentTypeEnum componentType,
+                                                                                             final String systemName,
+                                                                                             final String version) {
+        final Map<GraphPropertyEnum, Object> propertiesToMatch = new EnumMap<>(GraphPropertyEnum.class);
+        final Map<GraphPropertyEnum, Object> propertiesNotToMatch = new EnumMap<>(GraphPropertyEnum.class);
         propertiesToMatch.put(GraphPropertyEnum.SYSTEM_NAME, systemName);
+        propertiesToMatch.put(GraphPropertyEnum.VERSION, version);
         if (componentType != null) {
             propertiesToMatch.put(GraphPropertyEnum.COMPONENT_TYPE, componentType.name());
         }
         propertiesNotToMatch.put(GraphPropertyEnum.IS_DELETED, true);
-        Either<List<GraphVertex>, JanusGraphOperationStatus> getComponentsRes = janusGraphDao
-            .getByCriteria(null, propertiesToMatch, propertiesNotToMatch, JsonParseFlagEnum.ParseAll);
-        if (getComponentsRes.isRight()) {
-            JanusGraphOperationStatus status = getComponentsRes.right().value();
-            log.debug("Failed to fetch the component with system name {}. Status is {} ", systemName, status);
-            result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
-        }
-        if (result == null) {
-            componentVertices = getComponentsRes.left().value();
-            for (GraphVertex componentVertex : componentVertices) {
-                getComponentRes = getToscaElementByOperation(componentVertex);
-                if (getComponentRes.isRight()) {
-                    log.debug("Failed to get the component {}. Status is {} ", componentVertex.getJsonMetadataField(JsonPresentationFields.NAME),
-                        getComponentRes.right().value());
-                    result = Either.right(getComponentRes.right().value());
-                    break;
-                }
-                T componentBySystemName = getComponentRes.left().value();
-                log.debug("Found component, id: {}", componentBySystemName.getUniqueId());
-                components.add(componentBySystemName);
-            }
-        }
-        if (result == null) {
-            result = Either.left(components);
+
+        final Either<List<GraphVertex>, JanusGraphOperationStatus> getResourceResult
+            = janusGraphDao.getByCriteria(null, propertiesToMatch, propertiesNotToMatch, JsonParseFlagEnum.ParseAll);
+        if (getResourceResult.isRight()) {
+            final JanusGraphOperationStatus status = getResourceResult.right().value();
+            log.debug("Failed to find resource with systemName {}, version {}. Status is {} ", systemName, version, status);
+            return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
         }
-        return result;
+        return getToscaElementByOperation(getResourceResult.left().value().get(0));
     }
 
     public <T extends Component> Either<T, StorageOperationStatus> getComponentByNameAndVersion(ComponentTypeEnum componentType, String name,
@@ -895,7 +882,6 @@ public class ToscaOperationFacade {
 
     public <T extends Component> Either<T, StorageOperationStatus> getComponentByNameAndVersion(ComponentTypeEnum componentType, String name,
                                                                                                 String version, JsonParseFlagEnum parseFlag) {
-        Either<T, StorageOperationStatus> result;
         Map<GraphPropertyEnum, Object> hasProperties = new EnumMap<>(GraphPropertyEnum.class);
         Map<GraphPropertyEnum, Object> hasNotProperties = new EnumMap<>(GraphPropertyEnum.class);
         hasProperties.put(GraphPropertyEnum.NAME, name);
@@ -909,8 +895,7 @@ public class ToscaOperationFacade {
         if (getResourceRes.isRight()) {
             JanusGraphOperationStatus status = getResourceRes.right().value();
             log.debug("failed to find resource with name {}, version {}. Status is {} ", name, version, status);
-            result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
-            return result;
+            return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
         }
         return getToscaElementByOperation(getResourceRes.left().value().get(0));
     }
@@ -1322,14 +1307,22 @@ public class ToscaOperationFacade {
     /**
      * @return max counter of component instance Id's, null if not found
      */
-    private Integer getMaxCounterFromNamesAndIds(Component containerComponent, String normalizedName) {
-        List<String> countersInNames = containerComponent.getComponentInstances().stream()
+    private Integer getMaxCounterFromNamesAndIds(final Component containerComponent, final String normalizedName) {
+        final Pattern COUNTER_PATTERN = Pattern.compile(normalizedName + "[\\s_:-]?\\d+$");
+        final List<String> countersInNames = containerComponent.getComponentInstances().stream()
             .filter(ci -> ci.getNormalizedName() != null && ci.getNormalizedName().startsWith(normalizedName))
-            .map(ci -> ci.getNormalizedName().split(normalizedName)[1].replaceAll("\\D", "")).collect(Collectors.toList());
-        List<String> countersInIds = containerComponent.getComponentInstances().stream()
+            .filter(ci -> !ci.getNormalizedName().equals(normalizedName))
+            .map(ComponentInstance::getNormalizedName)
+            .map(COUNTER_PATTERN::matcher).filter(Matcher::find).map(matcher -> matcher.group(0))
+            .map(nn -> nn.replaceAll("\\D", ""))
+            .collect(Collectors.toList());
+        final List<String> countersInIds = containerComponent.getComponentInstances().stream()
             .filter(ci -> ci.getUniqueId() != null && ci.getUniqueId().contains(normalizedName))
-            .map(ci -> ci.getUniqueId().split(normalizedName)[1].replaceAll("\\D", "")).collect(Collectors.toList());
-        List<String> namesAndIdsList = new ArrayList<>(countersInNames);
+            .map(ComponentInstance::getUniqueId)
+            .map(COUNTER_PATTERN::matcher).filter(Matcher::find).map(matcher -> matcher.group(0))
+            .map(nn -> nn.replaceAll("\\D", ""))
+            .collect(Collectors.toList());
+        final List<String> namesAndIdsList = new ArrayList<>(countersInNames);
         namesAndIdsList.addAll(countersInIds);
         return getMaxInteger(namesAndIdsList);
     }
@@ -1667,39 +1660,40 @@ public class ToscaOperationFacade {
     }
 
     public Either<Map<String, MapInterfaceDataDefinition>, StorageOperationStatus> associateComponentInstanceInterfacesToComponent(
-            Map<String, Map<String, InterfaceDefinition>> instInterfaces,
-            String componentId
+        Map<String, Map<String, InterfaceDefinition>> instInterfaces,
+        String componentId
     ) {
         Either<GraphVertex, JanusGraphOperationStatus> getVertexEither = janusGraphDao.getVertexById(
-                componentId,
-                JsonParseFlagEnum.NoParse
+            componentId,
+            JsonParseFlagEnum.NoParse
         );
         if (getVertexEither.isRight()) {
             log.debug(
-                    COULDNT_FETCH_COMPONENT_WITH_AND_UNIQUE_ID_ERROR,
-                    componentId,
-                    getVertexEither.right().value()
+                COULDNT_FETCH_COMPONENT_WITH_AND_UNIQUE_ID_ERROR,
+                componentId,
+                getVertexEither.right().value()
             );
             return Either.right(
-                    DaoStatusConverter.convertJanusGraphStatusToStorageStatus(
-                            getVertexEither.right().value()
-                    )
+                DaoStatusConverter.convertJanusGraphStatusToStorageStatus(
+                    getVertexEither.right().value()
+                )
             );
         }
         GraphVertex vertex = getVertexEither.left().value();
         Map<String, MapInterfaceDataDefinition> instInterfacesMap = new HashMap<>();
         if (instInterfaces != null) {
-            MapInterfaceDataDefinition interfacesMap = new MapInterfaceDataDefinition();
+
             for (Map.Entry<String, Map<String, InterfaceDefinition>> entryInstances : instInterfaces.entrySet()) {
                 Map<String, InterfaceDataDefinition> incomingInterfacesMap = entryInstances.getValue().entrySet().stream()
-                        .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue()));
+                    .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue()));
+                MapInterfaceDataDefinition interfacesMap = new MapInterfaceDataDefinition();
                 interfacesMap.setMapToscaDataDefinition(incomingInterfacesMap);
                 instInterfacesMap.put(entryInstances.getKey(), interfacesMap);
             }
         }
         StorageOperationStatus status = topologyTemplateOperation.associateInstInterfacesToComponent(
-                vertex,
-                instInterfacesMap
+            vertex,
+            instInterfacesMap
         );
         if (StorageOperationStatus.OK == status) {
             log.debug(COMPONENT_CREATED_SUCCESSFULLY);
@@ -1799,25 +1793,25 @@ public class ToscaOperationFacade {
     }
 
     public Either<Map<String, List<ComponentInstanceAttribute>>, StorageOperationStatus> addComponentInstanceAttributesToComponent(
-        final Component containerComponent, final Map<String, List<ComponentInstanceAttribute>> instProperties) {
-        requireNonNull(instProperties);
-        for (final Entry<String, List<ComponentInstanceAttribute>> entry : instProperties.entrySet()) {
-            final List<ComponentInstanceAttribute> props = entry.getValue();
-            if (isEmpty(props)) {
+        final Component containerComponent, final Map<String, List<ComponentInstanceAttribute>> componentInstanceAttribute) {
+        requireNonNull(componentInstanceAttribute);
+        for (final Entry<String, List<ComponentInstanceAttribute>> entry : componentInstanceAttribute.entrySet()) {
+            final List<ComponentInstanceAttribute> attributes = entry.getValue();
+            if (isEmpty(attributes)) {
                 continue;
             }
             final String componentInstanceId = entry.getKey();
-            final List<ComponentInstanceAttribute> originalComponentInstProps = containerComponent.getComponentInstancesAttributes()
+            final List<ComponentInstanceAttribute> componentInstanceAttributes = containerComponent.getComponentInstancesAttributes()
                 .get(componentInstanceId);
-            for (final ComponentInstanceAttribute property : props) {
+            for (final ComponentInstanceAttribute attribute : attributes) {
                 final StorageOperationStatus status = updateOrAddComponentInstanceAttribute(containerComponent, componentInstanceId,
-                    originalComponentInstProps, property);
+                    componentInstanceAttributes, attribute);
                 if (status != StorageOperationStatus.OK) {
                     return Either.right(status);
                 }
             }
         }
-        return Either.left(instProperties);
+        return Either.left(componentInstanceAttribute);
     }
 
     private StorageOperationStatus populateAndUpdateInstanceCapProperty(Component containerComponent, String componentInstanceId,
@@ -1855,19 +1849,19 @@ public class ToscaOperationFacade {
     }
 
     private StorageOperationStatus updateOrAddComponentInstanceAttribute(Component containerComponent, String componentInstanceId,
-                                                                         List<ComponentInstanceAttribute> originalComponentInstProps,
-                                                                         ComponentInstanceAttribute property) {
+                                                                         List<ComponentInstanceAttribute> componentInstanceAttributes,
+                                                                         ComponentInstanceAttribute attribute) {
         StorageOperationStatus status;
-        // check if the property already exists or not
-        Optional<ComponentInstanceAttribute> instanceProperty = originalComponentInstProps.stream()
-            .filter(p -> p.getUniqueId().equals(property.getUniqueId())).findAny();
+        // check if the attribute already exists or not
+        Optional<ComponentInstanceAttribute> instanceProperty = componentInstanceAttributes.stream()
+            .filter(p -> p.getUniqueId().equals(attribute.getUniqueId())).findAny();
         if (instanceProperty.isPresent()) {
-            status = updateComponentInstanceAttribute(containerComponent, componentInstanceId, property);
+            status = updateComponentInstanceAttribute(containerComponent, componentInstanceId, attribute);
         } else {
-            status = addComponentInstanceAttribute(containerComponent, componentInstanceId, property);
+            status = addComponentInstanceAttribute(containerComponent, componentInstanceId, attribute);
         }
         if (status != StorageOperationStatus.OK) {
-            log.debug("Failed to update instance property {} for instance {} error {} ", property, componentInstanceId, status);
+            log.debug("Failed to update instance attribute {} for instance {} error {} ", attribute, componentInstanceId, status);
         }
         return status;
     }
@@ -2353,7 +2347,7 @@ public class ToscaOperationFacade {
     }
 
     private VertexTypeEnum getVertexTypeEnum(final ResourceTypeEnum resourceType) {
-        return ModelConverter.isAtomicComponent(resourceType) ? VertexTypeEnum.NODE_TYPE : VertexTypeEnum.TOPOLOGY_TEMPLATE;
+        return ModelConverter.isAtomicComponent(resourceType) ? VertexTypeEnum.NODE_TYPE : TOPOLOGY_TEMPLATE;
     }
 
     private Map<GraphPropertyEnum, Object> propertiesToMatch(final String normalizedName, final ComponentTypeEnum componentType) {
@@ -2425,7 +2419,7 @@ public class ToscaOperationFacade {
         }
         if (ComponentTypeEnum.SERVICE == componentTypeEnum || SERVICE.equalsIgnoreCase(internalComponentType) || VF.equalsIgnoreCase(
             internalComponentType)) {
-            internalVertexTypes.add(VertexTypeEnum.TOPOLOGY_TEMPLATE);
+            internalVertexTypes.add(TOPOLOGY_TEMPLATE);
         }
         return internalVertexTypes;
     }
@@ -2540,7 +2534,7 @@ public class ToscaOperationFacade {
         }
         Component component = latestVersionList.size() == 1 ? latestVersionList.get(0)
             : latestVersionList.stream().max((c1, c2) -> Double.compare(Double.parseDouble(c1.getVersion()), Double.parseDouble(c2.getVersion())))
-                .get();
+            .get();
         return Either.left(component);
     }
 
@@ -2786,7 +2780,7 @@ public class ToscaOperationFacade {
         }
         propertiesToMatch.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.SERVICE.name());
         propertiesNotToMatch.put(GraphPropertyEnum.IS_DELETED, true);
-        if (distStatus != null && !distStatus.isEmpty()) {
+        if (CollectionUtils.isNotEmpty(distStatus)) {
             for (DistributionStatusEnum state : distStatus) {
                 propertiesToMatch.put(GraphPropertyEnum.DISTRIBUTION_STATUS, state.name());
                 Either<List<Service>, StorageOperationStatus> fetchServicesByCriteria = fetchServicesByCriteria(servicesAll, propertiesToMatch,
@@ -2807,8 +2801,12 @@ public class ToscaOperationFacade {
                                                                                   Map<GraphPropertyEnum, Object> propertiesToMatch,
                                                                                   Map<GraphPropertyEnum, Object> propertiesNotToMatch,
                                                                                   String modelName) {
-        Either<List<GraphVertex>, JanusGraphOperationStatus> getRes = janusGraphDao
-            .getByCriteria(VertexTypeEnum.TOPOLOGY_TEMPLATE, propertiesToMatch, propertiesNotToMatch, JsonParseFlagEnum.ParseAll, modelName);
+        Either<List<GraphVertex>, JanusGraphOperationStatus> getRes;
+        if (StringUtils.isEmpty(modelName)) {
+            getRes = janusGraphDao.getByCriteria(TOPOLOGY_TEMPLATE, propertiesToMatch, propertiesNotToMatch, JsonParseFlagEnum.ParseAll);
+        } else {
+            getRes = janusGraphDao.getByCriteria(TOPOLOGY_TEMPLATE, propertiesToMatch, propertiesNotToMatch, JsonParseFlagEnum.ParseAll, modelName);
+        }
         if (getRes.isRight()) {
             if (getRes.right().value() != JanusGraphOperationStatus.NOT_FOUND) {
                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG,
@@ -3460,7 +3458,7 @@ public class ToscaOperationFacade {
             log.error(COULDNT_FETCH_A_COMPONENT_WITH_AND_UNIQUE_ID_ERROR, componentId, getVertexEither.right().value());
             result = Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(getVertexEither.right().value()));
         } else {
-            if (getVertexEither.left().value().getLabel() != VertexTypeEnum.TOPOLOGY_TEMPLATE) {
+            if (getVertexEither.left().value().getLabel() != TOPOLOGY_TEMPLATE) {
                 log.error("Policy association to component of Tosca type {} is not allowed. ", getVertexEither.left().value().getLabel());
                 result = Either.right(StorageOperationStatus.BAD_REQUEST);
             }