diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/cli/CLIToolData.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/cli/CLIToolData.java
index c490b6d..e75f866 100644
--- a/asdctool/src/main/java/org/openecomp/sdc/asdctool/cli/CLIToolData.java
+++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/cli/CLIToolData.java
@@ -7,9 +7,9 @@
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *      http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -32,11 +32,6 @@
         this.commandLine = commandLine;
     }
 
-    public CLIToolData(CommandLine commandLine, AbstractApplicationContext springApplicationContext) {
-        this.commandLine = commandLine;
-        this.springApplicationContext = springApplicationContext;
-    }
-
     public CommandLine getCommandLine() {
         return commandLine;
     }
diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/enums/DistributionStatusEnum.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/enums/DistributionStatusEnum.java
deleted file mode 100644
index 5e601a0..0000000
--- a/asdctool/src/main/java/org/openecomp/sdc/asdctool/enums/DistributionStatusEnum.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-package org.openecomp.sdc.asdctool.enums;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-@Getter
-@AllArgsConstructor
-public enum DistributionStatusEnum {
-    DISTRIBUTION_NOT_APPROVED("Distribution not approved"),
-    DISTRIBUTION_APPROVED("Distribution approved"),
-    DISTRIBUTED("Distributed"),
-    DISTRIBUTION_REJECTED("Distribution rejected");
-
-    private final String value;
-
-}
\ No newline at end of file
diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/enums/LifeCycleTransitionEnum.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/enums/LifeCycleTransitionEnum.java
deleted file mode 100644
index 6f52734..0000000
--- a/asdctool/src/main/java/org/openecomp/sdc/asdctool/enums/LifeCycleTransitionEnum.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-package org.openecomp.sdc.asdctool.enums;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-@Getter
-@AllArgsConstructor
-public enum LifeCycleTransitionEnum {
-
-    CHECKOUT("checkout"),
-    CHECKIN("checkin"),
-    CERTIFICATION_REQUEST("certificationRequest"),
-    UNDO_CHECKOUT("undoCheckout"),
-    CANCEL_CERTIFICATION("cancelCertification"),
-    START_CERTIFICATION("startCertification"),
-    FAIL_CERTIFICATION("failCertification"),
-    CERTIFY("certify"),
-    DISTRIBUTE("distribute");
-
-    private final String displayName;
-
-}
\ No newline at end of file
diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/ArtifactUuidFix.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/ArtifactUuidFix.java
index 579bf35..2a77b25 100644
--- a/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/ArtifactUuidFix.java
+++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/ArtifactUuidFix.java
@@ -7,9 +7,9 @@
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *      http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -20,10 +20,27 @@
 
 package org.openecomp.sdc.asdctool.impl;
 
+import static java.nio.charset.StandardCharsets.UTF_8;
+
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
 import com.google.gson.JsonArray;
 import fj.data.Either;
+import java.io.BufferedWriter;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
 import org.openecomp.sdc.asdctool.impl.validator.utils.VfModuleArtifactPayloadEx;
 import org.openecomp.sdc.be.components.distribution.engine.VfModuleArtifactPayload;
 import org.openecomp.sdc.be.dao.cassandra.ArtifactCassandraDao;
@@ -74,1305 +91,1288 @@
 import org.openecomp.sdc.exception.ResponseFormat;
 import org.springframework.beans.factory.annotation.Autowired;
 
-import java.io.BufferedWriter;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.EnumMap;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Collectors;
-
 @org.springframework.stereotype.Component("artifactUuidFix")
 public class ArtifactUuidFix {
 
-	private static final String MIGRATION1707_ARTIFACT_UUID_FIX = "Migration1707ArtifactUuidFix  fix group:  group name {} correct artifactId {} artifactUUID {} ";
+    private static final String MIGRATION1707_ARTIFACT_UUID_FIX = "Migration1707ArtifactUuidFix  fix group:  group name {} correct artifactId {} artifactUUID {} ";
 
-	private static final String FAILED_TO_FETCH_VF_RESOURCES = "Failed to fetch vf resources ";
+    private static final String FAILED_TO_FETCH_VF_RESOURCES = "Failed to fetch vf resources ";
 
-	private static final String UTF8 = "utf-8";
+    private static Logger log = Logger.getLogger(ArtifactUuidFix.class.getName());
+    private JanusGraphDao janusGraphDao;
+    private ToscaOperationFacade toscaOperationFacade;
+    private ToscaExportHandler toscaExportUtils;
+    private ArtifactCassandraDao artifactCassandraDao;
+    private CsarUtils csarUtils;
 
-	private JanusGraphDao janusGraphDao;
-	private ToscaOperationFacade toscaOperationFacade;
-	private ToscaExportHandler toscaExportUtils;
-	private ArtifactCassandraDao artifactCassandraDao;
-	private CsarUtils csarUtils;
+    @Autowired
+    public ArtifactUuidFix(JanusGraphDao janusGraphDao,
+                           ToscaOperationFacade toscaOperationFacade, ToscaExportHandler toscaExportUtils,
+                           ArtifactCassandraDao artifactCassandraDao, CsarUtils csarUtils) {
+        this.janusGraphDao = janusGraphDao;
+        this.toscaOperationFacade = toscaOperationFacade;
+        this.toscaExportUtils = toscaExportUtils;
+        this.artifactCassandraDao = artifactCassandraDao;
+        this.csarUtils = csarUtils;
+    }
 
-	private static Logger log = Logger.getLogger(ArtifactUuidFix.class.getName());
+    public boolean doFix(String fixComponent, String runMode) {
+        List<Resource> vfLst = new ArrayList<>();
+        List<Service> serviceList = new ArrayList<>();
+        Map<String, List<Component>> nodeToFixTosca = new HashMap<>();
+        Map<String, List<Component>> vfToFixTosca = new HashMap<>();
+        Map<String, List<Component>> serviceToFixTosca = new HashMap<>();
 
-	@Autowired
-	public ArtifactUuidFix(JanusGraphDao janusGraphDao,
-		ToscaOperationFacade toscaOperationFacade, ToscaExportHandler toscaExportUtils,
-		ArtifactCassandraDao artifactCassandraDao, CsarUtils csarUtils) {
-		this.janusGraphDao = janusGraphDao;
-		this.toscaOperationFacade = toscaOperationFacade;
-		this.toscaExportUtils = toscaExportUtils;
-		this.artifactCassandraDao = artifactCassandraDao;
-		this.csarUtils = csarUtils;
-	}
+        long time = System.currentTimeMillis();
 
-	public boolean doFix(String fixComponent, String runMode) {
-		List<Resource> vfLst = new ArrayList<>();
-		List<Service> serviceList = new ArrayList<>();
-		Map<String, List<Component>> nodeToFixTosca = new HashMap<>();
-		Map<String, List<Component>> vfToFixTosca = new HashMap<>();
-		Map<String, List<Component>> serviceToFixTosca = new HashMap<>();
+        doFixTosca(nodeToFixTosca, vfToFixTosca, serviceToFixTosca);
 
-		long time = System.currentTimeMillis();
+        if ("vf_only".equals(fixComponent)) {
+            if (!fetchFaultVf(vfLst, time)) {
+                return false;
+            }
+        } else {
+            if (!fetchServices(fixComponent, serviceList, time)) {
+                return false;
+            }
+        }
+        if ("service_vf".equals(runMode) || "fix".equals(runMode)) {
+            log.info("Mode {}. Find problem VFs", runMode);
+            if (!fetchVf(serviceList, vfLst, time)) {
+                log.info("Mode {}. Find problem VFs finished with failure", runMode);
+                return false;
+            }
+            log.info("Mode {}. Find problem VFs finished with success", runMode);
+        }
+        if ("fix".equals(runMode) || "fix_only_services".equals(runMode)) {
+            log.info("Mode {}. Start fix", runMode);
+            if (!fix(vfLst, serviceList, nodeToFixTosca, vfToFixTosca, serviceToFixTosca)) {
+                log.info("Mode {}. Fix finished with failure", runMode);
+                return false;
+            }
+            log.info("Mode {}. Fix finished with success", runMode);
+        }
 
-		doFixTosca(nodeToFixTosca, vfToFixTosca, serviceToFixTosca);
+        return true;
+    }
 
-		if ("vf_only".equals(fixComponent)) {
-			if (!fetchFaultVf(fixComponent, vfLst, time)) {
-				return false;
-			}
-		} else {
-			if (!fetchServices(fixComponent, serviceList, time)) {
-				return false;
-			}
-		}
-		if ("service_vf".equals(runMode) || "fix".equals(runMode)) {
-			log.info("Mode {}. Find problem VFs", runMode);
-			if (!fetchVf(serviceList, vfLst, time)) {
-				log.info("Mode {}. Find problem VFs finished with failure", runMode);
-				return false;
-			}
-			log.info("Mode {}. Find problem VFs finished with success", runMode);
-		}
-		if ("fix".equals(runMode) || "fix_only_services".equals(runMode)) {
-			log.info("Mode {}. Start fix", runMode);
-			if (!fix(vfLst, serviceList, nodeToFixTosca, vfToFixTosca, serviceToFixTosca)) {
-				log.info("Mode {}. Fix finished with failure", runMode);
-				return false;
-			}
-			log.info("Mode {}. Fix finished with success", runMode);
-		}
+    private boolean fetchFaultVf(List<Resource> vfLst, long time) {
+        log.info("Find fault VF ");
+        String fileName = "fault_" + time + ".csv";
+        try (Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName), UTF_8))) {
+            writer.write("vf name, vf id, state, version\n");
 
-		return true;
-	}
+            Map<GraphPropertyEnum, Object> hasProps = new EnumMap<>(GraphPropertyEnum.class);
+            hasProps.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.RESOURCE.name());
+            hasProps.put(GraphPropertyEnum.RESOURCE_TYPE, ResourceTypeEnum.VF.name());
 
-	private boolean fetchFaultVf(String fixComponent, List<Resource> vfLst, long time) {
-		log.info("Find fault VF ");
-		String fileName = "fault_" + time + ".csv";
-		try(Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName), UTF8))) {
-			writer.write("vf name, vf id, state, version\n");
+            Map<GraphPropertyEnum, Object> hasNotProps = new EnumMap<>(GraphPropertyEnum.class);
+            hasNotProps.put(GraphPropertyEnum.IS_DELETED, true);
+            log.info("Try to fetch resources with properties {} and not {}", hasProps, hasNotProps);
 
-			Map<GraphPropertyEnum, Object> hasProps = new EnumMap<>(GraphPropertyEnum.class);
-			hasProps.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.RESOURCE.name());
-			hasProps.put(GraphPropertyEnum.RESOURCE_TYPE, ResourceTypeEnum.VF.name());
+            Either<List<GraphVertex>, JanusGraphOperationStatus> servicesByCriteria = janusGraphDao
+                .getByCriteria(VertexTypeEnum.TOPOLOGY_TEMPLATE, hasProps, hasNotProps, JsonParseFlagEnum.ParseAll);
+            if (servicesByCriteria.isRight()) {
+                log.info("Failed to fetch resources {}", servicesByCriteria.right().value());
+                return false;
+            }
+            List<GraphVertex> resources = servicesByCriteria.left().value();
+            for (GraphVertex gv : resources) {
+                ComponentParametersView filter = new ComponentParametersView(true);
+                filter.setIgnoreComponentInstances(false);
+                filter.setIgnoreArtifacts(false);
+                filter.setIgnoreGroups(false);
 
-			Map<GraphPropertyEnum, Object> hasNotProps = new EnumMap<>(GraphPropertyEnum.class);
-			hasNotProps.put(GraphPropertyEnum.IS_DELETED, true);
-			log.info("Try to fetch resources with properties {} and not {}", hasProps, hasNotProps);
+                Either<Resource, StorageOperationStatus> toscaElement = toscaOperationFacade
+                    .getToscaElement(gv.getUniqueId());
+                if (toscaElement.isRight()) {
+                    log.info("Failed to fetch resources {} {}", gv.getUniqueId(), toscaElement.right().value());
+                    continue;
+                }
 
-			Either<List<GraphVertex>, JanusGraphOperationStatus> servicesByCriteria = janusGraphDao
-					.getByCriteria(VertexTypeEnum.TOPOLOGY_TEMPLATE, hasProps, hasNotProps, JsonParseFlagEnum.ParseAll);
-			if (servicesByCriteria.isRight()) {
-				log.info("Failed to fetch resources {}", servicesByCriteria.right().value());
-				return false;
-			}
-			List<GraphVertex> resources = servicesByCriteria.left().value();
-			for (GraphVertex gv : resources) {
-				ComponentParametersView filter = new ComponentParametersView(true);
-				filter.setIgnoreComponentInstances(false);
-				filter.setIgnoreArtifacts(false);
-				filter.setIgnoreGroups(false);
+                Resource resource = toscaElement.left().value();
+                String resourceName = resource.getName();
+                Map<String, ArtifactDefinition> deploymentArtifacts = resource.getDeploymentArtifacts();
+                List<GroupDefinition> groups = resource.getGroups();
+                if (groups == null || groups.isEmpty()) {
+                    log.info("No groups for resource {} id {} ", resourceName, gv.getUniqueId());
+                    continue;
+                }
+                boolean isProblematic = false;
+                for (GroupDefinition gr : groups) {
+                    if (gr.getType().equals(Constants.DEFAULT_GROUP_VF_MODULE) && isProblematicGroup(gr, resourceName, deploymentArtifacts)) {
+                        isProblematic = true;
+                        break;
+                    }
+                }
+                if (isProblematic) {
+                    vfLst.add(resource);
+                    writeModuleResultToFile(writer, resource, null);
+                    writer.flush();
+                }
+                janusGraphDao.commit();
+            }
 
-				Either<Resource, StorageOperationStatus> toscaElement = toscaOperationFacade
-						.getToscaElement(gv.getUniqueId());
-				if (toscaElement.isRight()) {
-					log.info("Failed to fetch resources {} {}", gv.getUniqueId(), toscaElement.right().value());
-					continue;
-				}
+        } catch (Exception e) {
+            log.info(FAILED_TO_FETCH_VF_RESOURCES, e);
+            return false;
+        } finally {
+            janusGraphDao.commit();
+        }
+        return true;
+    }
 
-				Resource resource = toscaElement.left().value();
-				String resourceName = resource.getName();
-				Map<String, ArtifactDefinition> deploymentArtifacts = resource.getDeploymentArtifacts();
-				List<GroupDefinition> groups = resource.getGroups();
-				if (groups == null || groups.isEmpty()) {
-					log.info("No groups for resource {} id {} ", resourceName, gv.getUniqueId());
-					continue;
-				}
-				boolean isProblematic = false;
-				for (GroupDefinition gr : groups) {
-					if (gr.getType().equals(Constants.DEFAULT_GROUP_VF_MODULE)) {
-						if (isProblematicGroup(gr, resourceName, deploymentArtifacts)) {
-							isProblematic = true;
-							break;
-						}
-					}
-				}
-				if (isProblematic) {
-					vfLst.add(resource);
-					writeModuleResultToFile(writer, resource, null);
-					writer.flush();
-				}
-				janusGraphDao.commit();
-			}
+    private boolean fetchVf(List<Service> serviceList, List<Resource> vfLst, long time) {
+        log.info("Find problem VF ");
+        if (serviceList.isEmpty()) {
+            log.info("No services as input");
+            return true;
+        }
+        String fileName = "problemVf_" + time + ".csv";
+        try (Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName), UTF_8))) {
+            writer.write("vf name, vf id, state, version, example service name\n");
+            Set<String> vfIds = new HashSet<>();
+            for (Service service : serviceList) {
+                List<ComponentInstance> componentInstances = service.getComponentInstances().stream()
+                    .filter(ci -> ci.getOriginType().equals(OriginTypeEnum.VF)).collect(Collectors.toList());
+                for (ComponentInstance ci : componentInstances) {
+                    if (!vfIds.contains(ci.getComponentUid())) {
+                        vfIds.add(ci.getComponentUid());
+                        ComponentParametersView filter = new ComponentParametersView(true);
+                        filter.setIgnoreComponentInstances(false);
+                        filter.setIgnoreArtifacts(false);
+                        filter.setIgnoreGroups(false);
+                        Either<Resource, StorageOperationStatus> toscaElement = toscaOperationFacade
+                            .getToscaElement(ci.getComponentUid(), filter);
+                        if (toscaElement.isRight()) {
+                            log.info("Failed to fetch resource {} {}", ci.getComponentUid(),
+                                toscaElement.right().value());
+                            continue;
+                        }
+                        Resource resource = toscaElement.left().value();
+                        if (resource.getResourceType().equals(ResourceTypeEnum.VF)) {
+                            vfLst.add(resource);
+                            writeModuleResultToFile(writer, resource, service);
+                            writer.flush();
 
-		} catch (Exception e) {
-			log.info(FAILED_TO_FETCH_VF_RESOURCES, e);
-			return false;
-		} finally {
-			janusGraphDao.commit();
-		}
-		return true;
-	}
+                        }
+                        janusGraphDao.commit();
+                    }
+                }
+            }
+            log.info("output file with list of Vf : {}", fileName);
+        } catch (Exception e) {
+            log.info("Failed to fetch services ", e);
+            return false;
+        } finally {
+            janusGraphDao.commit();
+        }
+        return true;
+    }
 
-	private boolean fetchVf(List<Service> serviceList, List<Resource> vfLst, long time) {
-		log.info("Find problem VF ");
-		if (serviceList.isEmpty()) {
-			log.info("No services as input");
-			return true;
-		}
-		String fileName = "problemVf_" + time + ".csv";
-		try(Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName), UTF8))) {
-			writer.write("vf name, vf id, state, version, example service name\n");
-			Set<String> vfIds = new HashSet<>();
-			for (Service service : serviceList) {
-				List<ComponentInstance> componentInstances = service.getComponentInstances().stream()
-						.filter(ci -> ci.getOriginType().equals(OriginTypeEnum.VF)).collect(Collectors.toList());
-				for (ComponentInstance ci : componentInstances) {
-					if (!vfIds.contains(ci.getComponentUid())) {
-						vfIds.add(ci.getComponentUid());
-						ComponentParametersView filter = new ComponentParametersView(true);
-						filter.setIgnoreComponentInstances(false);
-						filter.setIgnoreArtifacts(false);
-						filter.setIgnoreGroups(false);
-						Either<Resource, StorageOperationStatus> toscaElement = toscaOperationFacade
-								.getToscaElement(ci.getComponentUid(), filter);
-						if (toscaElement.isRight()) {
-							log.info("Failed to fetch resource {} {}", ci.getComponentUid(),
-									toscaElement.right().value());
-							continue;
-						}
-						Resource resource = toscaElement.left().value();
-						if (resource.getResourceType().equals(ResourceTypeEnum.VF)) {
-							vfLst.add(resource);
-							writeModuleResultToFile(writer, resource, service);
-							writer.flush();
+    private boolean fetchServices(String fixServices, List<Service> serviceList, long time) {
+        log.info("Find problem Services {}", fixServices);
+        String fileName = "problemService_" + time + ".csv";
+        try (Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName), UTF_8))) {
+            writer.write("service name, service id, state, version\n");
 
-						}
-						janusGraphDao.commit();
-					}
-				}
-			}
-			log.info("output file with list of Vf : {}", fileName);
-		} catch (Exception e) {
-			log.info("Failed to fetch services ", e);
-			return false;
-		} finally {
-			janusGraphDao.commit();
-		}
-		return true;
-	}
+            Map<GraphPropertyEnum, Object> hasProps = new EnumMap<>(GraphPropertyEnum.class);
+            hasProps.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.SERVICE.name());
+            if ("distributed_only".equals(fixServices)) {
+                hasProps.put(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name());
+                hasProps.put(GraphPropertyEnum.DISTRIBUTION_STATUS, DistributionStatusEnum.DISTRIBUTED.name());
+            }
 
-	private boolean fetchServices(String fixServices, List<Service> serviceList, long time) {
-		log.info("Find problem Services {}", fixServices);
-		String fileName = "problemService_" + time + ".csv";
-		try(Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName), UTF8))) {
-			writer.write("service name, service id, state, version\n");
+            Map<GraphPropertyEnum, Object> hasNotProps = new EnumMap<>(GraphPropertyEnum.class);
+            hasNotProps.put(GraphPropertyEnum.IS_DELETED, true);
+            log.info("Try to fetch services with properties {} and not {}", hasProps, hasNotProps);
 
-			Map<GraphPropertyEnum, Object> hasProps = new EnumMap<>(GraphPropertyEnum.class);
-			hasProps.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.SERVICE.name());
-			if ("distributed_only".equals(fixServices)) {
-				hasProps.put(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name());
-				hasProps.put(GraphPropertyEnum.DISTRIBUTION_STATUS, DistributionStatusEnum.DISTRIBUTED.name());
-			}
+            Either<List<GraphVertex>, JanusGraphOperationStatus> servicesByCriteria = janusGraphDao
+                .getByCriteria(VertexTypeEnum.TOPOLOGY_TEMPLATE, hasProps, hasNotProps, JsonParseFlagEnum.ParseAll);
+            if (servicesByCriteria.isRight()) {
+                log.info("Failed to fetch services {}", servicesByCriteria.right().value());
+                return false;
+            }
+            List<GraphVertex> services = servicesByCriteria.left().value();
+            for (GraphVertex gv : services) {
+                ComponentParametersView filter = new ComponentParametersView(true);
+                filter.setIgnoreComponentInstances(false);
+                filter.setIgnoreArtifacts(false);
+                filter.setIgnoreGroups(false);
 
-			Map<GraphPropertyEnum, Object> hasNotProps = new EnumMap<>(GraphPropertyEnum.class);
-			hasNotProps.put(GraphPropertyEnum.IS_DELETED, true);
-			log.info("Try to fetch services with properties {} and not {}", hasProps, hasNotProps);
+                Either<Service, StorageOperationStatus> toscaElement = toscaOperationFacade
+                    .getToscaElement(gv.getUniqueId(), filter);
+                if (toscaElement.isRight()) {
+                    log.info("Failed to fetch service {} {}", gv.getUniqueId(), toscaElement.right().value());
+                    continue;
+                }
+                Service service = toscaElement.left().value();
 
-			Either<List<GraphVertex>, JanusGraphOperationStatus> servicesByCriteria = janusGraphDao
-					.getByCriteria(VertexTypeEnum.TOPOLOGY_TEMPLATE, hasProps, hasNotProps, JsonParseFlagEnum.ParseAll);
-			if (servicesByCriteria.isRight()) {
-				log.info("Failed to fetch services {}", servicesByCriteria.right().value());
-				return false;
-			}
-			List<GraphVertex> services = servicesByCriteria.left().value();
-			for (GraphVertex gv : services) {
-				ComponentParametersView filter = new ComponentParametersView(true);
-				filter.setIgnoreComponentInstances(false);
-				filter.setIgnoreArtifacts(false);
-				filter.setIgnoreGroups(false);
+                String serviceName = (String) gv.getMetadataProperty(GraphPropertyEnum.NAME);
 
-				Either<Service, StorageOperationStatus> toscaElement = toscaOperationFacade
-						.getToscaElement(gv.getUniqueId(), filter);
-				if (toscaElement.isRight()) {
-					log.info("Failed to fetch service {} {}", gv.getUniqueId(), toscaElement.right().value());
-					continue;
-				}
-				Service service = toscaElement.left().value();
+                boolean isProblematic = isProblematicService(service, serviceName);
+                if (isProblematic) {
+                    serviceList.add(service);
+                    writeModuleResultToFile(writer, service, null);
+                    writer.flush();
 
-				String serviceName = (String) gv.getMetadataProperty(GraphPropertyEnum.NAME);
+                }
 
-				boolean isProblematic = isProblematicService(service, serviceName);
-				if (isProblematic) {
-					serviceList.add(service);
-					writeModuleResultToFile(writer, service, null);
-					writer.flush();
+                janusGraphDao.commit();
+            }
+            log.info("output file with list of services : {}", fileName);
+        } catch (Exception e) {
+            log.info("Failed to fetch services ", e);
+            return false;
+        } finally {
+            janusGraphDao.commit();
+        }
+        return true;
+    }
 
-				}
+    private boolean isProblematicService(Service service, String serviceName) {
 
-				janusGraphDao.commit();
-			}
-			log.info("output file with list of services : {}", fileName);
-		} catch (Exception e) {
-			log.info("Failed to fetch services ", e);
-			return false;
-		} finally {
-			janusGraphDao.commit();
-		}
-		return true;
-	}
+        List<ComponentInstance> componentInstances = service.getComponentInstances();
 
-	private boolean isProblematicService( Service service, String serviceName) {
+        if (componentInstances == null) {
+            log.info("No instances for service {} ", service.getUniqueId());
+            return false;
+        }
+        boolean isCheckVFModules = true;
+        if (service.getLifecycleState() == LifecycleStateEnum.NOT_CERTIFIED_CHECKIN ||
+            service.getLifecycleState() == LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT) {
+            isCheckVFModules = false;
+        }
+        for (ComponentInstance ci : componentInstances) {
+            Map<String, ArtifactDefinition> deploymentArtifacts = ci.getDeploymentArtifacts();
+            List<GroupInstance> groupInstances = ci.getGroupInstances();
+            if (groupInstances == null || groupInstances.isEmpty()) {
+                log.info("No instance groups for instance {} in service {} id {} ", ci.getName(), serviceName,
+                    service.getUniqueId());
+                continue;
+            }
+            List<VfModuleArtifactPayloadEx> vfModules = null;
+            if (isCheckVFModules) {
+                Optional<ArtifactDefinition> optionalVfModuleArtifact = deploymentArtifacts.values().stream()
+                    .filter(p -> p.getArtifactType().equals(ArtifactTypeEnum.VF_MODULES_METADATA.getType())).findAny();
 
-		List<ComponentInstance> componentInstances = service.getComponentInstances();
+                if (!optionalVfModuleArtifact.isPresent()) {
+                    return true;
+                }
 
-		if (componentInstances == null) {
-			log.info("No instances for service {} ", service.getUniqueId());
-			return false;
-		}
-		boolean isCheckVFModules = true;
-		if(service.getLifecycleState() == LifecycleStateEnum.NOT_CERTIFIED_CHECKIN ||
-				service.getLifecycleState() == LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT){
-			isCheckVFModules = false;
-		}
-		for (ComponentInstance ci : componentInstances) {
-			Map<String, ArtifactDefinition> deploymentArtifacts = ci.getDeploymentArtifacts();
-			List<GroupInstance> groupInstances = ci.getGroupInstances();
-			if (groupInstances == null || groupInstances.isEmpty()) {
-				log.info("No instance groups for instance {} in service {} id {} ", ci.getName(), serviceName,
-						service.getUniqueId());
-				continue;
-			}
-			List<VfModuleArtifactPayloadEx> vfModules = null;
-			if(isCheckVFModules){
-				Optional<ArtifactDefinition> optionalVfModuleArtifact = deploymentArtifacts.values().stream()
-						.filter(p -> p.getArtifactType().equals(ArtifactTypeEnum.VF_MODULES_METADATA.getType())).findAny();
+                ArtifactDefinition vfModuleArtifact = optionalVfModuleArtifact.get();
+                Either<List<VfModuleArtifactPayloadEx>, StorageOperationStatus> vfModulesEither = parseVFModuleJson(vfModuleArtifact);
+                if (vfModulesEither.isRight()) {
+                    log.error("Failed to parse vfModule for service {} status is {}", service.getUniqueId(), vfModulesEither.right().value());
+                    return true;
+                }
+                vfModules = vfModulesEither.left().value();
+                if (vfModules == null || vfModules.isEmpty()) {
+                    log.info("vfModules empty for service {}", service.getUniqueId());
+                    return true;
+                }
+            }
 
-				if(!optionalVfModuleArtifact.isPresent())
-					return true;
+            for (GroupInstance gi : groupInstances) {
+                if (gi.getType().equals(Constants.DEFAULT_GROUP_VF_MODULE)) {
+                    VfModuleArtifactPayloadEx vfModule = null;
+                    if (isCheckVFModules && vfModules != null) {
+                        Optional<VfModuleArtifactPayloadEx> op = vfModules.stream().filter(vf -> vf.getVfModuleModelName().equals(gi.getGroupName()))
+                            .findAny();
+                        if (!op.isPresent()) {
+                            log.error("Failed to find vfModule for group {}", gi.getGroupName());
+                            return true;
+                        }
+                        vfModule = op.get();
+                    }
+                    if (isProblematicGroupInstance(gi, ci.getName(), serviceName, deploymentArtifacts, vfModule)) {
+                        return true;
+                    }
+                }
+            }
 
-				ArtifactDefinition vfModuleArtifact = optionalVfModuleArtifact.get();
-				Either<List<VfModuleArtifactPayloadEx>, StorageOperationStatus> vfModulesEither = parseVFModuleJson(vfModuleArtifact);
-				if(vfModulesEither.isRight()){
-					log.error("Failed to parse vfModule for service {} status is {}", service.getUniqueId(), vfModulesEither.right().value());
-					return true;
-				}
-				vfModules = vfModulesEither.left().value();
-				if(vfModules == null || vfModules.isEmpty() ){
-					log.info("vfModules empty for service {}", service.getUniqueId());
-					return true;
-				}
-			}
+        }
+        return false;
+    }
 
-			for (GroupInstance gi : groupInstances) {
-				if (gi.getType().equals(Constants.DEFAULT_GROUP_VF_MODULE)) {
-					VfModuleArtifactPayloadEx vfModule= null;
-					if(isCheckVFModules && vfModules != null){
-						Optional<VfModuleArtifactPayloadEx> op = vfModules.stream().filter(vf -> vf.getVfModuleModelName().equals(gi.getGroupName())).findAny();
-						if(!op.isPresent()){
-							log.error("Failed to find vfModule for group {}", gi.getGroupName());
-							return true;
-						}
-						vfModule = op.get();
-					}
-					if (isProblematicGroupInstance(gi, ci.getName(), serviceName, deploymentArtifacts, vfModule)) {
-						return true;
-					}
-				}
-			}
+    private boolean isProblematicGroup(GroupDefinition gr, String resourceName,
+                                       Map<String, ArtifactDefinition> deploymentArtifacts) {
+        List<String> artifacts = gr.getArtifacts();
+        List<String> artifactsUuid = gr.getArtifactsUuid();
+        Set<String> artifactsSet = new HashSet<>();
 
-		}
-		return false;
-	}
+        if ((artifactsUuid == null || artifactsUuid.isEmpty()) && (artifacts == null || artifacts.isEmpty())) {
+            log.info("No groups in resource {} ", resourceName);
+            return true;
+        }
+        artifactsSet.addAll(artifacts);
+        if (artifactsSet.size() < artifacts.size()) {
+            log.info(" artifactsSet.size() < artifacts.size() group {} in resource {} ", gr.getName(), resourceName);
+            return true;
+        }
 
-	private boolean isProblematicGroup(GroupDefinition gr, String resourceName,
-									   Map<String, ArtifactDefinition> deploymentArtifacts) {
-		List<String> artifacts = gr.getArtifacts();
-		List<String> artifactsUuid = gr.getArtifactsUuid();
-		Set<String> artifactsSet = new HashSet<>();
+        if ((artifactsUuid != null) && (artifacts.size() < artifactsUuid.size())) {
+            log.info(" artifacts.size() < artifactsUuid.size() group {} in resource {} ", gr.getName(), resourceName);
+            return true;
+        }
+        if (!artifacts.isEmpty() && (artifactsUuid == null || artifactsUuid.isEmpty())) {
+            log.info(
+                " artifacts.size() > 0 && (artifactsUuid == null || artifactsUuid.isEmpty() group {} in resource {} ",
+                gr.getName(), resourceName);
+            return true;
+        }
+        if (artifactsUuid != null && artifactsUuid.contains(null)) {
+            log.info(" artifactsUuid.contains(null) group {} in resource {} ", gr.getName(), resourceName);
+            return true;
+        }
 
-		if ((artifactsUuid == null || artifactsUuid.isEmpty()) && (artifacts == null || artifacts.isEmpty())) {
-			log.info("No groups in resource {} ", resourceName);
-			return true;
-		}
-		artifactsSet.addAll(artifacts);
-		if (artifactsSet.size() < artifacts.size()) {
-			log.info(" artifactsSet.size() < artifacts.size() group {} in resource {} ", gr.getName(), resourceName);
-			return true;
-		}
+        for (String artifactId : artifacts) {
+            String artifactlabel = findArtifactLabelFromArtifactId(artifactId);
+            ArtifactDefinition artifactDefinition = deploymentArtifacts.get(artifactlabel);
+            if (artifactDefinition == null) {
+                log.info(" artifactDefinition == null label {} group {} in resource {} ", artifactlabel, gr.getName(),
+                    resourceName);
+                return true;
+            }
+            ArtifactTypeEnum artifactType = ArtifactTypeEnum.parse(artifactDefinition.getArtifactType());
+            if (artifactType != ArtifactTypeEnum.HEAT_ENV) {
+                if (!artifactId.equals(artifactDefinition.getUniqueId())) {
+                    log.info(
+                        " !artifactId.equals(artifactDefinition.getUniqueId() artifact {}  artId {} group {} in resource {} ",
+                        artifactlabel, artifactId, gr.getName(), resourceName);
+                    return true;
+                }
+                if (artifactsUuid != null && !artifactsUuid.contains(artifactDefinition.getArtifactUUID())) {
+                    log.info(
+                        " artifactsUuid.contains(artifactDefinition.getArtifactUUID() label {} group {} in resource {} ",
+                        artifactlabel, gr.getName(), resourceName);
+                    return true;
+                }
+            }
+        }
+        for (String artifactUUID : artifactsUuid) {
+            String label = findArtifactLabelFromArtifactId(artifactUUID);
+            if (label != null && !label.isEmpty() && !label.equals("")) {
+                return true;
+            }
+        }
 
-		if ((artifactsUuid != null) && (artifacts.size() < artifactsUuid.size())) {
-			log.info(" artifacts.size() < artifactsUuid.size() group {} in resource {} ", gr.getName(), resourceName);
-			return true;
-		}
-		if (!artifacts.isEmpty() && (artifactsUuid == null || artifactsUuid.isEmpty())) {
-			log.info(
-					" artifacts.size() > 0 && (artifactsUuid == null || artifactsUuid.isEmpty() group {} in resource {} ",
-					gr.getName(), resourceName);
-			return true;
-		}
-		if (artifactsUuid != null && artifactsUuid.contains(null)) {
-			log.info(" artifactsUuid.contains(null) group {} in resource {} ", gr.getName(), resourceName);
-			return true;
-		}
+        return false;
+    }
 
-		for (String artifactId : artifacts) {
-			String artifactlabel = findArtifactLabelFromArtifactId(artifactId);
-			ArtifactDefinition artifactDefinition = deploymentArtifacts.get(artifactlabel);
-			if (artifactDefinition == null) {
-				log.info(" artifactDefinition == null label {} group {} in resource {} ", artifactlabel, gr.getName(),
-						resourceName);
-				return true;
-			}
-			ArtifactTypeEnum artifactType = ArtifactTypeEnum.parse(artifactDefinition.getArtifactType());
-			if (artifactType != ArtifactTypeEnum.HEAT_ENV) {
-				if (!artifactId.equals(artifactDefinition.getUniqueId())) {
-					log.info(
-							" !artifactId.equals(artifactDefinition.getUniqueId() artifact {}  artId {} group {} in resource {} ",
-							artifactlabel, artifactId, gr.getName(), resourceName);
-					return true;
-				}
-				if (artifactsUuid != null && !artifactsUuid.contains(artifactDefinition.getArtifactUUID())) {
-					log.info(
-							" artifactsUuid.contains(artifactDefinition.getArtifactUUID() label {} group {} in resource {} ",
-							artifactlabel, gr.getName(), resourceName);
-					return true;
-				}
-			}
-		}
-		for (String artifactUUID : artifactsUuid) {
-			String label = findArtifactLabelFromArtifactId(artifactUUID);
-			if (label != null && !label.isEmpty() && !label.equals("")) {
-				return true;
-			}
-		}
+    private boolean isProblematicGroupInstance(GroupInstance gi, String instName, String servicename,
+                                               Map<String, ArtifactDefinition> deploymentArtifacts, VfModuleArtifactPayloadEx vfModule) {
+        List<String> artifacts = gi.getArtifacts();
+        List<String> artifactsUuid = gi.getArtifactsUuid();
+        List<String> instArtifactsUuid = gi.getGroupInstanceArtifactsUuid();
+        List<String> instArtifactsId = gi.getGroupInstanceArtifacts();
+        Set<String> instArtifatIdSet = new HashSet<>();
+        Set<String> artifactsSet = new HashSet<>();
 
-		return false;
-	}
+        log.info("check group {} for instance {} ", gi.getGroupName(), instName);
+        if ((artifactsUuid == null || artifactsUuid.isEmpty()) && (artifacts == null || artifacts.isEmpty())) {
+            log.info("No instance groups for instance {} in service {} ", instName, servicename);
+            return true;
+        }
+        artifactsSet.addAll(artifacts);
+        if (artifactsSet.size() < artifacts.size()) {
+            log.info(" artifactsSet.size() < artifacts.size() group {} in resource {} ", instName, servicename);
+            return true;
+        }
 
-	private boolean isProblematicGroupInstance(GroupInstance gi, String instName, String servicename,
-											   Map<String, ArtifactDefinition> deploymentArtifacts, VfModuleArtifactPayloadEx vfModule) {
-		List<String> artifacts = gi.getArtifacts();
-		List<String> artifactsUuid = gi.getArtifactsUuid();
-		List<String> instArtifactsUuid = gi.getGroupInstanceArtifactsUuid();
-		List<String> instArtifactsId = gi.getGroupInstanceArtifacts();
-		Set<String> instArtifatIdSet = new HashSet<>();
-		Set<String> artifactsSet = new HashSet<>();
+        if (instArtifactsId != null && !instArtifactsId.isEmpty()) {
+            instArtifatIdSet.addAll(instArtifactsId);
+        }
 
-		log.info("check group {} for instance {} ", gi.getGroupName(), instName);
-		if ((artifactsUuid == null || artifactsUuid.isEmpty()) && (artifacts == null || artifacts.isEmpty())) {
-			log.info("No instance groups for instance {} in service {} ", instName, servicename);
-			return true;
-		}
-		artifactsSet.addAll(artifacts);
-		if (artifactsSet.size() < artifacts.size()) {
-			log.info(" artifactsSet.size() < artifacts.size() group {} in resource {} ", instName, servicename);
-			return true;
-		}
+        if ((artifactsUuid != null) && (artifacts.size() < artifactsUuid.size())) {
+            log.info(" artifacts.size() < artifactsUuid.size() inst {} in service {} ", instName, servicename);
+            return true;
+        }
+        if (!artifacts.isEmpty() && (artifactsUuid == null || artifactsUuid.isEmpty())) {
+            log.info(
+                " artifacts.size() > 0 && (artifactsUuid == null || artifactsUuid.isEmpty() inst {} in service {} ",
+                instName, servicename);
+            return true;
+        }
+        if (artifactsUuid != null && artifactsUuid.contains(null)) {
+            log.info(" artifactsUuid.contains(null) inst {} in service {} ", instName, servicename);
+            return true;
+        }
+        if (instArtifactsId != null && instArtifatIdSet.size() < instArtifactsId.size()) {
+            log.info(" instArtifatIdSet.size() < instArtifactsId.size() inst {} in service {} ", instName, servicename);
+            return true;
+        }
 
-		if (instArtifactsId != null && !instArtifactsId.isEmpty()) {
-			instArtifatIdSet.addAll(instArtifactsId);
-		}
+        if ((instArtifactsId != null && instArtifactsUuid != null)
+            && instArtifactsId.size() != instArtifactsUuid.size()) {
+            log.info(" instArtifactsId.size() != instArtifactsUuid.size() inst {} in service {} ", instName,
+                servicename);
+            return true;
+        }
 
-		if ((artifactsUuid != null) && (artifacts.size() < artifactsUuid.size())) {
-			log.info(" artifacts.size() < artifactsUuid.size() inst {} in service {} ", instName, servicename);
-			return true;
-		}
-		if (!artifacts.isEmpty() && (artifactsUuid == null || artifactsUuid.isEmpty())) {
-			log.info(
-					" artifacts.size() > 0 && (artifactsUuid == null || artifactsUuid.isEmpty() inst {} in service {} ",
-					instName, servicename);
-			return true;
-		}
-		if (artifactsUuid != null && artifactsUuid.contains(null)) {
-			log.info(" artifactsUuid.contains(null) inst {} in service {} ", instName, servicename);
-			return true;
-		}
-		if (instArtifactsId != null && instArtifatIdSet.size() < instArtifactsId.size()) {
-			log.info(" instArtifatIdSet.size() < instArtifactsId.size() inst {} in service {} ", instName, servicename);
-			return true;
-		}
+        for (String artifactId : artifacts) {
+            String artifactlabel = findArtifactLabelFromArtifactId(artifactId);
+            ArtifactDefinition artifactDefinition = deploymentArtifacts.get(artifactlabel);
+            if (artifactDefinition == null) {
+                log.info(" artifactDefinition == null label {} inst {} in service {} ", artifactlabel, instName,
+                    servicename);
+                return true;
+            }
+            ArtifactTypeEnum artifactType = ArtifactTypeEnum.parse(artifactDefinition.getArtifactType());
+            if (artifactType != ArtifactTypeEnum.HEAT_ENV) {
+                if (!artifactId.equals(artifactDefinition.getUniqueId())) {
+                    log.info(
+                        " !artifactId.equals(artifactDefinition.getUniqueId() artifact {}  artId {} inst {} in service {} ",
+                        artifactlabel, artifactId, instName, servicename);
+                    return true;
+                }
+                if (artifactsUuid != null && !artifactsUuid.contains(artifactDefinition.getArtifactUUID())) {
+                    log.info(
+                        " artifactsUuid.contains(artifactDefinition.getArtifactUUID() label {} inst {} in service {} ",
+                        artifactlabel, instName, servicename);
+                    return true;
+                }
+            } else {
+                if (instArtifactsUuid == null || instArtifactsUuid.isEmpty()) {
+                    log.info(" instArtifactsUuid empty. label {} inst {} in service {} ", artifactlabel, instName,
+                        servicename);
+                    return true;
+                }
+                if (!instArtifactsUuid.contains(artifactDefinition.getArtifactUUID())) {
+                    log.info(
+                        " instArtifactsUuid.contains(artifactDefinition.getArtifactUUID() label {} inst {} in service {} ",
+                        artifactlabel, instName, servicename);
+                    return true;
+                }
+            }
+        }
+        for (String artifactUUID : artifactsUuid) {
+            String label = findArtifactLabelFromArtifactId(artifactUUID);
+            if (label != null && !label.isEmpty() && !"".equals(label)) {
+                return true;
+            }
+        }
+        if (vfModule != null && artifactsUuid != null) {
+            return isProblematicVFModule(vfModule, artifactsUuid, instArtifactsUuid);
+        }
 
-		if ((instArtifactsId != null && instArtifactsUuid != null)
-				&& instArtifactsId.size() != instArtifactsUuid.size()) {
-			log.info(" instArtifactsId.size() != instArtifactsUuid.size() inst {} in service {} ", instName,
-					servicename);
-			return true;
-		}
+        return false;
+    }
 
-		for (String artifactId : artifacts) {
-			String artifactlabel = findArtifactLabelFromArtifactId(artifactId);
-			ArtifactDefinition artifactDefinition = deploymentArtifacts.get(artifactlabel);
-			if (artifactDefinition == null) {
-				log.info(" artifactDefinition == null label {} inst {} in service {} ", artifactlabel, instName,
-						servicename);
-				return true;
-			}
-			ArtifactTypeEnum artifactType = ArtifactTypeEnum.parse(artifactDefinition.getArtifactType());
-			if (artifactType != ArtifactTypeEnum.HEAT_ENV) {
-				if (!artifactId.equals(artifactDefinition.getUniqueId())) {
-					log.info(
-							" !artifactId.equals(artifactDefinition.getUniqueId() artifact {}  artId {} inst {} in service {} ",
-							artifactlabel, artifactId, instName, servicename);
-					return true;
-				}
-				if (artifactsUuid != null && !artifactsUuid.contains(artifactDefinition.getArtifactUUID())) {
-					log.info(
-							" artifactsUuid.contains(artifactDefinition.getArtifactUUID() label {} inst {} in service {} ",
-							artifactlabel, instName, servicename);
-					return true;
-				}
-			} else {
-				if (instArtifactsUuid == null || instArtifactsUuid.isEmpty()) {
-					log.info(" instArtifactsUuid empty. label {} inst {} in service {} ", artifactlabel, instName,
-							servicename);
-					return true;
-				}
-				if (!instArtifactsUuid.contains(artifactDefinition.getArtifactUUID())) {
-					log.info(
-							" instArtifactsUuid.contains(artifactDefinition.getArtifactUUID() label {} inst {} in service {} ",
-							artifactlabel, instName, servicename);
-					return true;
-				}
-			}
-		}
-		for (String artifactUUID : artifactsUuid) {
-			String label = findArtifactLabelFromArtifactId(artifactUUID);
-			if (label != null && !label.isEmpty() && !"".equals(label)) {
-				return true;
-			}
-		}
-		if(vfModule != null && artifactsUuid != null){
-			return isProblematicVFModule(vfModule, artifactsUuid, instArtifactsUuid);
-		}
+    private boolean isProblematicVFModule(VfModuleArtifactPayloadEx vfModule, List<String> artifactsUuid,
+                                          List<String> instArtifactsUuid) {
+        log.info(" isProblematicVFModule  {}  ", vfModule.getVfModuleModelName());
+        List<String> vfModuleArtifacts = vfModule.getArtifacts();
+        List<String> allArtifacts = new ArrayList<>();
+        allArtifacts.addAll(artifactsUuid);
+        if (instArtifactsUuid != null) {
+            allArtifacts.addAll(instArtifactsUuid);
+        }
+        if ((vfModuleArtifacts == null || vfModuleArtifacts.isEmpty()) && !artifactsUuid.isEmpty()) {
+            log.error(" vfModuleArtifacts == null || vfModuleArtifacts.isEmpty()) && !artifactsUuid.isEmpty()");
+            return true;
+        }
+        if (vfModuleArtifacts != null) {
+            if (vfModuleArtifacts.size() != allArtifacts.size()) {
+                log.error(" vfModuleArtifacts.size() != allArtifacts.size()");
+                return true;
+            }
+            for (String vfModuleArtifact : vfModuleArtifacts) {
+                Optional<String> op = allArtifacts.stream().filter(a -> a.equals(vfModuleArtifact)).findAny();
+                if (!op.isPresent()) {
+                    log.error("failed to find artifact {} in group artifacts {}", vfModuleArtifact, allArtifacts);
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
 
-		return false;
-	}
 
-	private boolean isProblematicVFModule(VfModuleArtifactPayloadEx vfModule, List<String> artifactsUuid,
-										  List<String> instArtifactsUuid) {
-		log.info(" isProblematicVFModule  {}  ", vfModule.getVfModuleModelName());
-		List<String> vfModuleArtifacts = vfModule.getArtifacts();
-		List<String> allArtifacts = new ArrayList<>();
-		allArtifacts.addAll(artifactsUuid);
-		if(instArtifactsUuid != null)
-			allArtifacts.addAll(instArtifactsUuid);
-		if((vfModuleArtifacts == null || vfModuleArtifacts.isEmpty()) && !artifactsUuid.isEmpty()){
-			log.error(" vfModuleArtifacts == null || vfModuleArtifacts.isEmpty()) && !artifactsUuid.isEmpty()");
-			return true;
-		}
-		if(vfModuleArtifacts!= null){
-			if( vfModuleArtifacts.size() != allArtifacts.size()){
-				log.error(" vfModuleArtifacts.size() != allArtifacts.size()");
-				return true;
-			}
-			for(String vfModuleArtifact: vfModuleArtifacts){
-				Optional<String> op = allArtifacts.stream().filter(a -> a.equals(vfModuleArtifact)).findAny();
-				if(!op.isPresent()){
-					log.error("failed to find artifact {} in group artifacts {}", vfModuleArtifact,  allArtifacts);
-					return true;
-				}
-			}
-		}
-		return false;
-	}
+    private boolean fix(List<Resource> vfLst, List<Service> serviceList, Map<String, List<Component>> nodesToFixTosca,
+                        Map<String, List<Component>> vfToFixTosca, Map<String, List<Component>> servicesToFixTosca) {
+        boolean res = true;
+        log.info(" Fix started ***** ");
+        if (vfLst != null && !vfLst.isEmpty()) {
+            res = fixVf(vfLst);
 
+        }
 
+        if (res && serviceList != null && !serviceList.isEmpty()) {
+            res = fixServices(serviceList);
 
-	private boolean fix(List<Resource> vfLst, List<Service> serviceList, Map<String, List<Component>> nodesToFixTosca,
-						Map<String, List<Component>> vfToFixTosca, Map<String, List<Component>> servicesToFixTosca) {
-		boolean res = true;
-		log.info(" Fix started ***** ");
-		if (vfLst != null && !vfLst.isEmpty()) {
-			res = fixVf(vfLst);
+        }
 
-		}
+        Set<String> fixedIds = new HashSet<>();
 
-		if (res && serviceList != null && !serviceList.isEmpty()) {
-			res = fixServices(serviceList);
+        long time = System.currentTimeMillis();
+        String fileName = "FailedGenerateTosca" + "_" + time + ".csv";
 
-		}
+        try (Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName), UTF_8))) {
+            writer.write("componentType, name, version, UID, UUID, invariantUUID, state\n");
+            List<Component> failedList = new ArrayList<>();
 
-		Set<String> fixedIds = new HashSet<>();
+            if (res && nodesToFixTosca != null && !nodesToFixTosca.isEmpty()) {
 
-		long time = System.currentTimeMillis();
-		String fileName = "FailedGenerateTosca" + "_" + time + ".csv";
+                generateAndSaveToscaArtifacts(nodesToFixTosca, fixedIds, null, failedList);
 
-		try(Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName), UTF8))) {
-			writer.write("componentType, name, version, UID, UUID, invariantUUID, state\n");
-			List<Component> failedList = new ArrayList<>();
+            }
+            if (vfToFixTosca != null && !vfToFixTosca.isEmpty()) {
 
-			if (res && nodesToFixTosca != null && !nodesToFixTosca.isEmpty()) {
+                generateAndSaveToscaArtifacts(vfToFixTosca, fixedIds, vfLst, failedList);
 
-				generateAndSaveToscaArtifacts(nodesToFixTosca, fixedIds, null, failedList);
+            }
 
-			}
-			if (vfToFixTosca != null && !vfToFixTosca.isEmpty()) {
+            for (Component component : vfLst) {
+                res = generateToscaPerComponent(fixedIds, component);
+                if (res) {
+                    TopologyTemplate topologyTemplate = ModelConverter.convertToToscaElement(component);
+                    Map<String, GroupDataDefinition> groups = topologyTemplate.getGroups();
+                    res = fixDataOnGraph(component.getUniqueId(), VertexTypeEnum.GROUPS, EdgeLabelEnum.GROUPS, groups);
+                    if (res) {
+                        Map<String, ArtifactDataDefinition> arifacts = topologyTemplate.getDeploymentArtifacts();
+                        res = fixDataOnGraph(component.getUniqueId(), VertexTypeEnum.DEPLOYMENT_ARTIFACTS,
+                            EdgeLabelEnum.DEPLOYMENT_ARTIFACTS, arifacts);
+                    }
+                    if (res) {
+                        Map<String, ArtifactDataDefinition> arifacts = topologyTemplate.getToscaArtifacts();
+                        res = fixDataOnGraph(component.getUniqueId(), VertexTypeEnum.TOSCA_ARTIFACTS,
+                            EdgeLabelEnum.TOSCA_ARTIFACTS, arifacts);
+                    }
+                    janusGraphDao.commit();
+                } else {
+                    failedList.add(component);
+                }
+            }
 
-				generateAndSaveToscaArtifacts(vfToFixTosca, fixedIds, vfLst, failedList);
+            if (servicesToFixTosca != null && !servicesToFixTosca.isEmpty()) {
+                generateAndSaveToscaArtifacts(servicesToFixTosca, fixedIds, serviceList, failedList);
 
-			}
+            }
 
-			for (Component component : vfLst) {
-				res = generateToscaPerComponent(fixedIds, component);
-				if (res) {
-					TopologyTemplate topologyTemplate = ModelConverter.convertToToscaElement(component);
-					Map<String, GroupDataDefinition> groups = topologyTemplate.getGroups();
-					res = fixDataOnGraph(component.getUniqueId(), VertexTypeEnum.GROUPS, EdgeLabelEnum.GROUPS, groups);
-					if (res) {
-						Map<String, ArtifactDataDefinition> arifacts = topologyTemplate.getDeploymentArtifacts();
-						res = fixDataOnGraph(component.getUniqueId(), VertexTypeEnum.DEPLOYMENT_ARTIFACTS,
-								EdgeLabelEnum.DEPLOYMENT_ARTIFACTS, arifacts);
-					}
-					if (res) {
-						Map<String, ArtifactDataDefinition> arifacts = topologyTemplate.getToscaArtifacts();
-						res = fixDataOnGraph(component.getUniqueId(), VertexTypeEnum.TOSCA_ARTIFACTS,
-								EdgeLabelEnum.TOSCA_ARTIFACTS, arifacts);
-					}
-					janusGraphDao.commit();
-				} else {
-					failedList.add(component);
-				}
-			}
+            for (Component component : serviceList) {
+                res = generateToscaPerComponent(fixedIds, component);
+                if (res) {
+                    TopologyTemplate topologyTemplate = ModelConverter.convertToToscaElement(component);
+                    Map<String, MapGroupsDataDefinition> groups = topologyTemplate.getInstGroups();
+                    res = fixDataOnGraph(component.getUniqueId(), VertexTypeEnum.INST_GROUPS, EdgeLabelEnum.INST_GROUPS,
+                        groups);
 
-			if (servicesToFixTosca != null && !servicesToFixTosca.isEmpty()) {
-				generateAndSaveToscaArtifacts(servicesToFixTosca, fixedIds, serviceList, failedList);
+                    if (res) {
+                        Map<String, MapArtifactDataDefinition> artifacts = topologyTemplate
+                            .getInstDeploymentArtifacts();
+                        res = fixDataOnGraph(component.getUniqueId(), VertexTypeEnum.INST_DEPLOYMENT_ARTIFACTS,
+                            EdgeLabelEnum.INST_DEPLOYMENT_ARTIFACTS, artifacts);
+                    }
+                    if (res) {
+                        Map<String, ArtifactDataDefinition> arifacts = topologyTemplate.getToscaArtifacts();
+                        res = fixDataOnGraph(component.getUniqueId(), VertexTypeEnum.TOSCA_ARTIFACTS,
+                            EdgeLabelEnum.TOSCA_ARTIFACTS, arifacts);
+                    }
+                    janusGraphDao.commit();
+                } else {
+                    failedList.add(component);
+                }
 
-			}
+            }
+            if (!failedList.isEmpty()) {
+                for (Component component : failedList) {
+                    StringBuilder sb = new StringBuilder(component.getComponentType().getValue());
+                    sb.append(",").append(component.getName()).append(",").append(component.getVersion()).append(",")
+                        .append(component.getUniqueId()).append(",").append(component.getUUID()).append(",")
+                        .append(component.getInvariantUUID()).append(",").append(component.getLifecycleState());
 
+                    sb.append("\n");
+                    writer.write(sb.toString());
+                }
+                writer.flush();
+            }
+        } catch (IOException e) {
+            log.error(e.getMessage());
+        } finally {
+            janusGraphDao.commit();
+        }
+        log.info(" Fix finished with res {} ***** ", res);
+        return res;
+    }
 
-			for (Component component : serviceList) {
-				res = generateToscaPerComponent(fixedIds, component);
-				if (res) {
-					TopologyTemplate topologyTemplate = ModelConverter.convertToToscaElement(component);
-					Map<String, MapGroupsDataDefinition> groups = topologyTemplate.getInstGroups();
-					res = fixDataOnGraph(component.getUniqueId(), VertexTypeEnum.INST_GROUPS, EdgeLabelEnum.INST_GROUPS,
-							groups);
+    private boolean generateAndSaveToscaArtifacts(Map<String, List<Component>> nodesToFixTosca, Set<String> fixedIds,
+                                                  List<? extends Component> componentsWithFailedGroups, List<Component> failedList) {
+        boolean res = true;
+        log.debug("Migration1707ArtifactUuidFix  generateAndSaveToscaArtifacts started ");
+        for (Map.Entry<String, List<Component>> entry : nodesToFixTosca.entrySet()) {
 
-					if (res) {
-						Map<String, MapArtifactDataDefinition> artifacts = topologyTemplate
-								.getInstDeploymentArtifacts();
-						res = fixDataOnGraph(component.getUniqueId(), VertexTypeEnum.INST_DEPLOYMENT_ARTIFACTS,
-								EdgeLabelEnum.INST_DEPLOYMENT_ARTIFACTS, artifacts);
-					}
-					if (res) {
-						Map<String, ArtifactDataDefinition> arifacts = topologyTemplate.getToscaArtifacts();
-						res = fixDataOnGraph(component.getUniqueId(), VertexTypeEnum.TOSCA_ARTIFACTS,
-								EdgeLabelEnum.TOSCA_ARTIFACTS, arifacts);
-					}
-					janusGraphDao.commit();
-				} else {
-					failedList.add(component);
-				}
+            List<Component> component = entry.getValue();
+            for (Component c : component) {
+                log.debug("Migration1707ArtifactUuidFix  fix tosca on component : id {},  name {} ", c.getUniqueId(),
+                    c.getName());
+                if (componentsWithFailedGroups != null) {
+                    Optional<Component> op = (Optional<Component>) componentsWithFailedGroups.stream()
+                        .filter(cg -> cg.getUniqueId().equals(c.getUniqueId())).findAny();
+                    if (!op.isPresent()) {
+                        res = generateToscaPerComponent(fixedIds, c);
+                    }
+                } else {
+                    res = generateToscaPerComponent(fixedIds, c);
+                }
+                if (res) {
+                    ToscaElement topologyTemplate = ModelConverter.convertToToscaElement(c);
+                    Map<String, ArtifactDataDefinition> arifacts = topologyTemplate.getToscaArtifacts();
+                    res = fixDataOnGraph(c.getUniqueId(), VertexTypeEnum.TOSCA_ARTIFACTS, EdgeLabelEnum.TOSCA_ARTIFACTS,
+                        arifacts);
+                    janusGraphDao.commit();
+                } else {
+                    failedList.add(c);
+                }
 
-			}
-			if (!failedList.isEmpty()) {
-				for (Component component : failedList) {
-					StringBuilder sb = new StringBuilder(component.getComponentType().getValue());
-					sb.append(",").append(component.getName()).append(",").append(component.getVersion()).append(",")
-							.append(component.getUniqueId()).append(",").append(component.getUUID()).append(",")
-							.append(component.getInvariantUUID()).append(",").append(component.getLifecycleState());
+            }
+        }
+        log.debug("Migration1707ArtifactUuidFix  generateAndSaveToscaArtifacts finished with res {} ", res);
+        return res;
+    }
 
-					sb.append("\n");
-					writer.write(sb.toString());
-				}
-				writer.flush();
-			}
-		} catch (IOException e) {
-		    log.error(e.getMessage());
-		} finally {
-			janusGraphDao.commit();
-		}
-		log.info(" Fix finished with res {} ***** ", res);
-		return res;
-	}
-
-	private boolean generateAndSaveToscaArtifacts(Map<String, List<Component>> nodesToFixTosca, Set<String> fixedIds,
-												  List<? extends Component> componentsWithFailedGroups, List<Component> failedList) {
-		boolean res = true;
-		log.debug("Migration1707ArtifactUuidFix  generateAndSaveToscaArtifacts started ");
-		for (Map.Entry<String, List<Component>> entry : nodesToFixTosca.entrySet()) {
-
-			List<Component> component = entry.getValue();
-			for (Component c : component) {
-				log.debug("Migration1707ArtifactUuidFix  fix tosca on component : id {},  name {} ", c.getUniqueId(),
-						c.getName());
-				if (componentsWithFailedGroups != null) {
-					Optional<Component> op = (Optional<Component>) componentsWithFailedGroups.stream()
-							.filter(cg -> cg.getUniqueId().equals(c.getUniqueId())).findAny();
-					if (!op.isPresent())
-						res = generateToscaPerComponent(fixedIds, c);
-				} else
-					res = generateToscaPerComponent(fixedIds, c);
-				if (res) {
-					ToscaElement topologyTemplate = ModelConverter.convertToToscaElement(c);
-					Map<String, ArtifactDataDefinition> arifacts = topologyTemplate.getToscaArtifacts();
-					res = fixDataOnGraph(c.getUniqueId(), VertexTypeEnum.TOSCA_ARTIFACTS, EdgeLabelEnum.TOSCA_ARTIFACTS,
-							arifacts);
-					janusGraphDao.commit();
-				} else {
-					failedList.add(c);
-				}
-
-			}
-		}
-		log.debug("Migration1707ArtifactUuidFix  generateAndSaveToscaArtifacts finished with res {} ", res);
-		return res;
-	}
-
-	private boolean generateToscaPerComponent(Set<String> fixedIds, Component c) {
-		boolean res = true;
-		log.debug("Migration1707ArtifactUuidFix  generateToscaPerComponent started component name {} id {}",
-				c.getName(), c.getUniqueId());
-		try {
-			Either<Component, StorageOperationStatus> toscaElement = toscaOperationFacade
-					.getToscaFullElement(c.getUniqueId());
-			if (toscaElement.isRight()) {
-				log.info("Failed to fetch resources {} {}", c.getUniqueId(), toscaElement.right().value());
-				return false;
-			}
-			Component toscaElementFull = toscaElement.left().value();
-			toscaElementFull.setGroups(c.getGroups());
-			List<ComponentInstance> ciListFull = toscaElementFull.getComponentInstances();
-			List<ComponentInstance> ciList = c.getComponentInstances();
-			if (ciListFull != null && !ciListFull.isEmpty()) {
-				ciListFull.forEach(ciFull -> {
-					ComponentInstance compInst = ciList.stream()
-							.filter(ci -> ci.getUniqueId().equals(ciFull.getUniqueId())).findAny().get();
-					ciFull.setGroupInstances(compInst.getGroupInstances());
-				});
-			}
+    private boolean generateToscaPerComponent(Set<String> fixedIds, Component c) {
+        boolean res = true;
+        log.debug("Migration1707ArtifactUuidFix  generateToscaPerComponent started component name {} id {}",
+            c.getName(), c.getUniqueId());
+        try {
+            Either<Component, StorageOperationStatus> toscaElement = toscaOperationFacade
+                .getToscaFullElement(c.getUniqueId());
+            if (toscaElement.isRight()) {
+                log.info("Failed to fetch resources {} {}", c.getUniqueId(), toscaElement.right().value());
+                return false;
+            }
+            Component toscaElementFull = toscaElement.left().value();
+            toscaElementFull.setGroups(c.getGroups());
+            List<ComponentInstance> ciListFull = toscaElementFull.getComponentInstances();
+            List<ComponentInstance> ciList = c.getComponentInstances();
+            if (ciListFull != null && !ciListFull.isEmpty()) {
+                ciListFull.forEach(ciFull -> {
+                    ComponentInstance compInst = ciList.stream()
+                        .filter(ci -> ci.getUniqueId().equals(ciFull.getUniqueId())).findAny().get();
+                    ciFull.setGroupInstances(compInst.getGroupInstances());
+                });
+            }
 
-			Either<Component, ToscaError> either = generateToscaArtifact(toscaElementFull);
+            Either<Component, ToscaError> either = generateToscaArtifact(toscaElementFull);
 
-			if (either.isRight()) {
-				log.error("Couldn't generate and save tosca template component  unique id {}, name {} error: {}",
-						toscaElementFull.getUniqueId(), toscaElementFull.getName(), either.right().value());
-				res = false;
+            if (either.isRight()) {
+                log.error("Couldn't generate and save tosca template component  unique id {}, name {} error: {}",
+                    toscaElementFull.getUniqueId(), toscaElementFull.getName(), either.right().value());
+                res = false;
 
-			}
+            }
 
-			if (res) {
-				c.setToscaArtifacts(either.left().value().getToscaArtifacts());
-				fixedIds.add(toscaElementFull.getUniqueId());
-			}
-		} finally {
-			if (res)
-				janusGraphDao.commit();
-			else
-				janusGraphDao.rollback();
-		}
-		log.debug("Migration1707ArtifactUuidFix  generateToscaPerComponent finished  component name {} id {} res {}",
-				c.getName(), c.getUniqueId(), res);
-		return res;
-	}
+            if (res) {
+                c.setToscaArtifacts(either.left().value().getToscaArtifacts());
+                fixedIds.add(toscaElementFull.getUniqueId());
+            }
+        } finally {
+            if (res) {
+                janusGraphDao.commit();
+            } else {
+                janusGraphDao.rollback();
+            }
+        }
+        log.debug("Migration1707ArtifactUuidFix  generateToscaPerComponent finished  component name {} id {} res {}",
+            c.getName(), c.getUniqueId(), res);
+        return res;
+    }
 
-	private <T extends ToscaDataDefinition> boolean fixDataOnGraph(String componentId, VertexTypeEnum vertexTypeEnum,
-																   EdgeLabelEnum edgeLabelEnum, Map<String, T> groups) {
-		log.debug("amount groups to update: VertexTypeEnum {} EdgeLabelEnum {} data size {}", vertexTypeEnum.getName(),
-				edgeLabelEnum, groups.size());
-		boolean res = true;
-		Either<GraphVertex, JanusGraphOperationStatus> getResponse = janusGraphDao.getVertexById(componentId,
-				JsonParseFlagEnum.NoParse);
-		if (getResponse.isRight()) {
-			log.debug("Couldn't fetch component  unique id {}, error: {}", componentId, getResponse.right().value());
-			res = false;
+    private <T extends ToscaDataDefinition> boolean fixDataOnGraph(String componentId, VertexTypeEnum vertexTypeEnum,
+                                                                   EdgeLabelEnum edgeLabelEnum, Map<String, T> groups) {
+        log.debug("amount groups to update: VertexTypeEnum {} EdgeLabelEnum {} data size {}", vertexTypeEnum.getName(),
+            edgeLabelEnum, groups.size());
+        boolean res = true;
+        Either<GraphVertex, JanusGraphOperationStatus> getResponse = janusGraphDao.getVertexById(componentId,
+            JsonParseFlagEnum.NoParse);
+        if (getResponse.isRight()) {
+            log.debug("Couldn't fetch component  unique id {}, error: {}", componentId, getResponse.right().value());
+            res = false;
 
-		}
-		if (res) {
-			GraphVertex componentVertex = getResponse.left().value();
+        }
+        if (res) {
+            GraphVertex componentVertex = getResponse.left().value();
 
-			GraphVertex toscaDataVertex = null;
-			Either<GraphVertex, JanusGraphOperationStatus> groupVertexEither = janusGraphDao.getChildVertex(componentVertex,
-					edgeLabelEnum, JsonParseFlagEnum.ParseJson);
-			if (groupVertexEither.isRight() && groupVertexEither.right().value() == JanusGraphOperationStatus.NOT_FOUND) {
-				log.debug("no child {}  vertex for component  unique id {}, error: {}", edgeLabelEnum, componentId,
-						groupVertexEither.right().value());
-				return true;
-			}
-			if (groupVertexEither.isRight()) {
-				res = false;
-				log.debug("failed to get child {}  vertex for component  unique id {}, error: {}", edgeLabelEnum,
-						componentId, groupVertexEither.right().value());
-			}
-			if (res) {
-				toscaDataVertex = groupVertexEither.left().value();
-				toscaDataVertex.setJson(groups);
-				Either<GraphVertex, JanusGraphOperationStatus> updatevertexEither = janusGraphDao.updateVertex(toscaDataVertex);
-				if (updatevertexEither.isRight()) {
-					log.debug("failed to update vertex for component  unique id {}, error: {}", componentId,
-							updatevertexEither.right().value());
-					janusGraphDao.rollback();
-					return false;
-				}
-			}
-		}
-		log.debug("Fix data on graph finished: VertexTypeEnum {} EdgeLabelEnum {} res {}", vertexTypeEnum.getName(),
-				res);
-		return res;
-	}
+            GraphVertex toscaDataVertex = null;
+            Either<GraphVertex, JanusGraphOperationStatus> groupVertexEither = janusGraphDao.getChildVertex(componentVertex,
+                edgeLabelEnum, JsonParseFlagEnum.ParseJson);
+            if (groupVertexEither.isRight() && groupVertexEither.right().value() == JanusGraphOperationStatus.NOT_FOUND) {
+                log.debug("no child {}  vertex for component  unique id {}, error: {}", edgeLabelEnum, componentId,
+                    groupVertexEither.right().value());
+                return true;
+            }
+            if (groupVertexEither.isRight()) {
+                res = false;
+                log.debug("failed to get child {}  vertex for component  unique id {}, error: {}", edgeLabelEnum,
+                    componentId, groupVertexEither.right().value());
+            }
+            if (res) {
+                toscaDataVertex = groupVertexEither.left().value();
+                toscaDataVertex.setJson(groups);
+                Either<GraphVertex, JanusGraphOperationStatus> updatevertexEither = janusGraphDao.updateVertex(toscaDataVertex);
+                if (updatevertexEither.isRight()) {
+                    log.debug("failed to update vertex for component  unique id {}, error: {}", componentId,
+                        updatevertexEither.right().value());
+                    janusGraphDao.rollback();
+                    return false;
+                }
+            }
+        }
+        log.debug("Fix data on graph finished: VertexTypeEnum {} EdgeLabelEnum {} res {}", vertexTypeEnum.getName(),
+            res);
+        return res;
+    }
 
-	private boolean fixServices(List<Service> serviceList) {
-		for (Service service : serviceList) {
-			log.debug("Migration1707ArtifactUuidFix  fix service: id {},  name {} ", service.getUniqueId(),
-					service.getName());
-			List<ComponentInstance> instances = service.getComponentInstances();
-			for (ComponentInstance instance : instances) {
-				fixComponentInstances(service, instance);
-			}
+    private boolean fixServices(List<Service> serviceList) {
+        for (Service service : serviceList) {
+            log.debug("Migration1707ArtifactUuidFix  fix service: id {},  name {} ", service.getUniqueId(),
+                service.getName());
+            List<ComponentInstance> instances = service.getComponentInstances();
+            for (ComponentInstance instance : instances) {
+                fixComponentInstances(service, instance);
+            }
 
-		}
-		return true;
+        }
+        return true;
 
-	}
+    }
 
-	private void fixComponentInstances(Service service, ComponentInstance instance) {
-		Map<String, ArtifactDefinition> artifactsMap = instance.getDeploymentArtifacts();
-		List<GroupInstance> groupsList = instance.getGroupInstances();
-		if (groupsList != null && artifactsMap != null) {
-			List<GroupInstance> groupsToDelete = new ArrayList<>();
-			for (GroupInstance group : groupsList) {
-				fixGroupInstances(service, artifactsMap, groupsToDelete, group);
+    private void fixComponentInstances(Service service, ComponentInstance instance) {
+        Map<String, ArtifactDefinition> artifactsMap = instance.getDeploymentArtifacts();
+        List<GroupInstance> groupsList = instance.getGroupInstances();
+        if (groupsList != null && artifactsMap != null) {
+            List<GroupInstance> groupsToDelete = new ArrayList<>();
+            for (GroupInstance group : groupsList) {
+                fixGroupInstances(service, artifactsMap, groupsToDelete, group);
 
-			}
+            }
 
-			if (!groupsToDelete.isEmpty()) {
-				log.debug("Migration1707ArtifactUuidFix  delete group:  resource id {}, group instance to delete {} ",
-						service.getUniqueId(), groupsToDelete);
-				groupsList.removeAll(groupsToDelete);
+            if (!groupsToDelete.isEmpty()) {
+                log.debug("Migration1707ArtifactUuidFix  delete group:  resource id {}, group instance to delete {} ",
+                    service.getUniqueId(), groupsToDelete);
+                groupsList.removeAll(groupsToDelete);
 
-			}
+            }
 
-			Optional<ArtifactDefinition> optionalVfModuleArtifact = artifactsMap.values().stream()
-					.filter(p -> p.getArtifactType().equals(ArtifactTypeEnum.VF_MODULES_METADATA.getType())).findAny();
-			ArtifactDefinition vfModuleArtifact;
-			if(!optionalVfModuleArtifact.isPresent()){
-				vfModuleArtifact = createVfModuleArtifact(instance, service);
-				artifactsMap.put(vfModuleArtifact.getArtifactLabel(), vfModuleArtifact);
-			}
-			else {
-				vfModuleArtifact = optionalVfModuleArtifact.get();
-			}
-			fillVfModuleInstHeatEnvPayload(service, instance, groupsList, vfModuleArtifact);
-		}
-	}
+            Optional<ArtifactDefinition> optionalVfModuleArtifact = artifactsMap.values().stream()
+                .filter(p -> p.getArtifactType().equals(ArtifactTypeEnum.VF_MODULES_METADATA.getType())).findAny();
+            ArtifactDefinition vfModuleArtifact;
+            if (!optionalVfModuleArtifact.isPresent()) {
+                vfModuleArtifact = createVfModuleArtifact(instance);
+                artifactsMap.put(vfModuleArtifact.getArtifactLabel(), vfModuleArtifact);
+            } else {
+                vfModuleArtifact = optionalVfModuleArtifact.get();
+            }
+            fillVfModuleInstHeatEnvPayload(service, instance, groupsList, vfModuleArtifact);
+        }
+    }
 
-	private void fixGroupInstances(Service service, Map<String, ArtifactDefinition> artifactsMap,
-								   List<GroupInstance> groupsToDelete, GroupInstance group) {
-		if (group.getType().equals(Constants.DEFAULT_GROUP_VF_MODULE)) {
-			log.debug("Migration1707ArtifactUuidFix  fix group:  resource id {}, group name {} ", service.getUniqueId(),
-					group.getName());
-			if(group.getArtifacts() != null){
-				Set<String> groupArtifactsSet = new HashSet<>(group.getArtifacts());
-				if(group.getGroupInstanceArtifacts() != null){
-					List<String> groupInsArtifacts = new ArrayList<>(group.getGroupInstanceArtifacts());
-					groupArtifactsSet.addAll(groupInsArtifacts);
-				}
-				List<String> groupArtifacts = new ArrayList<>(groupArtifactsSet);
+    private void fixGroupInstances(Service service, Map<String, ArtifactDefinition> artifactsMap,
+                                   List<GroupInstance> groupsToDelete, GroupInstance group) {
+        if (group.getType().equals(Constants.DEFAULT_GROUP_VF_MODULE)) {
+            log.debug("Migration1707ArtifactUuidFix  fix group:  resource id {}, group name {} ", service.getUniqueId(),
+                group.getName());
+            if (group.getArtifacts() != null) {
+                Set<String> groupArtifactsSet = new HashSet<>(group.getArtifacts());
+                if (group.getGroupInstanceArtifacts() != null) {
+                    List<String> groupInsArtifacts = new ArrayList<>(group.getGroupInstanceArtifacts());
+                    groupArtifactsSet.addAll(groupInsArtifacts);
+                }
+                List<String> groupArtifacts = new ArrayList<>(groupArtifactsSet);
 
-				clearGroupInstanceArtifacts(group);
+                clearGroupInstanceArtifacts(group);
 
-				for (String artifactId : groupArtifacts) {
-					fixArtifactUndergroupInstances(artifactsMap, group, groupArtifacts, artifactId);
-				}
-			}
-			if (group.getArtifacts() == null || group.getArtifacts().isEmpty()) {
-				log.debug(
-						"Migration1707ArtifactUuidFix  fix groupInstance add to delete list:  resource id {} name {} , group name {} ",
-						service.getUniqueId(), service.getName(), group.getName());
-				groupsToDelete.add(group);
-			}
-		}
-	}
+                for (String artifactId : groupArtifacts) {
+                    fixArtifactUndergroupInstances(artifactsMap, group, groupArtifacts, artifactId);
+                }
+            }
+            if (group.getArtifacts() == null || group.getArtifacts().isEmpty()) {
+                log.debug(
+                    "Migration1707ArtifactUuidFix  fix groupInstance add to delete list:  resource id {} name {} , group name {} ",
+                    service.getUniqueId(), service.getName(), group.getName());
+                groupsToDelete.add(group);
+            }
+        }
+    }
 
-	private void clearGroupInstanceArtifacts(GroupInstance group) {
-		if(group.getArtifacts() != null)
-			group.getArtifacts().clear();
-		else
-			group.setArtifacts(new ArrayList<>());
-		if(group.getArtifactsUuid() != null)
-			group.getArtifactsUuid().clear();
-		else{
-			group.setArtifactsUuid(new ArrayList<>());
-		}
-		if(group.getGroupInstanceArtifacts() != null)
-			group.getGroupInstanceArtifacts().clear();
-		else{
-			group.setGroupInstanceArtifacts(new ArrayList<>());
-		}
-		if(group.getGroupInstanceArtifactsUuid() != null )
-			group.getGroupInstanceArtifactsUuid().clear();
-		else
-			group.setGroupInstanceArtifactsUuid(new ArrayList<>());
-	}
+    private void clearGroupInstanceArtifacts(GroupInstance group) {
+        if (group.getArtifacts() != null) {
+            group.getArtifacts().clear();
+        } else {
+            group.setArtifacts(new ArrayList<>());
+        }
+        if (group.getArtifactsUuid() != null) {
+            group.getArtifactsUuid().clear();
+        } else {
+            group.setArtifactsUuid(new ArrayList<>());
+        }
+        if (group.getGroupInstanceArtifacts() != null) {
+            group.getGroupInstanceArtifacts().clear();
+        } else {
+            group.setGroupInstanceArtifacts(new ArrayList<>());
+        }
+        if (group.getGroupInstanceArtifactsUuid() != null) {
+            group.getGroupInstanceArtifactsUuid().clear();
+        } else {
+            group.setGroupInstanceArtifactsUuid(new ArrayList<>());
+        }
+    }
 
-	private void fixArtifactUndergroupInstances(Map<String, ArtifactDefinition> artifactsMap, GroupInstance group,
-												List<String> groupArtifacts, String artifactId) {
-		String artifactlabel = findArtifactLabelFromArtifactId(artifactId);
-		log.debug("Migration1707ArtifactUuidFix  fix group:  group name {} artifactId for fix {} artifactlabel {} ",
-				group.getName(), artifactId, artifactlabel);
-		if (!artifactlabel.isEmpty() && artifactsMap.containsKey(artifactlabel)) {
-			ArtifactDefinition artifact = artifactsMap.get(artifactlabel);
-			ArtifactTypeEnum artifactType = ArtifactTypeEnum.parse(artifact.getArtifactType());
-			String correctArtifactId = artifact.getUniqueId();
-			String correctArtifactUUID = artifact.getArtifactUUID();
-			if (artifactType != ArtifactTypeEnum.HEAT_ENV) {
-				boolean isAddToGroup = true;
-				if (groupArtifacts.size() == 1) {
-					if (artifactType == ArtifactTypeEnum.HEAT_ARTIFACT) {
-						isAddToGroup = false;
-						artifact.setArtifactType(ArtifactTypeEnum.OTHER.getType());
-					}
-				}
-				if (isAddToGroup) {
-					log.debug(
-							MIGRATION1707_ARTIFACT_UUID_FIX,
-							group.getName(), correctArtifactId, correctArtifactUUID);
-					group.getArtifacts().add(correctArtifactId);
-					if (correctArtifactUUID != null && !correctArtifactUUID.isEmpty()) {
-						group.getArtifactsUuid().add(correctArtifactUUID);
-					}
-				}
-			} else {
-				log.debug(
-						MIGRATION1707_ARTIFACT_UUID_FIX,
-						group.getName(), correctArtifactId, correctArtifactUUID);
-				Set<String> tmpSet = new HashSet<>(group.getGroupInstanceArtifacts());
-				tmpSet.add(correctArtifactId);
-				group.setGroupInstanceArtifacts(new ArrayList<>(tmpSet));
-				if (correctArtifactUUID != null && !correctArtifactUUID.isEmpty()) {
-					Set<String> tmpSetUUID = new HashSet<>(group.getGroupInstanceArtifactsUuid());
-					tmpSetUUID.add(correctArtifactUUID);
-					group.setGroupInstanceArtifactsUuid(new ArrayList<>(tmpSetUUID));
-				}
-			}
-		}
-	}
+    private void fixArtifactUndergroupInstances(Map<String, ArtifactDefinition> artifactsMap, GroupInstance group,
+                                                List<String> groupArtifacts, String artifactId) {
+        String artifactlabel = findArtifactLabelFromArtifactId(artifactId);
+        log.debug("Migration1707ArtifactUuidFix  fix group:  group name {} artifactId for fix {} artifactlabel {} ",
+            group.getName(), artifactId, artifactlabel);
+        if (!artifactlabel.isEmpty() && artifactsMap.containsKey(artifactlabel)) {
+            ArtifactDefinition artifact = artifactsMap.get(artifactlabel);
+            ArtifactTypeEnum artifactType = ArtifactTypeEnum.parse(artifact.getArtifactType());
+            String correctArtifactId = artifact.getUniqueId();
+            String correctArtifactUUID = artifact.getArtifactUUID();
+            if (artifactType != ArtifactTypeEnum.HEAT_ENV) {
+                boolean isAddToGroup = true;
+                if (groupArtifacts.size() == 1 && artifactType == ArtifactTypeEnum.HEAT_ARTIFACT) {
+                    isAddToGroup = false;
+                    artifact.setArtifactType(ArtifactTypeEnum.OTHER.getType());
+                }
+                if (isAddToGroup) {
+                    log.debug(
+                        MIGRATION1707_ARTIFACT_UUID_FIX,
+                        group.getName(), correctArtifactId, correctArtifactUUID);
+                    group.getArtifacts().add(correctArtifactId);
+                    if (correctArtifactUUID != null && !correctArtifactUUID.isEmpty()) {
+                        group.getArtifactsUuid().add(correctArtifactUUID);
+                    }
+                }
+            } else {
+                log.debug(
+                    MIGRATION1707_ARTIFACT_UUID_FIX,
+                    group.getName(), correctArtifactId, correctArtifactUUID);
+                Set<String> tmpSet = new HashSet<>(group.getGroupInstanceArtifacts());
+                tmpSet.add(correctArtifactId);
+                group.setGroupInstanceArtifacts(new ArrayList<>(tmpSet));
+                if (correctArtifactUUID != null && !correctArtifactUUID.isEmpty()) {
+                    Set<String> tmpSetUUID = new HashSet<>(group.getGroupInstanceArtifactsUuid());
+                    tmpSetUUID.add(correctArtifactUUID);
+                    group.setGroupInstanceArtifactsUuid(new ArrayList<>(tmpSetUUID));
+                }
+            }
+        }
+    }
 
-	private boolean fixVf(List<Resource> vfLst) {
-		for (Resource resource : vfLst) {
-			log.debug("Migration1707ArtifactUuidFix  fix resource: id {},  name {} ", resource.getUniqueId(),
-					resource.getName());
-			Map<String, ArtifactDefinition> artifactsMap = resource.getDeploymentArtifacts();
-			List<GroupDefinition> groupsList = resource.getGroups();
-			List<GroupDefinition> groupsToDelete = new ArrayList<>();
-			if (groupsList != null && artifactsMap != null) {
-				for (GroupDefinition group : groupsList) {
-					if (group.getType().equals(Constants.DEFAULT_GROUP_VF_MODULE) && group.getArtifacts() != null) {
-						fixVfGroup(resource, artifactsMap, group);
-					}
-					if (group.getType().equals(Constants.DEFAULT_GROUP_VF_MODULE)
-							&& (group.getArtifacts() == null || group.getArtifacts().isEmpty())) {
-						log.debug(
-								"Migration1707ArtifactUuidFix  add group to delete list fix resource: id {},  name {} ",
-								resource.getUniqueId(), resource.getName(), group.getName());
-						groupsToDelete.add(group);
-					}
-				}
+    private boolean fixVf(List<Resource> vfLst) {
+        for (Resource resource : vfLst) {
+            log.debug("Migration1707ArtifactUuidFix  fix resource: id {},  name {} ", resource.getUniqueId(),
+                resource.getName());
+            Map<String, ArtifactDefinition> artifactsMap = resource.getDeploymentArtifacts();
+            List<GroupDefinition> groupsList = resource.getGroups();
+            List<GroupDefinition> groupsToDelete = new ArrayList<>();
+            if (groupsList != null && artifactsMap != null) {
+                for (GroupDefinition group : groupsList) {
+                    if (group.getType().equals(Constants.DEFAULT_GROUP_VF_MODULE) && group.getArtifacts() != null) {
+                        fixVfGroup(resource, artifactsMap, group);
+                    }
+                    if (group.getType().equals(Constants.DEFAULT_GROUP_VF_MODULE)
+                        && (group.getArtifacts() == null || group.getArtifacts().isEmpty())) {
+                        log.debug(
+                            "Migration1707ArtifactUuidFix  add group to delete list fix resource: id {},  name {} ",
+                            resource.getUniqueId(), resource.getName(), group.getName());
+                        groupsToDelete.add(group);
+                    }
+                }
 
-				if (!groupsToDelete.isEmpty()) {
-					groupsList.removeAll(groupsToDelete);
+                if (!groupsToDelete.isEmpty()) {
+                    groupsList.removeAll(groupsToDelete);
 
-				}
-			}
+                }
+            }
 
-		}
+        }
 
-		return true;
-	}
+        return true;
+    }
 
-	private void fixVfGroup(Resource resource, Map<String, ArtifactDefinition> artifactsMap, GroupDefinition group) {
-		log.debug("Migration1707ArtifactUuidFix  fix group:  resource id {}, group name {} ", resource.getUniqueId(),
-				group.getName());
-		Set<String> groupArtifactsSet = new HashSet<>(group.getArtifacts());
-		List<String> groupArtifacts = new ArrayList<>(groupArtifactsSet);
-		group.getArtifacts().clear();
-		group.getArtifactsUuid().clear();
+    private void fixVfGroup(Resource resource, Map<String, ArtifactDefinition> artifactsMap, GroupDefinition group) {
+        log.debug("Migration1707ArtifactUuidFix  fix group:  resource id {}, group name {} ", resource.getUniqueId(),
+            group.getName());
+        Set<String> groupArtifactsSet = new HashSet<>(group.getArtifacts());
+        List<String> groupArtifacts = new ArrayList<>(groupArtifactsSet);
+        group.getArtifacts().clear();
+        group.getArtifactsUuid().clear();
 
-		for (String artifactId : groupArtifacts) {
-			fixArtifactUnderGroup(artifactsMap, group, groupArtifacts, artifactId);
-		}
-	}
+        for (String artifactId : groupArtifacts) {
+            fixArtifactUnderGroup(artifactsMap, group, groupArtifacts, artifactId);
+        }
+    }
 
-	private void fixArtifactUnderGroup(Map<String, ArtifactDefinition> artifactsMap, GroupDefinition group,
-									   List<String> groupArtifacts, String artifactId) {
+    private void fixArtifactUnderGroup(Map<String, ArtifactDefinition> artifactsMap, GroupDefinition group,
+                                       List<String> groupArtifacts, String artifactId) {
 
-		String artifactlabel = findArtifactLabelFromArtifactId(artifactId);
-		log.debug("Migration1707ArtifactUuidFix  fix group:  group name {} artifactId for fix {} artifactlabel {} ",
-				group.getName(), artifactId, artifactlabel);
-		if (!artifactlabel.isEmpty() && artifactsMap.containsKey(artifactlabel)) {
-			ArtifactDefinition artifact = artifactsMap.get(artifactlabel);
-			String correctArtifactId = artifact.getUniqueId();
-			String correctArtifactUUID = artifact.getArtifactUUID();
-			boolean isAddToGroup = true;
-			if (groupArtifacts.size() == 1) {
-				ArtifactTypeEnum artifactType = ArtifactTypeEnum.parse(artifact.getArtifactType());
-				if (artifactType == ArtifactTypeEnum.HEAT_ARTIFACT) {
-					isAddToGroup = false;
-					artifact.setArtifactType(ArtifactTypeEnum.OTHER.getType());
-				}
-			}
-			if (isAddToGroup) {
-				log.debug(
-						MIGRATION1707_ARTIFACT_UUID_FIX,
-						group.getName(), correctArtifactId, correctArtifactUUID);
-				group.getArtifacts().add(correctArtifactId);
-				if (correctArtifactUUID != null && !correctArtifactUUID.isEmpty()) {
-					group.getArtifactsUuid().add(correctArtifactUUID);
-				}
-			}
+        String artifactlabel = findArtifactLabelFromArtifactId(artifactId);
+        log.debug("Migration1707ArtifactUuidFix  fix group:  group name {} artifactId for fix {} artifactlabel {} ",
+            group.getName(), artifactId, artifactlabel);
+        if (!artifactlabel.isEmpty() && artifactsMap.containsKey(artifactlabel)) {
+            ArtifactDefinition artifact = artifactsMap.get(artifactlabel);
+            String correctArtifactId = artifact.getUniqueId();
+            String correctArtifactUUID = artifact.getArtifactUUID();
+            boolean isAddToGroup = true;
+            if (groupArtifacts.size() == 1) {
+                ArtifactTypeEnum artifactType = ArtifactTypeEnum.parse(artifact.getArtifactType());
+                if (artifactType == ArtifactTypeEnum.HEAT_ARTIFACT) {
+                    isAddToGroup = false;
+                    artifact.setArtifactType(ArtifactTypeEnum.OTHER.getType());
+                }
+            }
+            if (isAddToGroup) {
+                log.debug(
+                    MIGRATION1707_ARTIFACT_UUID_FIX,
+                    group.getName(), correctArtifactId, correctArtifactUUID);
+                group.getArtifacts().add(correctArtifactId);
+                if (correctArtifactUUID != null && !correctArtifactUUID.isEmpty()) {
+                    group.getArtifactsUuid().add(correctArtifactUUID);
+                }
+            }
 
-		}
-	}
+        }
+    }
 
-	private String findArtifactLabelFromArtifactId(String artifactId) {
-		String artifactLabel = "";
+    private String findArtifactLabelFromArtifactId(String artifactId) {
+        String artifactLabel = "";
 
-		int index = artifactId.lastIndexOf('.');
-		if (index > 0 && index + 1 < artifactId.length())
-			artifactLabel = artifactId.substring(index + 1);
-		return artifactLabel;
-	}
+        int index = artifactId.lastIndexOf('.');
+        if (index > 0 && index + 1 < artifactId.length()) {
+            artifactLabel = artifactId.substring(index + 1);
+        }
+        return artifactLabel;
+    }
 
-	private void writeModuleResultToFile(Writer writer, org.openecomp.sdc.be.model.Component component,
-										 Service service) {
-		try {
-			// "service name, service id, state, version
-			StringBuilder sb = new StringBuilder(component.getName());
-			sb.append(",").append(component.getUniqueId()).append(",").append(component.getLifecycleState()).append(",")
-					.append(component.getVersion());
-			if (service != null) {
-				sb.append(",").append(service.getName());
-			}
-			sb.append("\n");
-			writer.write(sb.toString());
-		} catch (IOException e) {
-			log.error(e.getMessage());
-		}
-	}
+    private void writeModuleResultToFile(Writer writer, org.openecomp.sdc.be.model.Component component,
+                                         Service service) {
+        try {
+            // "service name, service id, state, version
+            StringBuilder sb = new StringBuilder(component.getName());
+            sb.append(",").append(component.getUniqueId()).append(",").append(component.getLifecycleState()).append(",")
+                .append(component.getVersion());
+            if (service != null) {
+                sb.append(",").append(service.getName());
+            }
+            sb.append("\n");
+            writer.write(sb.toString());
+        } catch (IOException e) {
+            log.error(e.getMessage());
+        }
+    }
 
-	private void writeModuleResultToFile(Writer writer, List<Component> components) {
-		try {
-			// "service name, service id, state, version
-			for (Component component : components) {
-				StringBuilder sb = new StringBuilder(component.getName());
-				sb.append(",").append(component.getUniqueId()).append(",").append(component.getInvariantUUID())
-						.append(",").append(component.getLifecycleState()).append(",").append(component.getVersion());
+    private void writeModuleResultToFile(Writer writer, List<Component> components) {
+        try {
+            // "service name, service id, state, version
+            for (Component component : components) {
+                StringBuilder sb = new StringBuilder(component.getName());
+                sb.append(",").append(component.getUniqueId()).append(",").append(component.getInvariantUUID())
+                    .append(",").append(component.getLifecycleState()).append(",").append(component.getVersion());
 
-				sb.append("\n");
-				writer.write(sb.toString());
-			}
-		} catch (IOException e) {
+                sb.append("\n");
+                writer.write(sb.toString());
+            }
+        } catch (IOException e) {
 
-		    log.error(e.getMessage());
-		}
-	}
+            log.error(e.getMessage());
+        }
+    }
 
-	public boolean doFixTosca(Map<String, List<Component>> nodeToFix, Map<String, List<Component>> vfToFix,
-							  Map<String, List<Component>> serviceToFix) {
+    public boolean doFixTosca(Map<String, List<Component>> nodeToFix, Map<String, List<Component>> vfToFix,
+                              Map<String, List<Component>> serviceToFix) {
 
-		Map<GraphPropertyEnum, Object> hasProps = new EnumMap<>(GraphPropertyEnum.class);
-		hasProps.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.RESOURCE.name());
-		hasProps.put(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name());
+        Map<GraphPropertyEnum, Object> hasProps = new EnumMap<>(GraphPropertyEnum.class);
+        hasProps.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.RESOURCE.name());
+        hasProps.put(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name());
 
-		Map<String, List<Component>> vertices = getVerticesToValidate(VertexTypeEnum.NODE_TYPE, hasProps);
-		validateTosca(vertices, nodeToFix, "RESOURCE_TOSCA_ARTIFACTS");//
+        Map<String, List<Component>> vertices = getVerticesToValidate(VertexTypeEnum.NODE_TYPE, hasProps);
+        validateTosca(vertices, nodeToFix, "RESOURCE_TOSCA_ARTIFACTS");//
 
-		hasProps.clear();
-		hasProps.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.RESOURCE.name());
-		hasProps.put(GraphPropertyEnum.RESOURCE_TYPE, ResourceTypeEnum.VF);
-		hasProps.put(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name());
+        hasProps.clear();
+        hasProps.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.RESOURCE.name());
+        hasProps.put(GraphPropertyEnum.RESOURCE_TYPE, ResourceTypeEnum.VF);
+        hasProps.put(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name());
 
-		vertices = getVerticesToValidate(VertexTypeEnum.TOPOLOGY_TEMPLATE, hasProps);
-		validateTosca(vertices, vfToFix, "VF_TOSCA_ARTIFACTS");
+        vertices = getVerticesToValidate(VertexTypeEnum.TOPOLOGY_TEMPLATE, hasProps);
+        validateTosca(vertices, vfToFix, "VF_TOSCA_ARTIFACTS");
 
-		hasProps.clear();
-		hasProps.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.SERVICE.name());
-		hasProps.put(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name());
+        hasProps.clear();
+        hasProps.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.SERVICE.name());
+        hasProps.put(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name());
 
-		vertices = getVerticesToValidate(VertexTypeEnum.TOPOLOGY_TEMPLATE, hasProps);
-		return validateTosca(vertices, serviceToFix, "SERVICE_TOSCA_ARTIFACTS");
-	}
+        vertices = getVerticesToValidate(VertexTypeEnum.TOPOLOGY_TEMPLATE, hasProps);
+        return validateTosca(vertices, serviceToFix, "SERVICE_TOSCA_ARTIFACTS");
+    }
 
-	public Map<String, List<Component>> getVerticesToValidate(VertexTypeEnum type,
-															  Map<GraphPropertyEnum, Object> hasProps) {
+    public Map<String, List<Component>> getVerticesToValidate(VertexTypeEnum type,
+                                                              Map<GraphPropertyEnum, Object> hasProps) {
 
-		Map<String, List<Component>> result = new HashMap<>();
-		try {
+        Map<String, List<Component>> result = new HashMap<>();
+        try {
 
-			Either<List<GraphVertex>, JanusGraphOperationStatus> resultsEither = janusGraphDao
-          .getByCriteria(type, hasProps);
-			if (resultsEither.isRight()) {
-				log.error("getVerticesToValidate failed {} ",resultsEither.right().value());
-				return result;
-			}
-			log.info("getVerticesToValidate: {}  vertices to scan", resultsEither.left().value().size());
-			List<GraphVertex> componentsList = resultsEither.left().value();
-			componentsList.forEach(vertex -> {
-				String ivariantUuid = (String) vertex.getMetadataProperty(GraphPropertyEnum.INVARIANT_UUID);
-				if (!result.containsKey(ivariantUuid)) {
-					List<Component> compList = new ArrayList<>();
-					result.put(ivariantUuid, compList);
-				}
-				List<Component> compList = result.get(ivariantUuid);
+            Either<List<GraphVertex>, JanusGraphOperationStatus> resultsEither = janusGraphDao
+                .getByCriteria(type, hasProps);
+            if (resultsEither.isRight()) {
+                log.error("getVerticesToValidate failed {} ", resultsEither.right().value());
+                return result;
+            }
+            log.info("getVerticesToValidate: {}  vertices to scan", resultsEither.left().value().size());
+            List<GraphVertex> componentsList = resultsEither.left().value();
+            componentsList.forEach(vertex -> {
+                String ivariantUuid = (String) vertex.getMetadataProperty(GraphPropertyEnum.INVARIANT_UUID);
+                if (!result.containsKey(ivariantUuid)) {
+                    List<Component> compList = new ArrayList<>();
+                    result.put(ivariantUuid, compList);
+                }
+                List<Component> compList = result.get(ivariantUuid);
 
-				ComponentParametersView filter = new ComponentParametersView(true);
-				filter.setIgnoreArtifacts(false);
+                ComponentParametersView filter = new ComponentParametersView(true);
+                filter.setIgnoreArtifacts(false);
 
-				Either<Component, StorageOperationStatus> toscaElement = toscaOperationFacade
-						.getToscaElement(vertex.getUniqueId(), filter);
-				if (toscaElement.isRight()) {
-					log.error("getVerticesToValidate: failed to find element {}  staus is {}", vertex.getUniqueId()
-							,toscaElement.right().value());
-				} else {
-					compList.add(toscaElement.left().value());
-				}
-				janusGraphDao.commit();
+                Either<Component, StorageOperationStatus> toscaElement = toscaOperationFacade
+                    .getToscaElement(vertex.getUniqueId(), filter);
+                if (toscaElement.isRight()) {
+                    log.error("getVerticesToValidate: failed to find element {}  staus is {}", vertex.getUniqueId()
+                        , toscaElement.right().value());
+                } else {
+                    compList.add(toscaElement.left().value());
+                }
+                janusGraphDao.commit();
 
-			});
+            });
 
-		} catch (Exception e) {
-			log.info(FAILED_TO_FETCH_VF_RESOURCES, e);
+        } catch (Exception e) {
+            log.info(FAILED_TO_FETCH_VF_RESOURCES, e);
 
-		} finally {
-			janusGraphDao.commit();
+        } finally {
+            janusGraphDao.commit();
 
-		}
-		return result;
-	}
+        }
+        return result;
+    }
 
-	public boolean validateTosca(Map<String, List<Component>> vertices, Map<String, List<Component>> compToFix,
-								 String name) {
-		boolean result = true;
-		long time = System.currentTimeMillis();
-		String fileName = name + "_" + time + ".csv";
-		try(Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName), UTF8))) {
-			writer.write("name, UUID, invariantUUID, state, version\n");
-			for (Map.Entry<String, List<Component>> entry : vertices.entrySet()) {
-				List<Component> compList = entry.getValue();
-				Set<String> artifactEsId = new HashSet<>();
-				for (Component component : compList) {
-					Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
-					Optional<ArtifactDefinition> op = toscaArtifacts.values().stream()
-							.filter(a -> artifactEsId.contains(a.getEsId()) && a.getEsId() != null).findAny();
-					if (op.isPresent()) {
-						result = false;
-						writeModuleResultToFile(writer, compList);
-						writer.flush();
-						break;
-					} else {
-						artifactEsId.addAll(toscaArtifacts.values().stream().map(ArtifactDefinition::getEsId)
-								.collect(Collectors.toList()));
-					}
-				}
-				if (!result) {
-					List<Component> compListfull = new ArrayList<>();
-					for (Component c : compList) {
-						ComponentParametersView filter = new ComponentParametersView(true);
-						filter.setIgnoreComponentInstances(false);
-						filter.setIgnoreArtifacts(false);
-						filter.setIgnoreGroups(false);
+    public boolean validateTosca(Map<String, List<Component>> vertices, Map<String, List<Component>> compToFix,
+                                 String name) {
+        boolean result = true;
+        long time = System.currentTimeMillis();
+        String fileName = name + "_" + time + ".csv";
+        try (Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName), UTF_8))) {
+            writer.write("name, UUID, invariantUUID, state, version\n");
+            for (Map.Entry<String, List<Component>> entry : vertices.entrySet()) {
+                List<Component> compList = entry.getValue();
+                Set<String> artifactEsId = new HashSet<>();
+                for (Component component : compList) {
+                    Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
+                    Optional<ArtifactDefinition> op = toscaArtifacts.values().stream()
+                        .filter(a -> artifactEsId.contains(a.getEsId()) && a.getEsId() != null).findAny();
+                    if (op.isPresent()) {
+                        result = false;
+                        writeModuleResultToFile(writer, compList);
+                        writer.flush();
+                        break;
+                    } else {
+                        artifactEsId.addAll(toscaArtifacts.values().stream().map(ArtifactDefinition::getEsId)
+                            .collect(Collectors.toList()));
+                    }
+                }
+                if (!result) {
+                    List<Component> compListfull = new ArrayList<>();
+                    for (Component c : compList) {
+                        ComponentParametersView filter = new ComponentParametersView(true);
+                        filter.setIgnoreComponentInstances(false);
+                        filter.setIgnoreArtifacts(false);
+                        filter.setIgnoreGroups(false);
 
-						Either<Component, StorageOperationStatus> toscaElement = toscaOperationFacade
-								.getToscaElement(c.getUniqueId(), filter);
-						if (toscaElement.isRight()) {
-							log.debug("getVerticesToValidate: failed to find element" + c.getUniqueId()
-									+ " status is" + toscaElement.right().value());
-						} else {
-							compListfull.add(toscaElement.left().value());
-						}
-						this.janusGraphDao.commit();
-					}
+                        Either<Component, StorageOperationStatus> toscaElement = toscaOperationFacade
+                            .getToscaElement(c.getUniqueId(), filter);
+                        if (toscaElement.isRight()) {
+                            log.debug("getVerticesToValidate: failed to find element {} status is {}", c.getUniqueId(), toscaElement.right().value());
+                        } else {
+                            compListfull.add(toscaElement.left().value());
+                        }
+                        this.janusGraphDao.commit();
+                    }
 
-					compToFix.put(entry.getKey(), compListfull);
-					result = true;
-				}
+                    compToFix.put(entry.getKey(), compListfull);
+                    result = true;
+                }
 
-			}
+            }
 
-		} catch (Exception e) {
-			log.info(FAILED_TO_FETCH_VF_RESOURCES, e);
-			return false;
-		} finally {
-			janusGraphDao.commit();
-		}
-		return result;
-	}
+        } catch (Exception e) {
+            log.info(FAILED_TO_FETCH_VF_RESOURCES, e);
+            return false;
+        } finally {
+            janusGraphDao.commit();
+        }
+        return result;
+    }
 
-	private Either<Component, ToscaError> generateToscaArtifact(Component parent) {
-		log.debug("tosca artifact generation");
-		try {
-			Map<String, ArtifactDefinition> toscaArtifacts = parent.getToscaArtifacts();
+    private Either<Component, ToscaError> generateToscaArtifact(Component parent) {
+        log.debug("tosca artifact generation");
+        try {
+            Map<String, ArtifactDefinition> toscaArtifacts = parent.getToscaArtifacts();
 
-			ArtifactDefinition toscaArtifact = null;
-			Optional<ArtifactDefinition> op = toscaArtifacts.values().stream()
-					.filter(p -> p.getArtifactType().equals(ArtifactTypeEnum.TOSCA_TEMPLATE.getType())).findAny();
+            ArtifactDefinition toscaArtifact = null;
+            Optional<ArtifactDefinition> op = toscaArtifacts.values().stream()
+                .filter(p -> p.getArtifactType().equals(ArtifactTypeEnum.TOSCA_TEMPLATE.getType())).findAny();
 
-			if (op.isPresent()) {
-				toscaArtifact = op.get();
-			}
-			if (toscaArtifact != null) {
-				log.debug("Migration1707ArtifactUuidFix  generateToscaPerComponent artifact name {} id {} esId {}",
-						toscaArtifact.getArtifactName(), toscaArtifact.getUniqueId(), toscaArtifact.getEsId());
+            if (op.isPresent()) {
+                toscaArtifact = op.get();
+            }
+            if (toscaArtifact != null) {
+                log.debug("Migration1707ArtifactUuidFix  generateToscaPerComponent artifact name {} id {} esId {}",
+                    toscaArtifact.getArtifactName(), toscaArtifact.getUniqueId(), toscaArtifact.getEsId());
 
-				Either<ToscaRepresentation, ToscaError> exportComponent = toscaExportUtils.exportComponent(parent);
-				if (exportComponent.isRight()) {
-					log.debug("Failed export tosca yaml for component {} error {}", parent.getUniqueId(),
-							exportComponent.right().value());
+                Either<ToscaRepresentation, ToscaError> exportComponent = toscaExportUtils.exportComponent(parent);
+                if (exportComponent.isRight()) {
+                    log.debug("Failed export tosca yaml for component {} error {}", parent.getUniqueId(),
+                        exportComponent.right().value());
 
-					return Either.right(exportComponent.right().value());
-				}
-				log.debug("Tosca yaml exported for component {} ", parent.getUniqueId());
+                    return Either.right(exportComponent.right().value());
+                }
+                log.debug("Tosca yaml exported for component {} ", parent.getUniqueId());
 
-				toscaArtifact.setPayload(exportComponent.left().value().getMainYaml());
-				byte[] decodedPayload = toscaArtifact.getPayloadData();
+                toscaArtifact.setPayload(exportComponent.left().value().getMainYaml());
+                byte[] decodedPayload = toscaArtifact.getPayloadData();
 
-				String uniqueId = UniqueIdBuilder.buildPropertyUniqueId(parent.getUniqueId(),
-						toscaArtifact.getArtifactLabel());
-				toscaArtifact.setUniqueId(uniqueId);
-				toscaArtifact.setEsId(toscaArtifact.getUniqueId());
+                String uniqueId = UniqueIdBuilder.buildPropertyUniqueId(parent.getUniqueId(),
+                    toscaArtifact.getArtifactLabel());
+                toscaArtifact.setUniqueId(uniqueId);
+                toscaArtifact.setEsId(toscaArtifact.getUniqueId());
 
-				toscaArtifact.setArtifactChecksum(GeneralUtility.calculateMD5Base64EncodedByByteArray(decodedPayload));
-				DAOArtifactData artifactData = new DAOArtifactData(toscaArtifact.getEsId(), decodedPayload);
-				artifactCassandraDao.saveArtifact(artifactData);
+                toscaArtifact.setArtifactChecksum(GeneralUtility.calculateMD5Base64EncodedByByteArray(decodedPayload));
+                DAOArtifactData artifactData = new DAOArtifactData(toscaArtifact.getEsId(), decodedPayload);
+                artifactCassandraDao.saveArtifact(artifactData);
 
-				log.debug("Tosca yaml artifact esId  {} ", toscaArtifact.getEsId());
-			}
-			ArtifactDefinition csarArtifact = null;
-			op = toscaArtifacts.values().stream()
-					.filter(p -> p.getArtifactType().equals(ArtifactTypeEnum.TOSCA_CSAR.getType())).findAny();
+                log.debug("Tosca yaml artifact esId  {} ", toscaArtifact.getEsId());
+            }
+            ArtifactDefinition csarArtifact = null;
+            op = toscaArtifacts.values().stream()
+                .filter(p -> p.getArtifactType().equals(ArtifactTypeEnum.TOSCA_CSAR.getType())).findAny();
 
-			if (op.isPresent()) {
-				csarArtifact = op.get();
-			}
+            if (op.isPresent()) {
+                csarArtifact = op.get();
+            }
 
-			if (csarArtifact != null) {
-				Either<byte[], ResponseFormat> generated = csarUtils.createCsar(parent, true, true);
+            if (csarArtifact != null) {
+                Either<byte[], ResponseFormat> generated = csarUtils.createCsar(parent, true, true);
 
-				if (generated.isRight()) {
-					log.debug("Failed to export tosca csar for component {} error {}", parent.getUniqueId(),
-							generated.right().value());
+                if (generated.isRight()) {
+                    log.debug("Failed to export tosca csar for component {} error {}", parent.getUniqueId(),
+                        generated.right().value());
 
-					return Either.right(ToscaError.GENERAL_ERROR);
-				}
-				byte[] value = generated.left().value();
-				csarArtifact.setPayload(value);
-				byte[] decodedPayload = csarArtifact.getPayloadData();
+                    return Either.right(ToscaError.GENERAL_ERROR);
+                }
+                byte[] value = generated.left().value();
+                csarArtifact.setPayload(value);
+                byte[] decodedPayload = csarArtifact.getPayloadData();
 
-				String uniqueId = UniqueIdBuilder.buildPropertyUniqueId(parent.getUniqueId(),
-						csarArtifact.getArtifactLabel());
-				csarArtifact.setUniqueId(uniqueId);
-				csarArtifact.setEsId(csarArtifact.getUniqueId());
+                String uniqueId = UniqueIdBuilder.buildPropertyUniqueId(parent.getUniqueId(),
+                    csarArtifact.getArtifactLabel());
+                csarArtifact.setUniqueId(uniqueId);
+                csarArtifact.setEsId(csarArtifact.getUniqueId());
 
-				csarArtifact.setArtifactChecksum(GeneralUtility.calculateMD5Base64EncodedByByteArray(decodedPayload));
-				DAOArtifactData artifactData = new DAOArtifactData(csarArtifact.getEsId(), decodedPayload);
-				artifactCassandraDao.saveArtifact(artifactData);
-				log.debug("Tosca csar artifact esId  {} ", csarArtifact.getEsId());
+                csarArtifact.setArtifactChecksum(GeneralUtility.calculateMD5Base64EncodedByByteArray(decodedPayload));
+                DAOArtifactData artifactData = new DAOArtifactData(csarArtifact.getEsId(), decodedPayload);
+                artifactCassandraDao.saveArtifact(artifactData);
+                log.debug("Tosca csar artifact esId  {} ", csarArtifact.getEsId());
 
-			}
+            }
 
-		} catch (Exception ex) {
-			log.error("Failed to generate tosca atifact component id {} component name {} error {}",
-					parent.getUniqueId(), parent.getName(), ex.getMessage());
+        } catch (Exception ex) {
+            log.error("Failed to generate tosca atifact component id {} component name {} error {}",
+                parent.getUniqueId(), parent.getName(), ex.getMessage());
 
-			return Either.right(ToscaError.GENERAL_ERROR);
-		}
+            return Either.right(ToscaError.GENERAL_ERROR);
+        }
 
-		return Either.left(parent);
-	}
+        return Either.left(parent);
+    }
 
-	private ArtifactDefinition createVfModuleArtifact(ComponentInstance currVF, Service service) {
+    private ArtifactDefinition createVfModuleArtifact(ComponentInstance currVF) {
 
-		ArtifactDefinition vfModuleArtifactDefinition = new ArtifactDefinition();
+        ArtifactDefinition vfModuleArtifactDefinition = new ArtifactDefinition();
 
-		vfModuleArtifactDefinition.setDescription("Auto-generated VF Modules information artifact");
-		vfModuleArtifactDefinition.setArtifactDisplayName("Vf Modules Metadata");
-		vfModuleArtifactDefinition.setArtifactType(ArtifactTypeEnum.VF_MODULES_METADATA.getType());
-		vfModuleArtifactDefinition.setArtifactGroupType(ArtifactGroupTypeEnum.DEPLOYMENT);
-		vfModuleArtifactDefinition.setArtifactLabel("vfModulesMetadata");
-		vfModuleArtifactDefinition.setTimeout(0);
-		vfModuleArtifactDefinition.setArtifactName(currVF.getNormalizedName() + "_modules.json");
+        vfModuleArtifactDefinition.setDescription("Auto-generated VF Modules information artifact");
+        vfModuleArtifactDefinition.setArtifactDisplayName("Vf Modules Metadata");
+        vfModuleArtifactDefinition.setArtifactType(ArtifactTypeEnum.VF_MODULES_METADATA.getType());
+        vfModuleArtifactDefinition.setArtifactGroupType(ArtifactGroupTypeEnum.DEPLOYMENT);
+        vfModuleArtifactDefinition.setArtifactLabel("vfModulesMetadata");
+        vfModuleArtifactDefinition.setTimeout(0);
+        vfModuleArtifactDefinition.setArtifactName(currVF.getNormalizedName() + "_modules.json");
 
-		return vfModuleArtifactDefinition;
-	}
+        return vfModuleArtifactDefinition;
+    }
 
 
-	private void fillVfModuleInstHeatEnvPayload(Component parent, ComponentInstance instance, List<GroupInstance> groupsForCurrVF,
-												ArtifactDefinition vfModuleArtifact) {
-		log.debug("generate new vf module for component. name  {}, id {}, Version {}", instance.getName(), instance.getUniqueId());
+    private void fillVfModuleInstHeatEnvPayload(Component parent, ComponentInstance instance, List<GroupInstance> groupsForCurrVF,
+                                                ArtifactDefinition vfModuleArtifact) {
+        log.debug("generate new vf module for component. name  {}, id {}, Version {}", instance.getName(), instance.getUniqueId());
 
-		String uniqueId = UniqueIdBuilder.buildInstanceArtifactUniqueId(parent.getUniqueId(), instance.getUniqueId(), vfModuleArtifact.getArtifactLabel());
+        String uniqueId = UniqueIdBuilder
+            .buildInstanceArtifactUniqueId(parent.getUniqueId(), instance.getUniqueId(), vfModuleArtifact.getArtifactLabel());
 
-		vfModuleArtifact.setUniqueId(uniqueId);
-		vfModuleArtifact.setEsId(vfModuleArtifact.getUniqueId());
+        vfModuleArtifact.setUniqueId(uniqueId);
+        vfModuleArtifact.setEsId(vfModuleArtifact.getUniqueId());
 
-		List<VfModuleArtifactPayload> vfModulePayloadForCurrVF = new ArrayList<>();
-		if (groupsForCurrVF != null) {
-			for (GroupInstance groupInstance : groupsForCurrVF) {
-				VfModuleArtifactPayload modulePayload = new VfModuleArtifactPayload(groupInstance);
-				vfModulePayloadForCurrVF.add(modulePayload);
-			}
-			Collections.sort(vfModulePayloadForCurrVF,
-					(art1, art2) -> VfModuleArtifactPayload.compareByGroupName(art1, art2));
+        List<VfModuleArtifactPayload> vfModulePayloadForCurrVF = new ArrayList<>();
+        if (groupsForCurrVF != null) {
+            for (GroupInstance groupInstance : groupsForCurrVF) {
+                VfModuleArtifactPayload modulePayload = new VfModuleArtifactPayload(groupInstance);
+                vfModulePayloadForCurrVF.add(modulePayload);
+            }
+            Collections.sort(vfModulePayloadForCurrVF,
+                (art1, art2) -> VfModuleArtifactPayload.compareByGroupName(art1, art2));
 
-			final Gson gson = new GsonBuilder().setPrettyPrinting().create();
+            final Gson gson = new GsonBuilder().setPrettyPrinting().create();
 
-			String vfModulePayloadString = gson.toJson(vfModulePayloadForCurrVF);
-			log.debug("vfModulePayloadString {}", vfModulePayloadString);
-			if (vfModulePayloadString != null) {
-				String newCheckSum = GeneralUtility
-						.calculateMD5Base64EncodedByByteArray(vfModulePayloadString.getBytes());
-				vfModuleArtifact.setArtifactChecksum(newCheckSum);
+            String vfModulePayloadString = gson.toJson(vfModulePayloadForCurrVF);
+            log.debug("vfModulePayloadString {}", vfModulePayloadString);
+            if (vfModulePayloadString != null) {
+                String newCheckSum = GeneralUtility
+                    .calculateMD5Base64EncodedByByteArray(vfModulePayloadString.getBytes());
+                vfModuleArtifact.setArtifactChecksum(newCheckSum);
 
-				DAOArtifactData artifactData = new DAOArtifactData(vfModuleArtifact.getEsId(),
-						vfModulePayloadString.getBytes());
-				artifactCassandraDao.saveArtifact(artifactData);
+                DAOArtifactData artifactData = new DAOArtifactData(vfModuleArtifact.getEsId(),
+                    vfModulePayloadString.getBytes());
+                artifactCassandraDao.saveArtifact(artifactData);
 
-			}
+            }
 
-		}
+        }
 
-	}
+    }
 
-	private Either<List<VfModuleArtifactPayloadEx>, StorageOperationStatus> parseVFModuleJson(ArtifactDefinition vfModuleArtifact) {
-		log.info("Try to get vfModule json from cassandra {}", vfModuleArtifact.getEsId());
-		Either<DAOArtifactData, CassandraOperationStatus> vfModuleData = artifactCassandraDao.getArtifact(vfModuleArtifact.getEsId());
+    private Either<List<VfModuleArtifactPayloadEx>, StorageOperationStatus> parseVFModuleJson(ArtifactDefinition vfModuleArtifact) {
+        log.info("Try to get vfModule json from cassandra {}", vfModuleArtifact.getEsId());
+        Either<DAOArtifactData, CassandraOperationStatus> vfModuleData = artifactCassandraDao.getArtifact(vfModuleArtifact.getEsId());
 
-		if (vfModuleData.isRight()) {
-			CassandraOperationStatus resourceUploadStatus = vfModuleData.right().value();
-			StorageOperationStatus storageResponse = DaoStatusConverter.convertCassandraStatusToStorageStatus(resourceUploadStatus);
-			log.error("failed to fetch vfModule json {} from cassandra. Status is {}", vfModuleArtifact.getEsId(), storageResponse);
-			return Either.right(storageResponse);
+        if (vfModuleData.isRight()) {
+            CassandraOperationStatus resourceUploadStatus = vfModuleData.right().value();
+            StorageOperationStatus storageResponse = DaoStatusConverter.convertCassandraStatusToStorageStatus(resourceUploadStatus);
+            log.error("failed to fetch vfModule json {} from cassandra. Status is {}", vfModuleArtifact.getEsId(), storageResponse);
+            return Either.right(storageResponse);
 
-		}
+        }
 
-		DAOArtifactData DAOArtifactData = vfModuleData.left().value();
-		String gsonData = new String( DAOArtifactData.getDataAsArray());
-		final Gson gson = new GsonBuilder().setPrettyPrinting().create();
-		JsonArray jsonElement = new JsonArray();
-		jsonElement = gson.fromJson(gsonData, jsonElement.getClass());
-		List<VfModuleArtifactPayloadEx> vfModules = new ArrayList<>();
-		jsonElement.forEach(je ->{
-			VfModuleArtifactPayloadEx vfModule = ComponentsUtils.parseJsonToObject(je.toString(), VfModuleArtifactPayloadEx.class);
-			vfModules.add(vfModule);
-		});
+        DAOArtifactData daoArtifactData = vfModuleData.left().value();
+        String gsonData = new String(daoArtifactData.getDataAsArray());
+        final Gson gson = new GsonBuilder().setPrettyPrinting().create();
+        JsonArray jsonElement = new JsonArray();
+        jsonElement = gson.fromJson(gsonData, jsonElement.getClass());
+        List<VfModuleArtifactPayloadEx> vfModules = new ArrayList<>();
+        jsonElement.forEach(je -> {
+            VfModuleArtifactPayloadEx vfModule = ComponentsUtils.parseJsonToObject(je.toString(), VfModuleArtifactPayloadEx.class);
+            vfModules.add(vfModule);
+        });
 
-		log.debug  ("parse vf module finish {}", gsonData);
-		return Either.left(vfModules);
+        log.debug("parse vf module finish {}", gsonData);
+        return Either.left(vfModules);
 
-	}
+    }
 }
 
 
diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/internal/tool/CsarGenerator.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/internal/tool/CsarGenerator.java
index 6c5ffb7..751801f 100644
--- a/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/internal/tool/CsarGenerator.java
+++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/internal/tool/CsarGenerator.java
@@ -7,9 +7,9 @@
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *      http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -19,6 +19,15 @@
  */
 package org.openecomp.sdc.asdctool.impl.internal.tool;
 
+import java.io.IOException;
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Scanner;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
 import org.openecomp.sdc.asdctool.utils.ConsoleWriter;
 import org.openecomp.sdc.be.dao.cassandra.ArtifactCassandraDao;
 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
@@ -40,20 +49,9 @@
 import org.openecomp.sdc.be.tosca.ToscaExportHandler;
 import org.openecomp.sdc.be.tosca.ToscaRepresentation;
 import org.openecomp.sdc.common.api.ArtifactTypeEnum;
-import org.openecomp.sdc.common.log.wrappers.Logger;
 import org.openecomp.sdc.common.util.GeneralUtility;
 import org.springframework.beans.factory.annotation.Autowired;
 
-import java.io.IOException;
-import java.util.EnumMap;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Scanner;
-import java.util.function.Supplier;
-import java.util.stream.Collectors;
-
 @org.springframework.stereotype.Component("csarGenerator")
 public class CsarGenerator extends CommonInternalTool {
 
@@ -65,8 +63,8 @@
 
     @Autowired
     public CsarGenerator(JanusGraphDao janusGraphDao, CsarUtils csarUtils,
-        ToscaOperationFacade toscaOperationFacade,
-        ArtifactCassandraDao artifactCassandraDao, ToscaExportHandler toscaExportHandler) {
+                         ToscaOperationFacade toscaOperationFacade,
+                         ArtifactCassandraDao artifactCassandraDao, ToscaExportHandler toscaExportHandler) {
         super("generate");
         this.janusGraphDao = janusGraphDao;
         this.csarUtils = csarUtils;
@@ -75,8 +73,6 @@
         this.toscaExportHandler = toscaExportHandler;
     }
 
-    private static Logger log = Logger.getLogger(CsarGenerator.class.getName());
-
     public void generateCsar(String uuid, Scanner scanner) {
         JanusGraphOperationStatus status = JanusGraphOperationStatus.OK;
 
@@ -98,7 +94,7 @@
                 ConsoleWriter.dataLine("\nGenerate CSAR (yes/no)?");
                 String input = scanner.nextLine();
                 if (input.equalsIgnoreCase("yes")) {
-                    
+
                     status = handleService(metadataV, uuid);
                 }
             }
@@ -119,47 +115,51 @@
 
             Supplier<byte[]> supplier = () -> generateToscaPayload(component);
             generateArtifact(component, ArtifactTypeEnum.TOSCA_TEMPLATE, supplier);
-            
+
             supplier = () -> generateCsarPayload(component);
             generateArtifact(component, ArtifactTypeEnum.TOSCA_CSAR, supplier);
-            
+
             GraphVertex toscaArtifactV = janusGraphDao
-                .getChildVertex(metadataV, EdgeLabelEnum.TOSCA_ARTIFACTS, JsonParseFlagEnum.ParseJson).either(l->l, r->null);
-            if ( toscaArtifactV != null ){
-                Map<String, ArtifactDataDefinition> copy = component.getToscaArtifacts().entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> new ArtifactDataDefinition(e.getValue())));
+                .getChildVertex(metadataV, EdgeLabelEnum.TOSCA_ARTIFACTS, JsonParseFlagEnum.ParseJson).either(l -> l, r -> null);
+            if (toscaArtifactV != null) {
+                Map<String, ArtifactDataDefinition> copy = component.getToscaArtifacts().entrySet().stream()
+                    .collect(Collectors.toMap(Map.Entry::getKey, e -> new ArtifactDataDefinition(e.getValue())));
                 toscaArtifactV.setJson(copy);
                 janusGraphDao.updateVertex(toscaArtifactV);
             }
-           
+
         } else {
             ConsoleWriter.dataLine("Failed to fetch certified service with UUID ", uuid);
         }
         return status;
     }
 
-    private JanusGraphOperationStatus generateArtifact(Component component, ArtifactTypeEnum artifactType, Supplier<byte[]> supplier){
+    private JanusGraphOperationStatus generateArtifact(Component component, ArtifactTypeEnum artifactType, Supplier<byte[]> supplier) {
         JanusGraphOperationStatus status = JanusGraphOperationStatus.GENERAL_ERROR;
         ArtifactDefinition csarArtifact;
-        Optional<ArtifactDefinition> op = component.getToscaArtifacts().values().stream().filter(p -> p.getArtifactType().equals(artifactType.getType())).findAny();
+        Optional<ArtifactDefinition> op = component.getToscaArtifacts().values().stream()
+            .filter(p -> p.getArtifactType().equals(artifactType.getType())).findAny();
         if (op.isPresent()) {
             csarArtifact = op.get();
-              
+
             status = savePayload(component, csarArtifact, supplier);
         }
         return status;
     }
-    
+
     private byte[] generateCsarPayload(org.openecomp.sdc.be.model.Component component) {
-        return csarUtils.createCsar(component, true, true).either( l -> l, r -> null);
-    }
-    private byte[] generateToscaPayload(Component component){
-       return toscaExportHandler.exportComponent(component).either(ToscaRepresentation::getMainYaml, r -> null);
+        return csarUtils.createCsar(component, true, true).either(l -> l, r -> null);
     }
 
-    private JanusGraphOperationStatus savePayload(org.openecomp.sdc.be.model.Component component, ArtifactDefinition csarArtifact, Supplier<byte[]> supplier) {
+    private byte[] generateToscaPayload(Component component) {
+        return toscaExportHandler.exportComponent(component).either(ToscaRepresentation::getMainYaml, r -> null);
+    }
+
+    private JanusGraphOperationStatus savePayload(org.openecomp.sdc.be.model.Component component, ArtifactDefinition csarArtifact,
+                                                  Supplier<byte[]> supplier) {
         byte[] payload = supplier.get();
 
-        if ( payload == null ) {
+        if (payload == null) {
             ConsoleWriter.dataLine("create artifact failed ", csarArtifact.getArtifactLabel());
             return JanusGraphOperationStatus.GENERAL_ERROR;
         }
@@ -170,10 +170,9 @@
         String uniqueId = UniqueIdBuilder.buildPropertyUniqueId(component.getUniqueId(), csarArtifact.getArtifactLabel());
         csarArtifact.setUniqueId(uniqueId);
         csarArtifact.setEsId(csarArtifact.getUniqueId());
-        
+
         ConsoleWriter.dataLine("create artifact unique id ", uniqueId);
-        
-        
+
         csarArtifact.setArtifactChecksum(GeneralUtility.calculateMD5Base64EncodedByByteArray(decodedPayload));
         DAOArtifactData artifactData = new DAOArtifactData(csarArtifact.getEsId(), decodedPayload);
         artifactCassandraDao.saveArtifact(artifactData);
diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/validator/utils/ValidationTaskResult.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/validator/utils/ValidationTaskResult.java
deleted file mode 100644
index 2dcc0ae..0000000
--- a/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/validator/utils/ValidationTaskResult.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *      http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-package org.openecomp.sdc.asdctool.impl.validator.utils;
-
-import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
-
-/**
- * Created by chaya on 7/5/2017.
- */
-public class ValidationTaskResult {
-    public ValidationTaskResult(GraphVertex vertex, String name, String resultMessage, boolean isSuccessful) {
-        this.vertexScanned = vertex;
-        this.name = name;
-        this.resultMessage = resultMessage;
-        this.isSuccessful = isSuccessful;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getResultMessage() {
-        return resultMessage;
-    }
-
-    public void setResultMessage(String resultMessage) {
-        this.resultMessage = resultMessage;
-    }
-
-    public boolean isSuccessful() {
-        return isSuccessful;
-    }
-
-    public void setSuccessful(boolean successful) {
-        isSuccessful = successful;
-    }
-
-    private String name;
-    private String resultMessage;
-    private boolean isSuccessful;
-    private GraphVertex vertexScanned;
-}
diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/main/DeleteComponentTool.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/main/DeleteComponentTool.java
index 309d23c..77b21fd 100644
--- a/asdctool/src/main/java/org/openecomp/sdc/asdctool/main/DeleteComponentTool.java
+++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/main/DeleteComponentTool.java
@@ -7,9 +7,9 @@
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *      http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -20,16 +20,14 @@
 
 package org.openecomp.sdc.asdctool.main;
 
+import java.util.Scanner;
 import org.openecomp.sdc.asdctool.configuration.ConfigurationUploader;
 import org.openecomp.sdc.asdctool.configuration.InternalToolConfiguration;
 import org.openecomp.sdc.asdctool.impl.internal.tool.DeleteComponentHandler;
 import org.openecomp.sdc.asdctool.utils.ConsoleWriter;
 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 
-import java.util.Scanner;
-
-public class DeleteComponentTool extends SdcInternalTool{
-    private static final String PSW = "ItIsTimeToDelete";
+public class DeleteComponentTool extends SdcInternalTool {
 
     public static void main(String[] args) {
         if (args == null || args.length < 2) {
@@ -37,8 +35,7 @@
             System.exit(1);
         }
         String appConfigDir = args[0];
-        String password = args[1];
-        
+
         disableConsole();
         ConsoleWriter.dataLine("STARTED... ");
 
@@ -46,7 +43,6 @@
         AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(InternalToolConfiguration.class);
         DeleteComponentHandler deleteComponentHandler = context.getBean(DeleteComponentHandler.class);
 
-
         String input = "";
         Scanner scanner = new Scanner(System.in);
         do {
@@ -54,9 +50,9 @@
             input = scanner.nextLine();
             if (!input.equals("exit")) {
                 if (!input.isEmpty()) {
-                    ConsoleWriter.dataLine("Your id is " ,input);
+                    ConsoleWriter.dataLine("Your id is ", input);
                     deleteComponentHandler.deleteComponent(input, scanner);
-                }else{
+                } else {
                     ConsoleWriter.dataLine("Your id is empty. Try again.");
                 }
             }
diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/main/ValidationTool.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/main/ValidationTool.java
index e5cd6f8..e68c9dd 100644
--- a/asdctool/src/main/java/org/openecomp/sdc/asdctool/main/ValidationTool.java
+++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/main/ValidationTool.java
@@ -7,9 +7,9 @@
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *      http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -32,7 +32,6 @@
 import org.openecomp.sdc.asdctool.impl.validator.report.ReportFile.TXTFile;
 import org.openecomp.sdc.asdctool.impl.validator.report.ReportFileWriter;
 import org.openecomp.sdc.be.config.ConfigurationManager;
-import org.openecomp.sdc.common.api.ConfigurationSource;
 import org.openecomp.sdc.common.impl.ExternalConfiguration;
 import org.openecomp.sdc.common.impl.FSConfigurationSource;
 import org.openecomp.sdc.common.log.wrappers.Logger;
@@ -76,8 +75,7 @@
     }
 
     private static AnnotationConfigApplicationContext initContext(String appConfigDir) {
-        ConfigurationSource configurationSource = new FSConfigurationSource(ExternalConfiguration.getChangeListener(), appConfigDir);
-        ConfigurationManager configurationManager = new ConfigurationManager(configurationSource);
+        new ConfigurationManager(new FSConfigurationSource(ExternalConfiguration.getChangeListener(), appConfigDir));
         return new AnnotationConfigApplicationContext(ValidationToolConfiguration.class);
     }
 }
diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/tasks/InstanceMigrationBase.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/tasks/InstanceMigrationBase.java
deleted file mode 100644
index 5876898..0000000
--- a/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/tasks/InstanceMigrationBase.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-package org.openecomp.sdc.asdctool.migration.tasks;
-
-import fj.data.Either;
-import org.apache.tinkerpop.gremlin.structure.Direction;
-import org.apache.tinkerpop.gremlin.structure.Edge;
-import org.janusgraph.core.JanusGraphVertex;
-import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
-import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
-import org.openecomp.sdc.be.dao.jsongraph.JanusGraphDao;
-import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum;
-import org.openecomp.sdc.be.dao.jsongraph.types.EdgePropertyEnum;
-import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
-import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum;
-import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
-import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
-import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
-import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.EnumMap;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-public abstract class InstanceMigrationBase {
-
-    private static final Logger log = LoggerFactory.getLogger(InstanceMigrationBase.class);
-    protected JanusGraphDao janusGraphDao;
-
-    public InstanceMigrationBase(JanusGraphDao janusGraphDao) {
-        this.janusGraphDao = janusGraphDao;
-    }
-
-    protected StorageOperationStatus upgradeTopologyTemplates() {
-        Map<GraphPropertyEnum, Object> hasNotProps = new EnumMap<>(GraphPropertyEnum.class);
-        hasNotProps.put(GraphPropertyEnum.IS_DELETED, true);
-        hasNotProps.put(GraphPropertyEnum.RESOURCE_TYPE, ResourceTypeEnum.CVFC);
-
-        return janusGraphDao.getByCriteria(VertexTypeEnum.TOPOLOGY_TEMPLATE, null, hasNotProps, JsonParseFlagEnum.ParseAll)
-                .either(this::proceed, this::handleError);
-    }
-
-    protected abstract StorageOperationStatus handleOneContainer(GraphVertex containerV);
-
-    protected StorageOperationStatus proceed(List<GraphVertex> containersV) {
-        int failureCounter = 0;
-        log.info("found {} vertices to migrate ", containersV.size());
-        for (GraphVertex container : containersV) {
-            StorageOperationStatus storageOperationStatus = handleOneContainer(container);
-            if (storageOperationStatus != StorageOperationStatus.OK) {
-                failureCounter++;
-            }
-        }
-
-        if (failureCounter > 0) {
-            log.info("Failed to update {} vertices", failureCounter);
-        } else {
-            log.info("All vertices were successfully updated");
-        }
-
-        return StorageOperationStatus.OK;
-    }
-
-    protected GraphVertex getVertexById(String vertexId) {
-        Either<GraphVertex, JanusGraphOperationStatus> vertexById = janusGraphDao.getVertexById(vertexId);
-        if (vertexById.isRight()) {
-            log.info("Exception occurred while query vertexId: {} exception: {} " + vertexId + vertexById.right().value());
-            return null;
-        }
-        else return vertexById.left().value();
-    }
-
-    protected StorageOperationStatus updateVertexAndCommit(GraphVertex graphVertex) {
-        StorageOperationStatus status;
-        if ((status = janusGraphDao.updateVertex(graphVertex)
-                .either(v -> StorageOperationStatus.OK, this::handleError)) != StorageOperationStatus.OK) {
-            return status;
-        }
-        return DaoStatusConverter.convertJanusGraphStatusToStorageStatus(janusGraphDao.commit());
-    }
-
-    protected StorageOperationStatus handleError(JanusGraphOperationStatus err) {
-        return DaoStatusConverter.convertJanusGraphStatusToStorageStatus(JanusGraphOperationStatus.NOT_FOUND == err ? JanusGraphOperationStatus.OK : err);
-    }
-
-    protected void removeEdges(Iterator<Edge> edges) {
-
-        while (edges.hasNext()) {
-            Edge edge = edges.next();
-            edge.remove();
-        }
-    }
-
-    protected void removeEdgesInState(Iterator<Edge> edges, String state) {
-
-        while (edges.hasNext()) {
-            Edge edge = edges.next();
-            String edgeState = (String) janusGraphDao.getProperty(edge, EdgePropertyEnum.STATE);
-            if (edgeState.equals(state)) {
-                edge.remove();
-            }
-        }
-    }
-
-
-    protected void updateEdgeProperty(EdgePropertyEnum property, String value, Iterator<Edge> edges) throws IOException {
-        while (edges.hasNext()) {
-            Edge edge = edges.next();
-            Map<EdgePropertyEnum, Object> prop = new HashMap<>();
-            prop.put(property, value);
-            janusGraphDao.setEdgeProperties(edge, prop);
-        }
-
-    }
-
-
-    // check if user has both edges state and last_state
-    protected boolean sameUser(List<JanusGraphVertex> stateList, List<JanusGraphVertex> lastStateList) {
-
-        for (JanusGraphVertex lsVertex : lastStateList) {
-            String idLs = (String) janusGraphDao.getProperty(lsVertex, GraphPropertyEnum.USERID.getProperty());
-            String idSt = (String) janusGraphDao.getProperty(stateList.get(0), GraphPropertyEnum.USERID.getProperty());
-            if (idLs.equals(idSt)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    protected Iterator<Edge> getVertexEdge(GraphVertex containerV, Direction direction, EdgeLabelEnum edgeLabel) {
-        return containerV.getVertex().edges(direction, edgeLabel.name());
-    }
-
-    public enum EdgeSide {
-        IN, OUT;
-    }
-}
-
diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/tasks/handlers/OutputHandler.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/tasks/handlers/OutputHandler.java
index b6dc27f..f7474ee 100644
--- a/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/tasks/handlers/OutputHandler.java
+++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/tasks/handlers/OutputHandler.java
@@ -7,9 +7,9 @@
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *      http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -22,8 +22,10 @@
 
 public interface OutputHandler {
 
-	public void initiate(String name, Object... title);
-	public void addRecord(Object... record);
-	public boolean writeOutputAndCloseFile();
-	
+    void initiate(String name, Object... title);
+
+    void addRecord(Object... record);
+
+    boolean writeOutputAndCloseFile();
+
 }
diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/tasks/mig1710/UpgradeMigration1710.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/tasks/mig1710/UpgradeMigration1710.java
deleted file mode 100644
index 8eda864..0000000
--- a/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/tasks/mig1710/UpgradeMigration1710.java
+++ /dev/null
@@ -1,1190 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *      http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-package org.openecomp.sdc.asdctool.migration.tasks.mig1710;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.Lists;
-import fj.data.Either;
-import org.apache.commons.collections.CollectionUtils;
-import org.apache.commons.collections.MapUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.openecomp.sdc.asdctool.enums.LifecycleStateEnum;
-import org.openecomp.sdc.asdctool.migration.core.task.MigrationResult;
-import org.openecomp.sdc.asdctool.migration.core.task.PostMigration;
-import org.openecomp.sdc.asdctool.migration.tasks.handlers.XlsOutputHandler;
-import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
-import org.openecomp.sdc.be.components.impl.ResourceBusinessLogic;
-import org.openecomp.sdc.be.components.impl.ServiceBusinessLogic;
-import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
-import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException;
-import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
-import org.openecomp.sdc.be.components.lifecycle.LifecycleBusinessLogic;
-import org.openecomp.sdc.be.components.lifecycle.LifecycleChangeInfoWithAction;
-import org.openecomp.sdc.be.components.lifecycle.LifecycleChangeInfoWithAction.LifecycleChanceActionEnum;
-import org.openecomp.sdc.be.components.scheduledtasks.ComponentsCleanBusinessLogic;
-import org.openecomp.sdc.be.config.Configuration;
-import org.openecomp.sdc.be.config.ConfigurationManager;
-import org.openecomp.sdc.be.dao.api.ActionStatus;
-import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
-import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
-import org.openecomp.sdc.be.dao.jsongraph.JanusGraphDao;
-import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum;
-import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
-import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum;
-import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
-import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
-import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
-import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
-import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
-import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
-import org.openecomp.sdc.be.impl.ComponentsUtils;
-import org.openecomp.sdc.be.model.ComponentInstance;
-import org.openecomp.sdc.be.model.ComponentInstanceProperty;
-import org.openecomp.sdc.be.model.ComponentParametersView;
-import org.openecomp.sdc.be.model.LifeCycleTransitionEnum;
-import org.openecomp.sdc.be.model.Resource;
-import org.openecomp.sdc.be.model.User;
-import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
-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.CsarOperation;
-import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
-import org.openecomp.sdc.be.model.operations.impl.UserAdminOperation;
-import org.openecomp.sdc.common.log.wrappers.Logger;
-import org.openecomp.sdc.exception.ResponseFormat;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-import javax.annotation.PostConstruct;
-import java.util.ArrayList;
-import java.util.EnumMap;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.function.Predicate;
-import java.util.stream.Collectors;
-
-@Component
-public class UpgradeMigration1710 implements PostMigration {
-
-    private static final String SERVICE_UUID_RPOPERTY = "providing_service_uuid";
-
-    private static final String SERVICE_INVARIANT_UUID_RPOPERTY = "providing_service_invariant_uuid";
-
-    private static final String UNKNOWN = "UNKNOWN";
-
-    private static final String CHECKOUT_MESSAGE = "checkout upon upgrade migration";
-
-    private static final String FAILED_TO_CHANGE_STATE_OF_COMPONENT = "Failed to change state of component with name {}, invariantUUID {}, version {} to {}. ";
-
-    private static final String FAILED_TO_UPGRADE_COMPONENT = "Failed to upgrade {} with name {}, invariantUUID {}, version {}. Operation {}. The reason for failure: {}. ";
-
-    private static final String UPGRADE_COMPONENT_SUCCEEDED = "Upgrade of {} with name {}, invariantUUID {}, version {} finished successfully. ";
-
-    private static final String UPGRADE_VFS_FAILED = "Upgrade VFs upon upgrade migration 1710 process failed. ";
-
-    private static final Logger log = Logger.getLogger(UpgradeMigration1710.class);
-
-    private static final String ALLOTTED_RESOURCE_NAME = "Allotted Resource";
-
-    //as per US 397775, only node type upgrade should be enabled,
-    // to support resource and service upgrade, this flag should be reverted
-    private boolean isNodeTypesSupportOnly = true;
-
-    @Autowired
-    private JanusGraphDao janusGraphDao;
-
-    @Autowired
-    private ToscaOperationFacade toscaOperationFacade;
-
-    @Autowired
-    private LifecycleBusinessLogic lifecycleBusinessLogic;
-
-    @Autowired
-    private UserAdminOperation userAdminOperation;
-
-    @Autowired
-    private ResourceBusinessLogic resourceBusinessLogic;
-
-    @Autowired
-    private ServiceBusinessLogic serviceBusinessLogic;
-
-    @Autowired
-    private CsarOperation csarOperation;
-
-    @Autowired
-    private ComponentInstanceBusinessLogic componentInstanceBusinessLogic;
-
-    @Autowired
-    private ComponentsUtils componentsUtils;
-
-    @Autowired
-    private ComponentsCleanBusinessLogic componentsCleanBusinessLogic;
-
-    private XlsOutputHandler outputHandler = new XlsOutputHandler(null, "UpgradeMigration1710report","COMPONENT TYPE", "COMPONENT NAME", "COMPONENT UUID", "COMPONENT UNIQUE_ID", "UPGRADE STATUS", "DESCRIPTION");
-
-    private User user = null;
-
-    private final LifecycleChangeInfoWithAction changeInfo = new LifecycleChangeInfoWithAction(CHECKOUT_MESSAGE, LifecycleChanceActionEnum.UPGRADE_MIGRATION);
-
-    private final Map<String, GraphVertex> latestGenericTypes = new HashMap<>();
-
-    private final Map<String, String> latestOriginResourceVersions = new HashMap<>();
-
-    private final Map<String, org.openecomp.sdc.be.model.Component> upgradedNodeTypesMap = new HashMap<>();
-
-    private List<String> nodeTypes;
-
-    private List<String> proxyServiceContainers = new ArrayList<>();
-
-    private List<String> vfAllottedResources = new ArrayList<>();
-
-    private List<String> allottedVfContainers = new ArrayList<>();
-
-    private boolean isVfcUpgradeRequired = false;
-
-    private boolean skipIfUpgradeVfFailed = true;
-
-    private boolean isAllottedAndProxySupported = true;
-
-    private String userId;
-
-    private boolean isCleanupLocked = false;
-
-    private int markedAsDeletedResourcesCnt = 0;
-
-    private int markedAsDeletedServicesCnt = 0;
-
-    //how many components can be deleted once
-    private int maxDeleteComponents = 10;
-
-    private boolean enableAutoHealing = true;
-
-    //map for tracing checked out resources that keep in place after upgrade failure
-    private HashMap<String, String> certifiedToNextCheckedOutUniqueId = new HashMap<>();
-
-    private int deleteLockTimeoutInSeconds = 60;
-
-    private boolean isLockSucceeded = false;
-
-    /***********************************************/
-
-    @VisibleForTesting
-    void setNodeTypesSupportOnly(boolean nodeTypesSupportOnly) {
-        isNodeTypesSupportOnly = nodeTypesSupportOnly;
-    }
-
-    @VisibleForTesting
-    void setUser(User user) {
-        this.user = user;
-    }
-
-    @VisibleForTesting
-    void setMarkedAsDeletedResourcesCnt(int markedAsDeletedResourcesCnt) {
-        this.markedAsDeletedResourcesCnt = markedAsDeletedResourcesCnt;
-    }
-
-    @VisibleForTesting
-    void setMarkedAsDeletedServicesCnt(int markedAsDeletedServicesCnt) {
-        this.markedAsDeletedServicesCnt = markedAsDeletedServicesCnt;
-    }
-
-    @PostConstruct
-    void init() {
-        Configuration config = ConfigurationManager.getConfigurationManager().getConfiguration();
-        isVfcUpgradeRequired = !config.getSkipUpgradeVSPsFlag();
-        skipIfUpgradeVfFailed = config.getSkipUpgradeFailedVfs();
-        isAllottedAndProxySupported = config.getSupportAllottedResourcesAndProxyFlag();
-        deleteLockTimeoutInSeconds = config.getDeleteLockTimeoutInSeconds();
-        maxDeleteComponents = config.getMaxDeleteComponents();
-
-        String toscaConformanceLevel = config.getToscaConformanceLevel();
-        Map<String, List<String>> resourcesForUpgrade = config.getResourcesForUpgrade();
-        nodeTypes = resourcesForUpgrade.get(toscaConformanceLevel);
-        enableAutoHealing = config.isEnableAutoHealing();
-        userId = config.getAutoHealingOwner();
-        isNodeTypesSupportOnly = true;
-    }
-
-    @Override
-    public String description() {
-        return "Upgrade migration 1710 - post migration task, which is dedicated to upgrade all latest certified (and not checked out) Node types, VFs and Services. ";
-    }
-
-    enum UpgradeStatus {
-        UPGRADED,
-        UPGRADED_AS_INSTANCE,
-        NOT_UPGRADED
-    }
-
-    @Override
-    public MigrationResult migrate() {
-        MigrationResult migrationResult = new MigrationResult();
-        //stop the upgrade if this ask is disabled
-        if (!enableAutoHealing) {
-            log.warn("Upgrade migration 1710 task is disabled");
-            migrationResult.setMigrationStatus(MigrationResult.MigrationStatus.COMPLETED);
-            return migrationResult ;
-        }
-        log.info("Starting upgrade migration 1710 process. ");
-        boolean result = true;
-
-        try {
-            //lock cleanup node to avoid BE to delete marked components
-            //while the auto-healing process is running
-            isLockSucceeded = isNodeTypesSupportOnly ? true : isLockDeleteOperationSucceeded();
-
-            if (!isLockSucceeded) {
-                result = false;
-                log.error("Cleanup node can't be locked. Upgrade migration failed");
-            }
-            else {
-                Either<User, ActionStatus> userReq = userAdminOperation.getUserData(userId, false);
-                if (userReq.isRight()) {
-                    result = false;
-                    log.error("Upgrade migration failed. User {} resolve failed: {} ", userId, userReq.right().value());
-                } else {
-                    user = userReq.left().value();
-                    log.info("User {} will perform upgrade operation", user.getUserId());
-                }
-            }
-            if (result) {
-                result = upgradeNodeTypes();
-            }
-            if (!isNodeTypesSupportOnly && result) {
-                result = upgradeTopologyTemplates();
-            }
-        }
-        catch (Exception e) {
-            result = false;
-            log.error("Error occurred during the migration: ", e);
-        } finally {
-            MigrationResult.MigrationStatus status = result ?
-                    MigrationResult.MigrationStatus.COMPLETED : MigrationResult.MigrationStatus.FAILED;
-            cleanup(status);
-            migrationResult.setMigrationStatus(status);
-        }
-        return migrationResult;
-    }
-
-    private boolean upgradeTopologyTemplates() {
-        if (upgradeVFs()) {
-            upgradeServices();
-            upgradeProxyServiceContainers();
-            upgradeAllottedVFs();
-            upgradeAllottedVfContainers();
-            return true;
-        }
-        return false;
-    }
-
-    private void cleanup(MigrationResult.MigrationStatus status) {
-        if (status == MigrationResult.MigrationStatus.COMPLETED ) {
-            log.info("Upgrade migration 1710 has been successfully finished. ");
-            janusGraphDao.commit();
-        } else {
-            log.info("Upgrade migration 1710 was failed. ");
-            janusGraphDao.rollback();
-        }
-        outputHandler.writeOutputAndCloseFile();
-        if (!isNodeTypesSupportOnly && isLockSucceeded) {
-            //delete rest of components if their upgrade failed
-            markedAsDeletedResourcesCnt = maxDeleteComponents;
-            deleteResourcesIfLimitIsReached();
-            markedAsDeletedServicesCnt = maxDeleteComponents;
-            deleteServicesIfLimitIsReached();
-            unlockDeleteOperation();
-        }
-    }
-
-    void upgradeServices(List<String> uniqueIDs, Predicate<org.openecomp.sdc.be.model.Component> shouldUpgrade, final String containerName) {
-        log.info("Starting upgrade {} upon upgrade migration 1710 process. ", containerName);
-        for (String currUid : uniqueIDs) {
-            upgradeServiceAndCommitIfNeeded(currUid, shouldUpgrade);
-        }
-        log.info("Upgrade {} upon upgrade migration 1710 process is finished. ", containerName);
-    }
-
-    private void upgradeServiceAndCommitIfNeeded(String currUid, Predicate<org.openecomp.sdc.be.model.Component> shouldUpgrade) {
-        boolean result = true;
-        try {
-            result = handleService(currUid, shouldUpgrade);
-        } catch (Exception e) {
-            result = false;
-            log.error("Failed to upgrade service with uniqueId {} due to a reason {}. ", currUid, e.getMessage());
-            log.debug("Failed to upgrade service with uniqueId {}", currUid, e);
-        }
-        finally {
-            if (result) {
-                log.info("Service upgrade finished successfully: uniqueId {} ", currUid);
-                janusGraphDao.commit();
-            }
-            else {
-                log.error("Failed to upgrade service with uniqueId {} ", currUid);
-                janusGraphDao.rollback();
-            }
-            markCheckedOutServiceAsDeletedIfUpgradeFailed(currUid, result);
-        }
-    }
-
-    private void upgradeAllottedVfContainers() {
-        upgradeServices(allottedVfContainers, component -> true, "proxy " + allottedVfContainers.size() + " service containers");
-    }
-
-    private void upgradeServices() {
-        Either<List<String>, JanusGraphOperationStatus> getServicesRes = getAllLatestCertifiedComponentUids(VertexTypeEnum.TOPOLOGY_TEMPLATE, ComponentTypeEnum.SERVICE);
-        if (getServicesRes.isRight()) {
-            log.error("Failed to retrieve the latest certified service versions");
-            return;
-        }
-        upgradeServices(getServicesRes.left().value(), this::shouldUpgrade, "services");
-    }
-
-    private void upgradeProxyServiceContainers() {
-        upgradeServices(proxyServiceContainers, component -> true, "proxy service containers");
-    }
-
-    private boolean handleService(String uniqueId, Predicate<org.openecomp.sdc.be.model.Component> shouldUpgrade) {
-        log.info("Starting upgrade Service with uniqueId {} upon upgrade migration 1710 process. ", uniqueId);
-        Either<org.openecomp.sdc.be.model.Component, StorageOperationStatus> getServiceRes = toscaOperationFacade.getToscaElement(uniqueId);
-        if(getServiceRes.isRight()){
-            log.error("Failed to upgrade service with uniqueId {} due to {}. ", uniqueId, getServiceRes.right().value());
-            outputHandler.addRecord(ComponentTypeEnum.SERVICE.name(), UNKNOWN, UNKNOWN, uniqueId, MigrationResult.MigrationStatus.FAILED.name(), getServiceRes.right().value());
-            return false;
-        }
-        String derivedFromGenericType =  getServiceRes.left().value().getDerivedFromGenericType();
-        log.debug("derivedFromGenericType: {}", derivedFromGenericType );
-        if (derivedFromGenericType == null) {
-            //malformed field value, upgrade required
-            return upgradeService(getServiceRes.left().value());
-        }
-        if(!latestGenericTypes.containsKey(derivedFromGenericType)){
-            Either<List<GraphVertex>, JanusGraphOperationStatus> getDerivedRes = findDerivedResources(derivedFromGenericType);
-            if(getDerivedRes.isRight()){
-                log.error(FAILED_TO_UPGRADE_COMPONENT, getServiceRes.left().value().getComponentType().getValue(), getServiceRes.left().value().getName(), getServiceRes.left().value().getInvariantUUID(), getServiceRes.left().value().getVersion(), "findDerivedResources", getDerivedRes.right().value());
-                outputHandler.addRecord( getServiceRes.left().value().getComponentType().name(),getServiceRes.left().value().getName(), getServiceRes.left().value().getInvariantUUID(), getServiceRes.left().value().getUniqueId(), MigrationResult.MigrationStatus.FAILED.name(), getDerivedRes.right().value());
-                return false;
-            }
-            latestGenericTypes.put(derivedFromGenericType, getDerivedRes.left().value().get(0));
-        }
-        if(latestVersionExists(latestGenericTypes.get(derivedFromGenericType), getServiceRes.left().value().getDerivedFromGenericVersion())){
-            return upgradeService(getServiceRes.left().value());
-        }
-        if(!collectLatestOriginResourceVersions(getServiceRes.left().value())){
-            return false;
-        }
-        if(shouldUpgrade.test(getServiceRes.left().value())){
-            return upgradeService(getServiceRes.left().value());
-        }
-        outputHandler.addRecord(getServiceRes.left().value().getComponentType().name(), getServiceRes.left().value().getName(), getServiceRes.left().value().getInvariantUUID(), getServiceRes.left().value().getUniqueId(), MigrationResult.MigrationStatus.COMPLETED.name(), UpgradeStatus.NOT_UPGRADED);
-        return true;
-    }
-
-    private boolean collectLatestOriginResourceVersions(org.openecomp.sdc.be.model.Component component) {
-        if (CollectionUtils.isNotEmpty(component.getComponentInstances())) {
-            for (ComponentInstance instance : component.getComponentInstances()) {
-                if (instance.getOriginType() != OriginTypeEnum.ServiceProxy && !latestOriginResourceVersions.containsKey(instance.getToscaComponentName()) && !addComponent(component, instance)) {
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
-    private boolean addComponent(org.openecomp.sdc.be.model.Component component, ComponentInstance instance) {
-        VertexTypeEnum vertexType = ModelConverter.getVertexType(instance.getOriginType().name());
-        Either<Resource, StorageOperationStatus> getOriginRes = toscaOperationFacade.getLatestCertifiedByToscaResourceName(instance.getToscaComponentName(), vertexType, JsonParseFlagEnum.ParseMetadata);
-        if (getOriginRes.isRight()) {
-            log.error(FAILED_TO_UPGRADE_COMPONENT, component.getComponentType().getValue(), component.getName(), component.getInvariantUUID(), component.getVersion(), "toscaOperationFacade.getLatestCertifiedByToscaResourceName", getOriginRes.right().value());
-            outputHandler.addRecord(component.getComponentType().name(), component.getName(), component.getInvariantUUID(), component.getUniqueId(), MigrationResult.MigrationStatus.FAILED.name(), getOriginRes.right().value());
-            return false;
-        }
-        latestOriginResourceVersions.put(instance.getToscaComponentName(), getOriginRes.left().value().getVersion());
-        return true;
-    }
-
-    private boolean shouldUpgrade(org.openecomp.sdc.be.model.Component component) {
-        if(CollectionUtils.isNotEmpty(component.getComponentInstances())) {
-            if (containsProxyOrAllottedVF(component)) {
-                return false;
-            }
-            for(ComponentInstance instance : component.getComponentInstances()){
-                if(isGreater(latestOriginResourceVersions.get(instance.getToscaComponentName()), instance.getComponentVersion())){
-                    log.info("The service with name {}, invariantUUID {}, version {}, contains instance {} from outdated version of origin {} {} , than the service should be upgraded. ", component.getName(), component.getInvariantUUID(), component.getVersion(), instance.getName(), instance.getComponentName(), instance.getComponentVersion());
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    private boolean containsProxyOrAllottedVF(org.openecomp.sdc.be.model.Component component) {
-        return !component.getComponentInstances()
-                .stream()
-                .filter(i->isProxyOrAllottedVF(i, component.getUniqueId()))
-                .collect(Collectors.toList()).isEmpty();
-    }
-
-    private boolean isProxyOrAllottedVF(ComponentInstance instance, String uniqueId) {
-        if (instance.getOriginType() == OriginTypeEnum.ServiceProxy) {
-            keepProxyServiceContainerIfSupported(uniqueId);
-            return true;
-        }
-        if (isAllottedResource(instance.getActualComponentUid())) {
-            keepAllottedVfContainerIfSupported(uniqueId);
-            return true;
-        }
-        return false;
-    }
-
-    private void keepAllottedVfContainerIfSupported(final String uniqueId) {
-        if (isAllottedAndProxySupported && !allottedVfContainers.contains(uniqueId)) {
-            log.info("Add a service with uniqueId {} to allotted VF containers container list", uniqueId);
-            allottedVfContainers.add(uniqueId);
-        }
-    }
-
-    private void keepProxyServiceContainerIfSupported(final String uniqueId) {
-        if (isAllottedAndProxySupported && !proxyServiceContainers.contains(uniqueId)) {
-            log.info("Add a service with uniqueId {} to proxy service container list", uniqueId);
-            proxyServiceContainers.add(uniqueId);
-        }
-    }
-
-    private boolean upgradeService(org.openecomp.sdc.be.model.Component service) {
-        String serviceName = service.getName();
-        String serviceUuid = service.getUUID();
-        log.info("Starting upgrade Service with name {}, invariantUUID {}, version {} upon upgrade migration 1710 process. ", serviceName, service.getInvariantUUID(), service.getVersion());
-        Either<? extends org.openecomp.sdc.be.model.Component, ResponseFormat> checkouRes = checkOutComponent(service);
-        if (checkouRes.isRight()) {
-            log.error(FAILED_TO_UPGRADE_COMPONENT, service.getComponentType().getValue(), serviceName, service.getInvariantUUID(), service.getVersion(), "lifecycleBusinessLogic.changeComponentState", checkouRes.right().value().getFormattedMessage());
-            outputHandler.addRecord(service.getComponentType().name(), serviceName, serviceUuid, service.getUniqueId(), MigrationResult.MigrationStatus.FAILED.name(), checkouRes.right().value().getFormattedMessage());
-            return false;
-        }
-        Either<org.openecomp.sdc.be.model.Component, ResponseFormat> updateCompositionRes = updateComposition(checkouRes.left().value());
-        if (updateCompositionRes.isRight()) {
-            log.error(FAILED_TO_UPGRADE_COMPONENT, service.getComponentType().getValue(), serviceName, service.getInvariantUUID(), service.getVersion(), "updateComposition", updateCompositionRes.right().value().getFormattedMessage());
-            outputHandler.addRecord(checkouRes.left().value().getComponentType().name(), checkouRes.left().value().getName(), checkouRes.left().value().getUUID(), checkouRes.left().value().getUniqueId(), MigrationResult.MigrationStatus.FAILED.name(), updateCompositionRes.right().value().getFormattedMessage());
-            return false;
-        }
-        Either<? extends org.openecomp.sdc.be.model.Component, ResponseFormat> certifyRes = performFullCertification(checkouRes.left().value());
-        if (certifyRes.isRight()) {
-            log.error(FAILED_TO_UPGRADE_COMPONENT, service.getComponentType().getValue(), serviceName, service.getInvariantUUID(), service.getVersion(), "performFullCertification", certifyRes.right().value().getFormattedMessage());
-            outputHandler.addRecord(checkouRes.left().value().getComponentType().name(), checkouRes.left().value().getName(), checkouRes.left().value().getInvariantUUID(), checkouRes.left().value().getUniqueId(), MigrationResult.MigrationStatus.FAILED.name(), certifyRes.right().value().getFormattedMessage());
-            return false;
-        }
-        outputHandler.addRecord(checkouRes.left().value().getComponentType().name(), checkouRes.left().value().getName(), serviceUuid, checkouRes.left().value().getUniqueId(), MigrationResult.MigrationStatus.COMPLETED.name(), UpgradeStatus.UPGRADED);
-        return true;
-    }
-
-    private Either<org.openecomp.sdc.be.model.Component, ResponseFormat> updateComposition(org.openecomp.sdc.be.model.Component component) {
-        if (component != null && component.getComponentInstances() != null) {
-            for (ComponentInstance instance : component.getComponentInstances()) {
-                try {
-                    upgradeInstance(component, instance);
-                }catch (ComponentException e){
-                    ResponseFormat responseFormat = e.getResponseFormat();
-                    log.error(FAILED_TO_UPGRADE_COMPONENT, component.getComponentType().getValue(), component.getName(),
-                            component.getInvariantUUID(), component.getVersion(), "upgradeInstance",
-                            responseFormat.getFormattedMessage());
-                    outputHandler.addRecord(component.getComponentType().name(), component.getName(), component.getUUID(),
-                            component.getUniqueId(), MigrationResult.MigrationStatus.FAILED.name(),
-                            responseFormat.getFormattedMessage());
-                    return Either.right(responseFormat);
-                }
-            }
-        }
-        return Either.left(component);
-    }
-
-    private ComponentInstance upgradeInstance(org.openecomp.sdc.be.model.Component component, ComponentInstance instance) {
-        log.info("Starting upgrade {} instance {} upon upgrade migration 1710 process. ", component.getComponentType().getValue(), instance.getName());
-        ComponentInstance newComponentInstance = new ComponentInstance(instance);
-        if (instance.getOriginType() == OriginTypeEnum.ServiceProxy) {
-            return upgradeServiceProxyInstance(component, instance, newComponentInstance);
-        }
-        return upgradeResourceInstance(component, instance, newComponentInstance);
-    }
-
-    private ComponentInstance upgradeResourceInstance(org.openecomp.sdc.be.model.Component component, ComponentInstance instance, ComponentInstance newComponentInstance) {
-
-        log.info("Starting upgrade {} instance {} upon upgrade migration 1710 process. ", component.getComponentType().getValue(), instance.getName());
-        ComponentInstance upgradeInstanceRes = null;
-        VertexTypeEnum vertexType = ModelConverter.getVertexType(instance.getOriginType().name());
-        Either<Resource, StorageOperationStatus> getOriginRes = toscaOperationFacade.getLatestCertifiedByToscaResourceName(instance.getToscaComponentName(), vertexType, JsonParseFlagEnum.ParseMetadata);
-        if(getOriginRes.isRight()){
-            log.info("Upgrade of {} instance {} upon upgrade migration 1710 process failed due to a reason {}. ",
-                    component.getComponentType().getValue(), instance.getName(), getOriginRes.right().value());
-            throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(getOriginRes.right().value(), instance.getOriginType().getComponentType()));
-        }
-        copyComponentNameAndVersionToNewInstance(newComponentInstance, getOriginRes.left().value());
-
-        if(isGreater(getOriginRes.left().value().getVersion(), instance.getComponentVersion())){
-            upgradeInstanceRes = changeAssetVersion(component, instance, newComponentInstance);
-        }
-        if(isAllottedResource(instance.getComponentUid()) && MapUtils.isNotEmpty(component.getComponentInstancesProperties())){
-            ComponentInstance instanceToUpdate = upgradeInstanceRes == null ? instance : upgradeInstanceRes;
-            upgradeInstanceRes = updateServiceUuidProperty(component, instanceToUpdate, component.getComponentInstancesProperties().get(instance.getUniqueId()));
-        }
-        //upgrade nodes contained by CVFC
-        if(upgradeInstanceRes == null && isVfcUpgradeRequired && newComponentInstance.getOriginType() == OriginTypeEnum.CVFC &&
-                !upgradeVf(getOriginRes.left().value().getUniqueId(), false, true)) {
-            throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR);
-        }
-        if(upgradeInstanceRes == null){
-            upgradeInstanceRes = instance;
-        }
-        log.info("Upgrade of {} instance {} upon upgrade migration 1710 process finished successfully. ",
-                component.getComponentType().getValue(), instance.getName());
-        return upgradeInstanceRes;
-    }
-
-    private void copyComponentNameAndVersionToNewInstance(ComponentInstance newComponentInstance, Resource originResource) {
-        newComponentInstance.setComponentName(originResource.getName());
-        newComponentInstance.setComponentUid(originResource.getUniqueId());
-        newComponentInstance.setComponentVersion(originResource.getVersion());
-        newComponentInstance.setToscaComponentName(originResource.getToscaResourceName());
-    }
-
-    private ComponentInstance updateServiceUuidProperty(org.openecomp.sdc.be.model.Component component, ComponentInstance instance, List<ComponentInstanceProperty> instanceProperties){
-        if(isAllottedResource(instance.getComponentUid()) && instanceProperties != null){
-            Optional<ComponentInstanceProperty> propertyUuid = instanceProperties.stream().filter(p->p.getName().equals(SERVICE_UUID_RPOPERTY)).findFirst();
-            Optional<ComponentInstanceProperty> propertyInvariantUuid = instanceProperties.stream().filter(p->p.getName().equals(SERVICE_INVARIANT_UUID_RPOPERTY)).findFirst();
-            if(propertyUuid.isPresent() && propertyInvariantUuid.isPresent()){
-                String serviceInvariantUUID = propertyInvariantUuid.get().getValue();
-                Either<List<GraphVertex>, JanusGraphOperationStatus> getLatestOriginServiceRes = getLatestCertifiedService(serviceInvariantUUID);
-                if (getLatestOriginServiceRes.isRight()) {
-                    return instance;
-                }
-                propertyUuid.get().setValue((String) getLatestOriginServiceRes.left().value().get(0).getJsonMetadataField(JsonPresentationFields.UUID));
-                componentInstanceBusinessLogic.createOrUpdatePropertiesValues(component.getComponentType(), component.getUniqueId(), instance.getUniqueId(), Lists.newArrayList(propertyUuid.get()), user.getUserId())
-                        .right()
-                        .forEach(e -> log.debug("Failed to update property {} of the instance {} of the component {}. ", SERVICE_UUID_RPOPERTY, instance.getUniqueId(), component.getName()));
-            }
-        }
-        return instance;
-    }
-
-    private boolean isAllottedResource(String uniqueId){
-        ComponentParametersView filters = new ComponentParametersView(true);
-        filters.setIgnoreCategories(false);
-        Either<org.openecomp.sdc.be.model.Component, StorageOperationStatus> getResourceRes = toscaOperationFacade.getToscaElement(uniqueId, filters);
-        if(getResourceRes.isRight()){
-            return false;
-        }
-        if(getResourceRes.left().value().getCategories() != null && getResourceRes.left().value().getCategories().get(0)!= null){
-            return ALLOTTED_RESOURCE_NAME.equals(getResourceRes.left().value().getCategories().get(0).getName());
-        }
-        return false;
-    }
-
-    private boolean isAllottedVf(org.openecomp.sdc.be.model.Component component){
-        if(component.getComponentType() != ComponentTypeEnum.RESOURCE || ((Resource)component).getResourceType() != ResourceTypeEnum.VF){
-            return false;
-        }
-        return isAllottedResource(component.getUniqueId());
-    }
-
-    private ComponentInstance upgradeServiceProxyInstance(org.openecomp.sdc.be.model.Component component, ComponentInstance instance, ComponentInstance newComponentInstance) {
-        Either<List<GraphVertex>, JanusGraphOperationStatus> getLatestOriginServiceRes = getLatestCertifiedService(instance.getSourceModelInvariant());
-        if (getLatestOriginServiceRes.isRight()) {
-            throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(getLatestOriginServiceRes.right().value()), instance.getOriginType().getComponentType()));
-        }
-        ModelConverter.getVertexType(instance.getOriginType().name());
-        Either<Resource, StorageOperationStatus> getOriginRes = toscaOperationFacade.getLatestByName(instance.getComponentName());
-        if(getOriginRes.isRight()){
-            log.info("Upgrade of {} instance {} upon upgrade migration 1710 process failed due to a reason {}. ",
-                    component.getComponentType().getValue(), instance.getName(), getOriginRes.right().value());
-            throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(getOriginRes.right().value(), instance.getOriginType().getComponentType()));
-        }
-        newComponentInstance.setComponentUid((String) getLatestOriginServiceRes.left().value().get(0).getJsonMetadataField(JsonPresentationFields.UNIQUE_ID));
-        return changeAssetVersion(component, instance, newComponentInstance);
-    }
-
-    private Either<List<GraphVertex>, JanusGraphOperationStatus> getLatestCertifiedService(String invariantUUID) {
-
-        Map<GraphPropertyEnum, Object> propertiesToMatch = new EnumMap<>(GraphPropertyEnum.class);
-        propertiesToMatch.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.SERVICE.name());
-        propertiesToMatch.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true);
-        propertiesToMatch.put(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name());
-        propertiesToMatch.put(GraphPropertyEnum.INVARIANT_UUID, invariantUUID);
-        Map<GraphPropertyEnum, Object> propertiesNotToMatch = new EnumMap<>(GraphPropertyEnum.class);
-        propertiesNotToMatch.put(GraphPropertyEnum.IS_DELETED, true);
-        return janusGraphDao
-            .getByCriteria(VertexTypeEnum.TOPOLOGY_TEMPLATE, propertiesToMatch, propertiesNotToMatch, JsonParseFlagEnum.ParseMetadata);
-    }
-
-    private ComponentInstance changeAssetVersion(org.openecomp.sdc.be.model.Component containerComponent, ComponentInstance instance, ComponentInstance newComponentInstance) {
-        return componentInstanceBusinessLogic.changeComponentInstanceVersion(ComponentTypeEnum.SERVICE_PARAM_NAME, containerComponent.getUniqueId(), instance.getUniqueId(), user.getUserId(), newComponentInstance);
-    }
-
-    private boolean upgradeNodeTypes() {
-        log.info("Starting upgrade node types upon upgrade migration 1710 process. ");
-        if (nodeTypes != null && !nodeTypes.isEmpty()) {
-            Either<List<String>, JanusGraphOperationStatus> getRes = getAllLatestCertifiedComponentUids(VertexTypeEnum.NODE_TYPE, ComponentTypeEnum.RESOURCE);
-            if (getRes.isRight()) {
-                return false;
-            }
-            for (String toscaResourceName : nodeTypes) {
-                if (!upgradeNodeType(toscaResourceName, getRes.left().value())) {
-                    return false;
-                }
-            }
-        }
-        else {
-            log.info("No node types for upgrade are configured");
-        }
-        return true;
-    }
-
-    private boolean upgradeNodeType(String toscaResourceName, List<String> allNodeTypes) {
-        Either<List<GraphVertex>, StorageOperationStatus> status = getLatestByName(GraphPropertyEnum.TOSCA_RESOURCE_NAME, toscaResourceName);
-        if (status.isRight()) {
-            log.error("Failed to find node type {} ", toscaResourceName);
-            return false;
-        }
-        List<GraphVertex> vList = status.left().value();
-        for (GraphVertex vertex : vList) {
-            StorageOperationStatus updateRes = upgradeNodeType(vertex, allNodeTypes);
-            if (updateRes != StorageOperationStatus.OK) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    private boolean upgradeVFs() {
-        log.info("Starting upgrade VFs upon upgrade migration 1710 process. ");
-        Either<List<String>, JanusGraphOperationStatus> getVfsRes = getAllLatestCertifiedComponentUids(VertexTypeEnum.TOPOLOGY_TEMPLATE, ComponentTypeEnum.RESOURCE);
-        if (getVfsRes.isRight()) {
-            log.info(UPGRADE_VFS_FAILED);
-            return false;
-        }
-        return upgradeVFs(getVfsRes.left().value(), false);
-    }
-
-    private boolean upgradeAllottedVFs() {
-        log.info("Starting upgrade {} allotted Vfs with upon upgrade migration 1710 process. ", vfAllottedResources.size());
-        return upgradeVFs(vfAllottedResources, true);
-    }
-
-    boolean upgradeVFs(List<String> resourceList, boolean isAllottedVfsUpgrade) {
-        for (String currUid : resourceList) {
-            boolean result = true;
-            try {
-                result = upgradeVf(currUid, isAllottedVfsUpgrade, false);
-                if (!result && !skipIfUpgradeVfFailed) {
-                    return false;
-                }
-            } catch (Exception e) {
-                log.error("The exception {} occurred upon upgrade VFs. ", e.getMessage());
-                log.debug("The exception occurred upon upgrade VFs:", e);
-                result = false;
-                if (!skipIfUpgradeVfFailed) {
-                    return false;
-                }
-            }
-            finally {
-                if (result) {
-                    log.info("Resource upgrade finished successfully: uniqueId {} ", currUid);
-                    janusGraphDao.commit();
-                }
-                else {
-                    log.error("Failed to upgrade resource with uniqueId {} ", currUid);
-                    janusGraphDao.rollback();
-                }
-                markCheckedOutResourceAsDeletedIfUpgradeFailed(currUid, result);
-            }
-        }
-        log.info("Upgrade VFs upon upgrade migration 1710 process finished successfully. ");
-        return true;
-    }
-
-    private boolean upgradeVf(String uniqueId, boolean allottedVfsUpgrade, boolean isInstance) {
-        log.info("Starting upgrade VF with uniqueId {} upon upgrade migration 1710 process. ", uniqueId);
-        Either<org.openecomp.sdc.be.model.Component, StorageOperationStatus> getRes = toscaOperationFacade.getToscaElement(uniqueId);
-        if (getRes.isRight()) {
-            log.debug("Failed to fetch VF with uniqueId {} upon upgrade migration 1710 process. ", uniqueId);
-            outputHandler.addRecord(ComponentTypeEnum.RESOURCE.name(), UNKNOWN, UNKNOWN, uniqueId, MigrationResult.MigrationStatus.FAILED.name(), getRes.right().value());
-            return false;
-        }
-        if(!allottedVfsUpgrade && isAllottedVf(getRes.left().value())){
-            keepAllottedResourceIfSupported(uniqueId);
-            return true;
-        }
-        if (StringUtils.isNotEmpty(getRes.left().value().getCsarUUID())) {
-            log.info("Going to fetch the latest version of VSP with csarUUID {} upon upgrade migration 1710 process. ", getRes.left().value().getCsarUUID());
-            Either<String, StorageOperationStatus> latestVersionRes = csarOperation.getCsarLatestVersion(getRes.left().value().getCsarUUID(), user);
-            if (latestVersionRes.isRight()) {
-                log.debug("Failed to fetch the latest version of VSP with csarUUID {} upon upgrade migration 1710 process. ", getRes.left().value().getCsarUUID());
-                outputHandler.addRecord(getRes.left().value().getComponentType().name(), getRes.left().value().getName(), getRes.left().value().getUUID(), getRes.left().value().getUniqueId(), MigrationResult.MigrationStatus.FAILED.name(), latestVersionRes.right().value());
-                return false;
-            }
-            if (isGreater(latestVersionRes.left().value(), getRes.left().value().getCsarVersion())) {
-                return upgradeVfWithLatestVsp(getRes.left().value(), latestVersionRes.left().value(), isInstance);
-            }
-            if (isVfcUpgradeRequired) {
-                return upgradeComponentWithLatestGeneric(getRes.left().value(), isInstance);
-            }
-            log.warn("Warning: No need to upgrade VF with name {}, invariantUUID {}, version {} and VSP version {}. No new version of VSP. ", getRes.left().value().getName(), getRes.left().value().getInvariantUUID(), getRes.left().value().getVersion(), getRes.left().value().getCsarVersion());
-            return true;
-        }
-        else {
-            return upgradeComponentWithLatestGeneric(getRes.left().value(), isInstance);
-        }
-    }
-
-    private void keepAllottedResourceIfSupported(final String uniqueId) {
-        if (isAllottedAndProxySupported && !vfAllottedResources.contains(uniqueId)) {
-            log.info("Add a resource with uniqueId {} to allotted resource list", uniqueId);
-            vfAllottedResources.add(uniqueId);
-        }
-    }
-
-    private boolean upgradeVfWithLatestVsp(org.openecomp.sdc.be.model.Component vf, String latestVersion, boolean isInstance) {
-        log.info("Starting upgrade vf with name {}, invariantUUID {}, version {} and latest VSP version {} upon upgrade migration 1710 process. ", vf.getName(), vf.getInvariantUUID(), vf.getVersion(), latestVersion);
-        Either<? extends org.openecomp.sdc.be.model.Component, ResponseFormat> checkouRes = checkOutComponent(vf);
-        if (checkouRes.isRight()) {
-            outputHandler.addRecord(vf.getComponentType().name(), vf.getName(), vf.getUUID(), vf.getUniqueId(), MigrationResult.MigrationStatus.FAILED.name(), checkouRes.right().value().getFormattedMessage());
-            return false;
-        }
-        Resource resourceToUpdate = new Resource(((Resource) checkouRes.left().value()).getComponentMetadataDefinition());
-        resourceToUpdate.setDerivedFromGenericType(((Resource) checkouRes.left().value()).getDerivedFromGenericType());
-        resourceToUpdate.setDerivedFromGenericVersion(((Resource) checkouRes.left().value()).getDerivedFromGenericVersion());
-        resourceToUpdate.setCsarVersion(Double.toString(Double.parseDouble(latestVersion)));
-        resourceToUpdate.setCategories(((Resource)checkouRes.left().value()).getCategories());
-        try {
-            Resource updateResourceFromCsarRes = resourceBusinessLogic.validateAndUpdateResourceFromCsar(resourceToUpdate, user, null, null, resourceToUpdate.getUniqueId());
-        } catch(ByResponseFormatComponentException e){
-            outputHandler.addRecord(resourceToUpdate.getComponentType().name(), resourceToUpdate.getName(), resourceToUpdate.getUUID(), resourceToUpdate.getUniqueId(), MigrationResult.MigrationStatus.FAILED.name(), e.getResponseFormat().getFormattedMessage());
-            log.info("Failed to update vf with name {}, invariantUUID {}, version {} and latest VSP {}. ", vf.getName(), vf.getInvariantUUID(), vf.getVersion(), latestVersion);
-            return false;
-        }
-        Either<? extends org.openecomp.sdc.be.model.Component, ResponseFormat> certifyRes = performFullCertification(checkouRes.left().value());
-        if (certifyRes.isRight()) {
-            log.info(FAILED_TO_CHANGE_STATE_OF_COMPONENT, checkouRes.left().value().getName(), checkouRes.left().value().getInvariantUUID(), checkouRes.left().value().getVersion(), LifeCycleTransitionEnum.CERTIFY);
-            outputHandler.addRecord(checkouRes.left().value().getComponentType().name(), checkouRes.left().value().getName(), checkouRes.left().value().getInvariantUUID(), checkouRes.left().value().getUniqueId(), MigrationResult.MigrationStatus.FAILED.name(), certifyRes.right().value().getFormattedMessage());
-            return false;
-        }
-        log.info("Full certification of vf with name {}, invariantUUID {}, version {} finished . ", vf.getName(), vf.getInvariantUUID(), vf.getVersion(), latestVersion);
-        outputHandler.addRecord(certifyRes.left().value().getComponentType().name(), certifyRes.left().value().getName(), certifyRes.left().value().getUUID(), certifyRes.left().value().getUniqueId(), MigrationResult.MigrationStatus.COMPLETED.name(), getVfUpgradeStatus(true, isInstance));
-        return true;
-    }
-
-    private boolean upgradeComponentWithLatestGeneric(org.openecomp.sdc.be.model.Component component, boolean isInstance) {
-        String derivedFromGenericType = component.getDerivedFromGenericType();
-        String derivedFromGenericVersion = component.getDerivedFromGenericVersion();
-        org.openecomp.sdc.be.model.Component updatedComponent = component;
-        if (failedToFindDerivedResourcesOfNodeType(component, derivedFromGenericType, derivedFromGenericVersion)) {
-            return false;
-        }
-        if (StringUtils.isEmpty(derivedFromGenericType) ||
-                latestVersionExists(latestGenericTypes.get(derivedFromGenericType), derivedFromGenericVersion) ||
-                isVfcUpgradeRequired ||
-                isAllottedAndProxySupported) {
-            if (StringUtils.isNotEmpty(derivedFromGenericType)) {
-                log.info("Newer version {} of derived from generic type {} exists. ", latestGenericTypes.get(derivedFromGenericType).getJsonMetadataField(JsonPresentationFields.VERSION), derivedFromGenericType);
-            }
-            else {
-                log.info("The vf resource with name {}, invariantUUID {}, version {},  has an empty derivedFromGenericType field. ", component.getName(), component.getInvariantUUID(), component.getVersion());
-            }
-            updatedComponent = checkOutAndCertifyComponent(component);
-        } else {
-            log.info("The version {} of derived from generic type {} is up to date. No need to upgrade component with name {}, invariantUUID {} and version {}. ", latestGenericTypes.get(derivedFromGenericType), derivedFromGenericType, component.getName(), component.getInvariantUUID(), component.getVersion());
-        }
-        if (updatedComponent != null) {
-            log.info(UPGRADE_COMPONENT_SUCCEEDED, component.getComponentType().getValue(), component.getName(), component.getInvariantUUID(), component.getVersion());
-            outputHandler.addRecord(updatedComponent.getComponentType().name(), updatedComponent.getName(), updatedComponent.getUUID(), updatedComponent.getUniqueId(), MigrationResult.MigrationStatus.COMPLETED.name(),
-                    getVfUpgradeStatus(!updatedComponent.equals(component), isInstance));
-        }
-        return true;
-    }
-
-    private org.openecomp.sdc.be.model.Component checkOutAndCertifyComponent(org.openecomp.sdc.be.model.Component component) {
-
-        log.info("Starting to perform check out of vf with name {}, invariantUUID {}, version {}. ", component.getName(), component.getInvariantUUID(), component.getVersion());
-        Either<? extends org.openecomp.sdc.be.model.Component, ResponseFormat> checkoutRes = checkOutComponent(component);
-        if (checkoutRes.isRight()) {
-            log.error(FAILED_TO_CHANGE_STATE_OF_COMPONENT, component.getName(), component.getInvariantUUID(), component.getVersion(), LifeCycleTransitionEnum.CHECKOUT);
-            outputHandler.addRecord(component.getComponentType().name(), component.getName(), component.getInvariantUUID(), component.getUniqueId(), MigrationResult.MigrationStatus.FAILED.name(), checkoutRes.right().value().getFormattedMessage());
-            return null;
-        }
-
-        if (!updateCompositionFailed(component, checkoutRes.left().value())) {
-            return null;
-        }
-        Either<? extends org.openecomp.sdc.be.model.Component, ResponseFormat> certifyRes = performFullCertification(checkoutRes.left().value());
-        if (certifyRes.isRight()) {
-            log.error(FAILED_TO_UPGRADE_COMPONENT, component.getComponentType().getValue(), component.getName(), component.getInvariantUUID(), component.getVersion(), "performFullCertification", certifyRes.right().value());
-            outputHandler.addRecord(checkoutRes.left().value().getComponentType().name(), checkoutRes.left().value().getName(), checkoutRes.left().value().getInvariantUUID(), checkoutRes.left().value().getUniqueId(), MigrationResult.MigrationStatus.FAILED.name(), certifyRes.right().value().getFormattedMessage());
-            return null;
-        }
-        return certifyRes.left().value();
-    }
-
-    private boolean failedToFindDerivedResourcesOfNodeType(org.openecomp.sdc.be.model.Component component, String derivedFromGenericType, String derivedFromGenericVersion) {
-        if (StringUtils.isNotEmpty(derivedFromGenericType) && !latestGenericTypes.containsKey(derivedFromGenericType)) {
-            log.info("Starting upgrade vf with name {}, invariantUUID {}, version {}, latest derived from generic type {}, latest derived from generic version {}. ", component.getName(), component.getInvariantUUID(), component.getVersion(), derivedFromGenericType, derivedFromGenericVersion);
-            log.info("Starting to fetch latest generic node type {}. ", derivedFromGenericType);
-            Either<List<GraphVertex>, JanusGraphOperationStatus> getDerivedRes = findDerivedResources(derivedFromGenericType);
-            if (getDerivedRes.isRight()) {
-                outputHandler.addRecord(component.getComponentType().name(), component.getName(), component.getInvariantUUID(), component.getUniqueId(), MigrationResult.MigrationStatus.FAILED.name(), getDerivedRes.right().value());
-                log.info("Failed to upgrade component with name {}, invariantUUID {}, version {} and latest generic. Status is {}. ", component.getName(), component.getInvariantUUID(), component.getVersion(), derivedFromGenericType);
-                return true;
-            }
-            latestGenericTypes.put(derivedFromGenericType, getDerivedRes.left().value().get(0));
-        }
-        return false;
-    }
-
-    private boolean updateCompositionFailed(org.openecomp.sdc.be.model.Component component, org.openecomp.sdc.be.model.Component checkoutResource) {
-        //try to update included VFCs, if it is either required as per configuration or an allotted resource
-        if ((isVfcUpgradeRequired && CollectionUtils.isNotEmpty(checkoutResource.getComponentInstances())) || isAllottedAndProxySupported) {
-            log.info("VFC upgrade is required: updating components of vf with name {}, invariantUUID {}, version {}. ", component.getName(), component.getInvariantUUID(), component.getVersion());
-            Either<org.openecomp.sdc.be.model.Component, ResponseFormat> updateCompositionRes = updateComposition(checkoutResource);
-            if (updateCompositionRes.isRight()) {
-                if (log.isErrorEnabled()) {
-                    log.error(FAILED_TO_UPGRADE_COMPONENT, checkoutResource.getComponentType().name(), checkoutResource.getName(), checkoutResource.getInvariantUUID(), checkoutResource.getVersion(), "updateComposition", updateCompositionRes.right().value().getFormattedMessage());
-                }
-                outputHandler.addRecord(checkoutResource.getComponentType().name(), checkoutResource.getName(), checkoutResource.getUUID(), checkoutResource.getUniqueId(), MigrationResult.MigrationStatus.FAILED.name(), updateCompositionRes.right().value().getFormattedMessage());
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private StorageOperationStatus upgradeNodeType(GraphVertex nodeTypeV, List<String> allCertifiedUids) {
-        StorageOperationStatus result = StorageOperationStatus.OK;
-        log.info("Starting upgrade node type with name {}, invariantUUID {}, version{}. ", nodeTypeV.getMetadataProperty(GraphPropertyEnum.NAME), nodeTypeV.getMetadataProperty(GraphPropertyEnum.INVARIANT_UUID), nodeTypeV.getMetadataProperty(GraphPropertyEnum.VERSION));
-        log.info("Starting to find derived to for node type with name {}, invariantUUID {}, version{}. ", nodeTypeV.getMetadataProperty(GraphPropertyEnum.NAME), nodeTypeV.getMetadataProperty(GraphPropertyEnum.INVARIANT_UUID), nodeTypeV.getMetadataProperty(GraphPropertyEnum.VERSION));
-        Either<List<GraphVertex>, JanusGraphOperationStatus> parentResourceRes = janusGraphDao
-            .getParentVertices(nodeTypeV, EdgeLabelEnum.DERIVED_FROM, JsonParseFlagEnum.ParseMetadata);
-        if (parentResourceRes.isRight() && parentResourceRes.right().value() != JanusGraphOperationStatus.NOT_FOUND) {
-            return DaoStatusConverter.convertJanusGraphStatusToStorageStatus(parentResourceRes.right().value());
-
-        }
-        List<GraphVertex> derivedResourcesUid = getAllDerivedGraphVertices(allCertifiedUids, parentResourceRes);
-        String uniqueId = (String) nodeTypeV.getJsonMetadataField(JsonPresentationFields.UNIQUE_ID);
-
-        Either<org.openecomp.sdc.be.model.Component, StorageOperationStatus> getRes = toscaOperationFacade.getToscaElement(uniqueId);
-        if (getRes.isRight()) {
-            log.info("failed to fetch element with uniqueId {} ", uniqueId);
-            return getRes.right().value();
-        }
-
-        Resource nodeType = (Resource)getRes.left().value();
-        if (!upgradedNodeTypesMap.containsKey(nodeType.getToscaResourceName()) && !nodeTypes.stream().anyMatch(p -> p.equals(nodeType.getToscaResourceName()))
-            && !isNodeTypeUpgradeSucceeded((Resource) getRes.left().value())) {
-                return StorageOperationStatus.GENERAL_ERROR;
-        }
-        for (GraphVertex chV : derivedResourcesUid) {
-            result = upgradeNodeType(chV, allCertifiedUids);
-            log.info("Upgrade node type with name {}, invariantUUID {}, version {} has been finished with the status {}", chV.getMetadataProperty(GraphPropertyEnum.NAME), chV.getMetadataProperty(GraphPropertyEnum.INVARIANT_UUID), chV.getMetadataProperty(GraphPropertyEnum.VERSION), result);
-        }
-        return result;
-    }
-
-    private boolean isNodeTypeUpgradeSucceeded(Resource nodeType) {
-        log.info("Starting to perform check out of node type with name {}, invariantUUID {}, version {}. ", nodeType.getName(), nodeType.getInvariantUUID(), nodeType.getVersion());
-        Either<? extends org.openecomp.sdc.be.model.Component, ResponseFormat> checkouRes =
-                lifecycleBusinessLogic.changeComponentState(nodeType.getComponentType(), nodeType.getUniqueId(), user, LifeCycleTransitionEnum.CHECKOUT, changeInfo, true, false);
-        if (checkouRes.isRight()) {
-            log.info("Failed to check out node type with name {}, invariantUUID {} due to {}", nodeType.getName(), nodeType.getInvariantUUID(), checkouRes.right().value());
-            return false;
-        }
-        if (performFullCertification(checkouRes.left().value()).isLeft()) {
-            upgradedNodeTypesMap.put(nodeType.getToscaResourceName(), checkouRes.left().value());
-            janusGraphDao.commit();
-            return true;
-        }
-        return false;
-    }
-
-    private List<GraphVertex> getAllDerivedGraphVertices(List<String> allCertifiedUids, Either<List<GraphVertex>, JanusGraphOperationStatus> parentResources) {
-        List<GraphVertex> derivedResourcesUid = new ArrayList<>();
-
-        if (parentResources.isLeft()) {
-            for (GraphVertex chV : parentResources.left().value()) {
-                Optional<String> op = allCertifiedUids.stream().filter(id -> id.equals((String) chV.getJsonMetadataField(JsonPresentationFields.UNIQUE_ID))).findAny();
-                if (op.isPresent()) {
-                    derivedResourcesUid.add(chV);
-                }
-            }
-        }
-        return derivedResourcesUid;
-    }
-
-    private Either<? extends org.openecomp.sdc.be.model.Component, ResponseFormat> performFullCertification(org.openecomp.sdc.be.model.Component component) {
-        log.info("Starting to perform full certification of {} with name {}, invariantUUID {}, version {}. ",
-                component.getComponentType().getValue(), component.getName(), component.getInvariantUUID(), component.getVersion());
-        org.openecomp.sdc.be.model.Component updatedComponent = component;
-        Either<? extends org.openecomp.sdc.be.model.Component, ResponseFormat> changeStateEither;
-        changeStateEither = lifecycleBusinessLogic.changeComponentState(component.getComponentType(), updatedComponent.getUniqueId(), user, LifeCycleTransitionEnum.CERTIFY, changeInfo, true, false);
-        if (changeStateEither.isRight()) {
-            log.info(FAILED_TO_CHANGE_STATE_OF_COMPONENT, component.getName(), component.getInvariantUUID(), component.getVersion(), LifeCycleTransitionEnum.CERTIFY);
-        } else {
-            log.info("Full certification of {} with name {}, invariantUUID {}, version {} finished successfully",
-                    changeStateEither.left().value().getComponentType().getValue(), changeStateEither.left().value().getName(),
-                    changeStateEither.left().value().getInvariantUUID(), changeStateEither.left().value().getVersion());
-        }
-        return changeStateEither;
-    }
-
-    private Either<List<GraphVertex>, JanusGraphOperationStatus> findDerivedResources(String parentResource) {
-        Map<GraphPropertyEnum, Object> propertiesToMatch = new EnumMap<>(GraphPropertyEnum.class);
-        propertiesToMatch.put(GraphPropertyEnum.STATE, LifecycleStateEnum.CERTIFIED.name());
-
-        propertiesToMatch.put(GraphPropertyEnum.TOSCA_RESOURCE_NAME, parentResource);
-        propertiesToMatch.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true);
-
-        return janusGraphDao
-            .getByCriteria(VertexTypeEnum.NODE_TYPE, propertiesToMatch, JsonParseFlagEnum.ParseMetadata);
-    }
-
-    private boolean latestVersionExists(GraphVertex latestDerivedFrom, String currentVersion) {
-        return isGreater((String) latestDerivedFrom.getJsonMetadataField(JsonPresentationFields.VERSION), currentVersion);
-    }
-
-    private boolean isGreater(String latestVersion, String currentVersion) {
-        if (latestVersion != null && currentVersion == null) {
-            return true;
-        }
-        if (latestVersion == null) {
-            return false;
-        }
-        return Double.parseDouble(latestVersion) > Double.parseDouble(currentVersion);
-    }
-
-    private Either<List<String>, JanusGraphOperationStatus> getAllLatestCertifiedComponentUids(VertexTypeEnum vertexType, ComponentTypeEnum componentType) {
-        log.info("Starting to fetch all latest certified not checked out components with type {} upon upgrade migration 1710 process", componentType);
-        Either<List<String>, JanusGraphOperationStatus> result = null;
-        Map<String, String> latestCertifiedMap = new HashMap<>();
-        Map<String, String> latestNotCertifiedMap = new HashMap<>();
-
-        Either<List<GraphVertex>, JanusGraphOperationStatus> getComponentsRes = getAllLatestComponents(vertexType, componentType);
-        if (getComponentsRes.isRight() && getComponentsRes.right().value() != JanusGraphOperationStatus.NOT_FOUND) {
-            log.error("Failed to fetch all latest certified not checked out components with type {}. Status is {}. ", componentType, getComponentsRes.right().value());
-            result = Either.right(getComponentsRes.right().value());
-        }
-        if (getComponentsRes.isRight()) {
-            result = Either.left(new ArrayList<>());
-        }
-        if (result == null) {
-            for (GraphVertex component : getComponentsRes.left().value()) {
-                String invariantUUID = (String) component.getJsonMetadataField(JsonPresentationFields.INVARIANT_UUID);
-                if (((String) component.getJsonMetadataField(JsonPresentationFields.LIFECYCLE_STATE)).equals(LifecycleStateEnum.CERTIFIED.name())) {
-                    latestCertifiedMap.put(invariantUUID, (String) component.getJsonMetadataField(JsonPresentationFields.UNIQUE_ID));
-                } else {
-                    latestNotCertifiedMap.put(invariantUUID, (String) component.getJsonMetadataField(JsonPresentationFields.UNIQUE_ID));
-                }
-            }
-            result = Either.left(latestCertifiedMap.entrySet().stream().filter(e -> !latestNotCertifiedMap.containsKey(e.getKey())).map(Map.Entry::getValue).collect(Collectors.toList()));
-        }
-        return result;
-    }
-
-    private Either<List<GraphVertex>, JanusGraphOperationStatus> getAllLatestComponents(VertexTypeEnum vertexType, ComponentTypeEnum componentType) {
-
-        Map<GraphPropertyEnum, Object> propertiesToMatch = new EnumMap<>(GraphPropertyEnum.class);
-        propertiesToMatch.put(GraphPropertyEnum.COMPONENT_TYPE, componentType.name());
-        propertiesToMatch.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true);
-
-
-        Map<GraphPropertyEnum, Object> propertiesNotToMatch = new EnumMap<>(GraphPropertyEnum.class);
-        propertiesNotToMatch.put(GraphPropertyEnum.IS_DELETED, true);
-        if (vertexType == VertexTypeEnum.TOPOLOGY_TEMPLATE && componentType == ComponentTypeEnum.RESOURCE) {
-            propertiesNotToMatch.put(GraphPropertyEnum.RESOURCE_TYPE, ResourceTypeEnum.CVFC.name());
-        }
-        return janusGraphDao
-            .getByCriteria(vertexType, propertiesToMatch, propertiesNotToMatch, JsonParseFlagEnum.ParseMetadata);
-    }
-
-    private Either<List<GraphVertex>, StorageOperationStatus> getLatestByName(GraphPropertyEnum property, String nodeName) {
-
-        Map<GraphPropertyEnum, Object> propertiesToMatch = new EnumMap<>(GraphPropertyEnum.class);
-        Map<GraphPropertyEnum, Object> propertiesNotToMatch = new EnumMap<>(GraphPropertyEnum.class);
-
-        propertiesToMatch.put(property, nodeName);
-        propertiesNotToMatch.put(GraphPropertyEnum.IS_DELETED, true);
-
-        Either<List<GraphVertex>, JanusGraphOperationStatus> highestResources = janusGraphDao
-            .getByCriteria(null, propertiesToMatch, propertiesNotToMatch, JsonParseFlagEnum.ParseMetadata);
-        if (highestResources.isRight()) {
-            JanusGraphOperationStatus status = highestResources.right().value();
-            log.debug("Failed to fetch resource with name {}. Status is {} ", nodeName, status);
-            return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
-        }
-        List<GraphVertex> resources = highestResources.left().value();
-        List<GraphVertex> result = new ArrayList<>();
-        for (GraphVertex component : resources) {
-            if (((String) component.getJsonMetadataField(JsonPresentationFields.LIFECYCLE_STATE)).equals(LifecycleStateEnum.CERTIFIED.name())) {
-                result.add(component);
-            }
-        }
-        return Either.left(result);
-    }
-
-    private void deleteMarkedComponents(NodeTypeEnum componentType, int toBeDeleted) {
-        Map<NodeTypeEnum, Either<List<String>, ResponseFormat>> cleanComponentsResult;
-        List<NodeTypeEnum> cleanComponents = new ArrayList<>();
-        cleanComponents.add(componentType);
-        try {
-            log.info("Trying to delete {} components of type {} marked as deleted", toBeDeleted, componentType);
-            cleanComponentsResult = componentsCleanBusinessLogic.cleanComponents(cleanComponents, true);
-            logDeleteResult(componentType, cleanComponentsResult.get(componentType));
-        }
-        catch (Exception e) {
-            log.error("Exception occurred {}", e.getMessage());
-            log.debug("Exception occurred", e);
-        }
-    }
-
-    private void logDeleteResult(NodeTypeEnum type, Either<List<String>, ResponseFormat> deleteResult) {
-        if (deleteResult == null) {
-            return;
-        }
-        if (deleteResult.isLeft()) {
-            log.info("Checked out {} versions are deleted successfully", type.getName());
-        }
-        else {
-            log.info("Cleanup of checked out {} versions failed due to the error: {}", type.getName(), deleteResult.right().value().getFormattedMessage());
-        }
-    }
-
-    private void markCheckedOutResourceAsDeletedIfUpgradeFailed(String certUid, boolean isNotFailed) {
-        String checkedOutUniqueId = certifiedToNextCheckedOutUniqueId.remove(certUid);
-        if (!isNotFailed && checkedOutUniqueId != null) {
-            try {
-                //mark as deleted the checked out resource as this upgrade failed
-                ResponseFormat respFormat = resourceBusinessLogic.deleteResource(checkedOutUniqueId.toLowerCase(), user);
-                log.info("Checked out resource uniqueId = {} is marked as deleted, status: {}", checkedOutUniqueId, respFormat.getFormattedMessage());
-                deleteResourcesIfLimitIsReached();
-            }
-            catch (Exception e) {
-                log.error("Error occurred:", e);
-            }
-        }
-    }
-
-    private void markCheckedOutServiceAsDeletedIfUpgradeFailed(String certUid, boolean isNotFailed) {
-        String checkedOutUniqueId = certifiedToNextCheckedOutUniqueId.remove(certUid);
-        if (!isNotFailed && checkedOutUniqueId != null) {
-            try {
-                //delete the checked out resource as this upgrade failed
-                ResponseFormat respFormat = serviceBusinessLogic.deleteService(checkedOutUniqueId.toLowerCase(), user);
-                log.info("Checked out service uniqueId = {} is marked as deleted, status: {}", checkedOutUniqueId, respFormat.getFormattedMessage());
-                deleteServicesIfLimitIsReached();
-            } catch (Exception e) {
-                log.error("Error occurred:", e);
-            }
-        }
-
-    }
-
-    void deleteResourcesIfLimitIsReached() {
-        markedAsDeletedResourcesCnt++;
-        if (markedAsDeletedResourcesCnt >= maxDeleteComponents) {
-            deleteMarkedComponents(NodeTypeEnum.Resource, markedAsDeletedResourcesCnt);
-            markedAsDeletedResourcesCnt = 0;
-        }
-    }
-
-    void deleteServicesIfLimitIsReached() {
-        markedAsDeletedServicesCnt++;
-        if (markedAsDeletedServicesCnt >= maxDeleteComponents) {
-            deleteMarkedComponents(NodeTypeEnum.Service, markedAsDeletedServicesCnt);
-            markedAsDeletedServicesCnt = 0;
-        }
-    }
-
-    boolean isLockDeleteOperationSucceeded() {
-        StorageOperationStatus status = componentsCleanBusinessLogic.lockDeleteOperation();
-
-        switch(status) {
-            case OK:
-                log.info("Lock delete operation succeeded");
-                isCleanupLocked = true;
-                break;
-            case FAILED_TO_LOCK_ELEMENT:
-                log.info("Delete operation node is already locked");
-                isCleanupLocked = isLockRetrySucceeded();
-                break;
-            default:
-                log.error("Lock delete operation failed due to the error: {}", status);
-                isCleanupLocked = false;
-                break;
-        }
-        return isCleanupLocked;
-    }
-
-    private boolean isLockRetrySucceeded() {
-        long startTime = System.currentTimeMillis();
-        //try to lock the cleanup resource until configurable time interval is finished
-        while (System.currentTimeMillis() - startTime <= deleteLockTimeoutInSeconds * 1000) {
-            try {
-                //sleep one second and try lock again
-                Thread.sleep(1000);
-                if (componentsCleanBusinessLogic.lockDeleteOperation() == StorageOperationStatus.OK) {
-                    return true;
-                }
-            } catch (InterruptedException e) {
-                log.error("Error occurred: {}", e.getMessage());
-                Thread.currentThread().interrupt();
-            }
-        }
-        return false;
-    }
-
-    void unlockDeleteOperation() {
-        if (isCleanupLocked) {
-            try {
-                componentsCleanBusinessLogic.unlockDeleteOperation();
-                log.info("Lock delete operation is canceled");
-                isCleanupLocked = false;
-            }
-            catch (Exception e) {
-                log.debug("Failed to unlock delete operation", e);
-                log.error("Failed to unlock delete operation due to the error {}", e.getMessage());
-            }
-        }
-    }
-
-    private Either<? extends org.openecomp.sdc.be.model.Component, ResponseFormat> checkOutComponent(org.openecomp.sdc.be.model.Component component) {
-        log.info("Starting to perform check out of {} {}, uniqueId = {}", component.getComponentType(), component.getName(), component.getUniqueId());
-        Either<? extends org.openecomp.sdc.be.model.Component, ResponseFormat> checkoutRes =
-                lifecycleBusinessLogic.changeComponentState(component.getComponentType(), component.getUniqueId(), user, LifeCycleTransitionEnum.CHECKOUT, changeInfo, true, false);
-        if (checkoutRes.isLeft()) {
-            //add the uniqueId from "upgradeVf(String uniqueId)" and checkouRes's uniqueUID to the new map
-            certifiedToNextCheckedOutUniqueId.put(component.getUniqueId(), checkoutRes.left().value().getUniqueId());
-            log.debug("Add checked out component uniqueId = {} produced from certified component uniqueId = {} to the checked out map", checkoutRes.left().value().getUniqueId(), component.getUniqueId());
-        }
-        return checkoutRes;
-    }
-
-    UpgradeStatus getVfUpgradeStatus(boolean isUpgraded, boolean isInstance) {
-        if (isUpgraded) {
-            return isInstance ? UpgradeStatus.UPGRADED_AS_INSTANCE : UpgradeStatus.UPGRADED;
-        }
-        return UpgradeStatus.NOT_UPGRADED;
-    }
-
-}
diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/tasks/mig1902/SdcGroupsMigration.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/tasks/mig1902/SdcGroupsMigration.java
deleted file mode 100644
index 1045634..0000000
--- a/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/tasks/mig1902/SdcGroupsMigration.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-package org.openecomp.sdc.asdctool.migration.tasks.mig1902;
-
-import org.openecomp.sdc.asdctool.migration.core.DBVersion;
-import org.openecomp.sdc.asdctool.migration.core.task.Migration;
-import org.openecomp.sdc.asdctool.migration.core.task.MigrationResult;
-import org.openecomp.sdc.asdctool.migration.tasks.InstanceMigrationBase;
-import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
-import org.openecomp.sdc.be.dao.jsongraph.JanusGraphDao;
-import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum;
-import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
-import org.openecomp.sdc.be.datatypes.elements.GroupDataDefinition;
-import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
-import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
-import org.openecomp.sdc.be.model.GroupTypeDefinition;
-import org.openecomp.sdc.be.model.PropertyDefinition;
-import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
-import org.openecomp.sdc.be.model.operations.impl.GroupTypeOperation;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Component;
-
-import java.math.BigInteger;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-@Component
-public class SdcGroupsMigration extends InstanceMigrationBase implements Migration {
-
-    private static final Logger log = LoggerFactory.getLogger(SdcGroupsMigration.class);
-
-    private final GroupTypeOperation groupTypeOperation;
-
-    private Map<String, GroupTypeDefinition> latestGroupTypeMap = new HashMap<>();
-
-    public enum GroupsForUpgrade {
-        NW_COLLECTION_GROUP_NAME("org.openecomp.groups.NetworkCollection"),
-        VFC_INSTANCE_GROUP_NAME("org.openecomp.groups.VfcInstanceGroup");
-
-        private String toscaType;
-
-        GroupsForUpgrade(String toscaType) {
-            this.toscaType = toscaType;
-        }
-
-        public static boolean containsToscaType(String type) {
-            try {
-                return Arrays.stream(values()).anyMatch(g->g.getToscaType().equals(type));
-            }
-            catch (IllegalArgumentException ex) {
-                return false;
-            }
-        }
-
-        public String getToscaType() {
-            return toscaType;
-        }
-
-    }
-    public SdcGroupsMigration(JanusGraphDao janusGraphDao, GroupTypeOperation groupTypeOperation) {
-        super(janusGraphDao);
-        this.groupTypeOperation = groupTypeOperation;
-    }
-
-    @Override
-    public String description() {
-        return "update derived from field value for NetworkCollection and VfcInstanceGroup group instances ";
-    }
-
-    @Override
-    public DBVersion getVersion() {
-        return DBVersion.from(BigInteger.valueOf(1902), BigInteger.valueOf(0));
-    }
-
-    @Override
-    public MigrationResult migrate() {
-        loadLatestGroupTypeDefinitions();
-        StorageOperationStatus status = upgradeTopologyTemplates();
-        return status == StorageOperationStatus.OK ?
-                MigrationResult.success() : MigrationResult.error("failed to update derived from value for NetworkCollection and VfcInstanceGroup group instances. Error : " + status);
-    }
-
-    void loadLatestGroupTypeDefinitions() {
-        Arrays.stream(GroupsForUpgrade.values()).forEach(this::getLatestGroupTypeDefinition);
-    }
-
-    @Override
-    protected StorageOperationStatus handleOneContainer(GraphVertex containerVorig) {
-        StorageOperationStatus status = StorageOperationStatus.NOT_FOUND;
-        GraphVertex containerV = getVertexById(containerVorig.getUniqueId());
-
-        try {
-            status = janusGraphDao.getChildVertex(containerV, EdgeLabelEnum.GROUPS, JsonParseFlagEnum.ParseAll)
-                    .either(this::updateGroupPropertiesIfRequired, this::handleError);
-        }
-        catch (Exception e) {
-            log.error("Exception occurred:", e);
-            status = StorageOperationStatus.GENERAL_ERROR;
-        }
-        finally {
-            if (status != StorageOperationStatus.OK) {
-                janusGraphDao.rollback();
-                if (status == StorageOperationStatus.NOT_FOUND) {
-                    //it is happy flow as well
-                    status = StorageOperationStatus.OK;
-                }
-            }
-            if (log.isInfoEnabled()) {
-                log.info("Upgrade status is <{}> for topology template <{}> uniqueId <{}>",
-                        status.name(), containerV.getMetadataProperties().get(GraphPropertyEnum.NAME),
-                        containerV.getMetadataProperties().get(GraphPropertyEnum.UNIQUE_ID));
-            }
-        }
-        return status;
-    }
-
-    private StorageOperationStatus updateGroupPropertiesIfRequired(GraphVertex vertex) {
-        StorageOperationStatus status = StorageOperationStatus.NOT_FOUND;
-        boolean isUpdated = false;
-        Map<String, GroupDataDefinition> groupDefinitionMap = (Map<String, GroupDataDefinition>) vertex.getJson();
-        for (GroupDataDefinition groupDef : groupDefinitionMap.values()) {
-           if (GroupsForUpgrade.containsToscaType(groupDef.getType())) {
-                if (log.isDebugEnabled()) {
-                    log.debug("Group instance named <{}> of type <{}> is supposed to be updated on vertex <{}>",
-                            groupDef.getName(), groupDef.getType(), vertex.getUniqueId());
-                }
-                isUpdated = isGroupPropertiesUpdateDone(groupDef.getProperties(), latestGroupTypeMap.get(groupDef.getType()).getProperties());
-                if (log.isDebugEnabled()) {
-                    String result = isUpdated ? "has been updated" : "is up to date ";
-                    log.debug("Group instance named <{}> of type <{}> uniqueID <{}> {} on vertex <{}>",
-                                            groupDef.getName(), groupDef.getType(), groupDef.getUniqueId(), result, vertex.getUniqueId());
-                }
-            }
-        }
-        if (isUpdated) {
-            vertex.setJson(groupDefinitionMap);
-            status = updateVertexAndCommit(vertex);
-            if (status == StorageOperationStatus.OK && log.isDebugEnabled()) {
-                log.debug("Group properties change is committed on vertex <{}>", vertex.getUniqueId());
-            }
-        }
-        return status;
-    }
-
-    private boolean isGroupPropertiesUpdateDone(List<PropertyDataDefinition> curPropDefList, List<PropertyDefinition> latestGroupDefList) {
-        boolean isUpdated = false;
-        for (PropertyDefinition prop: latestGroupDefList) {
-            if (curPropDefList.stream().noneMatch(l->l.getName().equals(prop.getName()))) {
-                curPropDefList.add(prop);
-                isUpdated = true;
-            }
-        }
-        return isUpdated;
-    }
-
-    StorageOperationStatus getLatestGroupTypeDefinition(GroupsForUpgrade groupsForUpgrade) {
-        return groupTypeOperation.getLatestGroupTypeByType(groupsForUpgrade.getToscaType(), false)
-                .either(g-> {
-                    latestGroupTypeMap.put(groupsForUpgrade.getToscaType(), g);
-                    return StorageOperationStatus.OK;
-                }, err->err);
-    }
-
-
-}
diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/tasks/mig1902/SdcResourceIconMigration.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/tasks/mig1902/SdcResourceIconMigration.java
deleted file mode 100644
index 837abf1..0000000
--- a/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/tasks/mig1902/SdcResourceIconMigration.java
+++ /dev/null
@@ -1,187 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-package org.openecomp.sdc.asdctool.migration.tasks.mig1902;
-
-import com.google.common.annotations.VisibleForTesting;
-import org.openecomp.sdc.asdctool.migration.core.DBVersion;
-import org.openecomp.sdc.asdctool.migration.core.task.Migration;
-import org.openecomp.sdc.asdctool.migration.core.task.MigrationResult;
-import org.openecomp.sdc.asdctool.migration.tasks.InstanceMigrationBase;
-import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
-import org.openecomp.sdc.be.dao.jsongraph.JanusGraphDao;
-import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
-import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum;
-import org.openecomp.sdc.be.datatypes.elements.ComponentInstanceDataDefinition;
-import org.openecomp.sdc.be.datatypes.elements.CompositionDataDefinition;
-import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
-import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
-import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
-import org.openecomp.sdc.be.model.jsonjanusgraph.enums.JsonConstantKeysEnum;
-import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
-import org.openecomp.sdc.common.log.wrappers.Logger;
-import org.springframework.stereotype.Component;
-
-import java.math.BigInteger;
-import java.util.EnumMap;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-@Component
-public class SdcResourceIconMigration extends InstanceMigrationBase implements Migration {
-
-    private static final Logger log = Logger.getLogger(SdcResourceIconMigration.class);
-
-    private Map <String, String> resourceTypeToIconMap = new HashMap<>();
-
-    @VisibleForTesting
-    SdcResourceIconMigration(JanusGraphDao janusGraphDao) {
-        super(janusGraphDao);
-    }
-
-
-    @Override
-    public String description() {
-        return "update iconPath for VL and CP nodes";
-    }
-
-    @Override
-    public DBVersion getVersion() {
-        return DBVersion.from(BigInteger.valueOf(1902), BigInteger.valueOf(0));
-    }
-
-    @Override
-    public MigrationResult migrate() {
-        StorageOperationStatus status;
-        try {
-            updateNodeTypeIconAndStoreInMap(ResourceTypeEnum.VL);
-            updateNodeTypeIconAndStoreInMap(ResourceTypeEnum.CP);
-
-            if (!resourceTypeToIconMap.isEmpty()) {
-                status = upgradeTopologyTemplates();
-            } else {
-                log.error("No VL and CP node definitions found");
-                status = StorageOperationStatus.NOT_FOUND;
-            }
-        }
-        catch(Exception e) {
-            log.error("Exception thrown: {}", e);
-            status = StorageOperationStatus.GENERAL_ERROR;
-        }
-        return status == StorageOperationStatus.OK ?
-                    MigrationResult.success() : MigrationResult.error("failed to update iconPath for VL and CP nodes. Error : " + status);
-    }
-
-    @Override
-    protected StorageOperationStatus handleOneContainer(GraphVertex containerVorig) {
-        StorageOperationStatus status = StorageOperationStatus.OK;
-        GraphVertex containerV = getVertexById(containerVorig.getUniqueId());
-
-        Map<String, CompositionDataDefinition> jsonComposition = (Map<String, CompositionDataDefinition>)containerV.getJson();
-        if (jsonComposition != null && !jsonComposition.isEmpty()) {
-            CompositionDataDefinition compositionDataDefinition = jsonComposition.get(JsonConstantKeysEnum.COMPOSITION.getValue());
-            Map<String, ComponentInstanceDataDefinition> componentInstances = compositionDataDefinition.getComponentInstances();
-
-            long updateCount = componentInstances.values()
-                    .stream()
-                    .filter(this::updateIconInsideInstance).count();
-            if (updateCount > 0) {
-                status = updateVertexAndCommit(containerV);
-            }
-        }
-        else {
-            log.warn("No json found for template <{}> uniqueId <{}>",
-                    containerV.getMetadataProperties().get(GraphPropertyEnum.NAME),
-                    containerV.getMetadataProperties().get(GraphPropertyEnum.UNIQUE_ID));
-        }
-        if (log.isInfoEnabled()) {
-            log.info("Upgrade status is <{}> for topology template <{}> uniqueId <{}>",
-                    status.name(), containerV.getMetadataProperties().get(GraphPropertyEnum.NAME),
-                    containerV.getMetadataProperties().get(GraphPropertyEnum.UNIQUE_ID));
-        }
-        return status;
-    }
-
-
-    @VisibleForTesting
-    boolean updateIconInsideInstance(ComponentInstanceDataDefinition componentInstanceDataDefinition) {
-        String iconPath = resourceTypeToIconMap.get(componentInstanceDataDefinition.getComponentName());
-        if (iconPath != null) {
-            componentInstanceDataDefinition.setIcon(iconPath);
-            if (log.isDebugEnabled()) {
-                log.debug("Icon of component {} is set to {}", componentInstanceDataDefinition.getComponentName(), iconPath);
-            }
-            return true;
-        }
-        return false;
-    }
-
-    @VisibleForTesting
-    void updateNodeTypeIconAndStoreInMap(ResourceTypeEnum resourceType) {
-        Map<GraphPropertyEnum, Object> propertiesToMatch = new EnumMap<>(GraphPropertyEnum.class);
-        Map<GraphPropertyEnum, Object> propertiesNotToMatch = new EnumMap<>(GraphPropertyEnum.class);
-
-        propertiesToMatch.put(GraphPropertyEnum.RESOURCE_TYPE, resourceType.name());
-        propertiesToMatch.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true);
-
-        propertiesNotToMatch.put(GraphPropertyEnum.IS_DELETED, true);
-
-        String iconPath = String.valueOf(resourceType.getValue()).toLowerCase();
-
-        Map<String, String> resourceNameToIconMap = janusGraphDao.getByCriteria(VertexTypeEnum.NODE_TYPE, propertiesToMatch, propertiesNotToMatch, JsonParseFlagEnum.ParseAll)
-                .either(vl-> updateIconResource(vl, iconPath), status->null);
-
-        if (resourceNameToIconMap != null) {
-            resourceTypeToIconMap.putAll(resourceNameToIconMap);
-        }
-        else {
-            log.warn("Failed to get resources of type <{}>", resourceType.name());
-        }
-    }
-
-    private Map <String, String> updateIconResource(List<GraphVertex> vertexList, String iconPath) {
-        if (vertexList.isEmpty()) {
-            return null;
-        }
-        Map <String, String> nameToIconMap = new HashMap<>();
-        vertexList.forEach(v->{
-            StorageOperationStatus status = updateIconOnVertex(v, iconPath);
-            if (status == StorageOperationStatus.OK) {
-                if (log.isDebugEnabled()) {
-                    log.debug("Node type's {} icon is updated to {}", v.getMetadataProperty(GraphPropertyEnum.NAME), iconPath);
-                }
-                nameToIconMap.put(String.valueOf(v.getMetadataProperty(GraphPropertyEnum.NAME)), iconPath);
-            }
-            else {
-                log.error("Failed to update node type {} icon due to a reason: {}",
-                                v.getMetadataProperty(GraphPropertyEnum.NAME), status);
-                throw new RuntimeException("Node update failure");
-            }
-        });
-        return nameToIconMap;
-    }
-
-    private StorageOperationStatus updateIconOnVertex(GraphVertex vertex, String iconPath) {
-        vertex.setJsonMetadataField(JsonPresentationFields.ICON, iconPath);
-        return updateVertexAndCommit(vertex);
-    }
-
-}
diff --git a/asdctool/src/test/java/org/openecomp/sdc/asdctool/impl/validator/utils/ValidationTaskResultTest.java b/asdctool/src/test/java/org/openecomp/sdc/asdctool/impl/validator/utils/ValidationTaskResultTest.java
deleted file mode 100644
index afbda6e..0000000
--- a/asdctool/src/test/java/org/openecomp/sdc/asdctool/impl/validator/utils/ValidationTaskResultTest.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *      http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-package org.openecomp.sdc.asdctool.impl.validator.utils;
-
-import org.junit.Test;
-import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
-
-
-public class ValidationTaskResultTest {
-
-	private ValidationTaskResult createTestSubject() {
-		return new ValidationTaskResult(new GraphVertex(), "", "", false);
-	}
-
-	
-	@Test
-	public void testGetName() {
-		ValidationTaskResult testSubject;
-		String result;
-
-		// default test
-		testSubject = createTestSubject();
-		result = testSubject.getName();
-	}
-
-	
-	@Test
-	public void testSetName() {
-		ValidationTaskResult testSubject;
-		String name = "";
-
-		// default test
-		testSubject = createTestSubject();
-		testSubject.setName(name);
-	}
-
-	
-	@Test
-	public void testGetResultMessage() {
-		ValidationTaskResult testSubject;
-		String result;
-
-		// default test
-		testSubject = createTestSubject();
-		result = testSubject.getResultMessage();
-	}
-
-	
-	@Test
-	public void testSetResultMessage() {
-		ValidationTaskResult testSubject;
-		String resultMessage = "";
-
-		// default test
-		testSubject = createTestSubject();
-		testSubject.setResultMessage(resultMessage);
-	}
-
-	
-	@Test
-	public void testIsSuccessful() {
-		ValidationTaskResult testSubject;
-		boolean result;
-
-		// default test
-		testSubject = createTestSubject();
-		result = testSubject.isSuccessful();
-	}
-
-	
-	@Test
-	public void testSetSuccessful() {
-		ValidationTaskResult testSubject;
-		boolean successful = false;
-
-		// default test
-		testSubject = createTestSubject();
-		testSubject.setSuccessful(successful);
-	}
-}
diff --git a/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/tasks/mig1710/UpgradeMigration1710Test.java b/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/tasks/mig1710/UpgradeMigration1710Test.java
deleted file mode 100644
index 8763a1b..0000000
--- a/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/tasks/mig1710/UpgradeMigration1710Test.java
+++ /dev/null
@@ -1,648 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- * Modifications copyright (c) 2019 Nokia
- * ================================================================================
- */
-package org.openecomp.sdc.asdctool.migration.tasks.mig1710;
-
-import com.google.common.collect.Lists;
-import fj.data.Either;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnitRunner;
-import org.openecomp.sdc.asdctool.migration.core.task.MigrationResult;
-import org.openecomp.sdc.asdctool.migration.tasks.handlers.XlsOutputHandler;
-import org.openecomp.sdc.be.components.impl.ResourceBusinessLogic;
-import org.openecomp.sdc.be.components.impl.ServiceBusinessLogic;
-import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException;
-import org.openecomp.sdc.be.components.lifecycle.LifecycleBusinessLogic;
-import org.openecomp.sdc.be.components.scheduledtasks.ComponentsCleanBusinessLogic;
-import org.openecomp.sdc.be.config.Configuration;
-import org.openecomp.sdc.be.config.ConfigurationManager;
-import org.openecomp.sdc.be.dao.api.ActionStatus;
-import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
-import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
-import org.openecomp.sdc.be.dao.jsongraph.JanusGraphDao;
-import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum;
-import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
-import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum;
-import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
-import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
-import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
-import org.openecomp.sdc.be.impl.ComponentsUtils;
-import org.openecomp.sdc.be.model.Component;
-import org.openecomp.sdc.be.model.ComponentInstance;
-import org.openecomp.sdc.be.model.ComponentParametersView;
-import org.openecomp.sdc.be.model.LifecycleStateEnum;
-import org.openecomp.sdc.be.model.Resource;
-import org.openecomp.sdc.be.model.Service;
-import org.openecomp.sdc.be.model.User;
-import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
-import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
-import org.openecomp.sdc.be.model.operations.impl.CsarOperation;
-import org.openecomp.sdc.be.model.operations.impl.UserAdminOperation;
-import org.openecomp.sdc.common.api.ConfigurationSource;
-import org.openecomp.sdc.common.http.client.api.HttpRequestHandler;
-import org.openecomp.sdc.exception.ResponseFormat;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-@RunWith(MockitoJUnitRunner.class)
-public class UpgradeMigration1710Test {
-
-    private static final String USER = "jh0003";
-    private static final String CONF_LEVEL = "5.0";
-    private static final String COMPONENT_UNIQUE_ID = "12345";
-    private static final String OLD_VERSION = "1.0";
-    private static final String UPDATED_VERSION = "2.0";
-    private static final String CSAR_UUID = "1234578";
-    private static HttpRequestHandler originHandler;
-
-    private final User user = new User();
-
-    @InjectMocks
-    private UpgradeMigration1710 migration = new UpgradeMigration1710();
-    @Mock
-    private UserAdminOperation userAdminOperation;
-    @Mock
-    private ToscaOperationFacade toscaOperationFacade;
-    @Mock
-    private LifecycleBusinessLogic lifecycleBusinessLogic;
-    @Mock
-    private JanusGraphDao janusGraphDao;
-    @Mock
-    private ComponentsUtils componentUtils;
-    @Mock
-    private CsarOperation csarOperation;
-    @Mock
-    private ConfigurationSource configurationSource;
-    //don't remove - it is intended to avoid the xls file generating
-    @Mock
-    private XlsOutputHandler outputHandler;
-    @Mock
-    private ResourceBusinessLogic resourceBusinessLogic;
-    @Mock
-    private ServiceBusinessLogic serviceBusinessLogic;
-    @Mock
-    private ResponseFormat responseFormat;
-    @Mock
-    private ComponentsCleanBusinessLogic componentsCleanBusinessLogic;
-
-    private static ConfigurationManager configurationManager;
-    private static List<String> resources = Stream.of("org.openecomp.resource.cp.extCP").collect(Collectors.toList());
-    private static Map<String, List<String>> resourcesForUpgrade;
-    private static Configuration.EnvironmentContext environmentContext = new Configuration.EnvironmentContext();
-
-    private Resource resource;
-    private Service service;
-    private List<String> vfList = new ArrayList<>();
-
-    @BeforeClass
-    public static void setUpClass() {
-        resourcesForUpgrade = new HashMap<>();
-        resourcesForUpgrade.put(CONF_LEVEL, resources);
-        originHandler = HttpRequestHandler.get();
-    }
-
-    @AfterClass
-    public static void tearDownClass() {
-        //put the origin handler back
-        HttpRequestHandler.setTestInstance(originHandler);
-    }
-
-    @Before
-    public void setUp() {
-        user.setUserId(USER);
-        configurationManager = new ConfigurationManager(configurationSource);
-        configurationManager.setConfiguration(new Configuration());
-        configurationManager.getConfiguration().setSkipUpgradeVSPs(true);
-        configurationManager.getConfiguration().setSkipUpgradeFailedVfs(true);
-        configurationManager.getConfiguration().setAutoHealingOwner(USER);
-        configurationManager.getConfiguration().setSupportAllottedResourcesAndProxy(true);
-        configurationManager.getConfiguration().setDeleteLockTimeoutInSeconds(10);
-        configurationManager.getConfiguration().setMaxDeleteComponents(5);
-        configurationManager.getConfiguration().setEnableAutoHealing(true);
-        configurationManager.getConfiguration().setToscaConformanceLevel("5.0");
-        environmentContext.setDefaultValue("General_Revenue-Bearing");
-        configurationManager.getConfiguration().setEnvironmentContext(environmentContext);
-        HashMap<String, List<String>> resourcesForUpgrade = new HashMap();
-        resourcesForUpgrade.put("5.0", Lists.newArrayList("port"));
-        configurationManager.getConfiguration().setResourcesForUpgrade(resourcesForUpgrade);
-
-        migration.init();
-        migration.setNodeTypesSupportOnly(false);
-        when(componentsCleanBusinessLogic.lockDeleteOperation()).thenReturn(StorageOperationStatus.OK);
-
-        resource = new Resource();
-        resource.setCsarUUID(CSAR_UUID);
-        resource.setVersion(OLD_VERSION);
-        resource.setUniqueId(COMPONENT_UNIQUE_ID);
-
-        service = new Service();
-        service.setVersion(OLD_VERSION);
-        service.setUniqueId(COMPONENT_UNIQUE_ID);
-
-        vfList.add(COMPONENT_UNIQUE_ID);
-
-        when(responseFormat.getFormattedMessage())
-                .thenReturn("");
-        when(componentUtils.convertFromStorageResponse(any(), any())).thenCallRealMethod();
-        mockChangeComponentState();
-    }
-
-    @Test
-    public void nodeTypesUpgradeFailed() {
-        migration.setNodeTypesSupportOnly(true);
-        resolveUserAndDefineUpgradeLevel();
-        when(janusGraphDao.getByCriteria(any(), any(), any(), any()))
-                .thenReturn(Either.right(JanusGraphOperationStatus.NOT_FOUND));
-        assertEquals(MigrationResult.MigrationStatus.FAILED, migration.migrate().getMigrationStatus());
-    }
-
-    @Test
-    public void migrationDisabled() {
-        configurationManager.getConfiguration().setEnableAutoHealing(false);
-        migration.init();
-        assertEquals(MigrationResult.MigrationStatus.COMPLETED, migration.migrate().getMigrationStatus());
-        verify(janusGraphDao, times(0)).commit();
-        verify(janusGraphDao, times(0)).rollback();
-    }
-
-    @Test
-    public void migrationFailedIfDeleteNodeLockFailed() {
-        when(componentsCleanBusinessLogic.lockDeleteOperation())
-                .thenReturn(StorageOperationStatus.BAD_REQUEST);
-        assertEquals(MigrationResult.MigrationStatus.FAILED, migration.migrate().getMigrationStatus());
-    }
-
-    @Test
-    public void migrationFailedIfDeleteNodeLockRetryFailed() {
-        when(componentsCleanBusinessLogic.lockDeleteOperation())
-                .thenReturn(StorageOperationStatus.FAILED_TO_LOCK_ELEMENT)
-                .thenReturn(StorageOperationStatus.BAD_REQUEST);
-        assertEquals(MigrationResult.MigrationStatus.FAILED, migration.migrate().getMigrationStatus());
-    }
-
-    @Test
-    public void nodeTypesOnlyUpgradePassed() {
-        migration.setNodeTypesSupportOnly(true);
-        upgradeAllScenario(false);
-        assertEquals(MigrationResult.MigrationStatus.COMPLETED, migration.migrate().getMigrationStatus());
-        verify(janusGraphDao, times(2)).commit();
-        verify(janusGraphDao, times(0)).rollback();
-    }
-
-    @Test
-    public void nodeTypesUpgradePassedAndVFsUpgradeFailedWhenSkipFailedVFsIsNotSupported() {
-        final boolean failOnVfUpgrade = true;
-        final boolean upgradeServices = false;
-        final boolean exceptionOnVfUpgrade = false;
-        final boolean upgradeVFC = false;
-        final boolean isFailed = true;
-        configurationManager.getConfiguration().setSkipUpgradeFailedVfs(false);
-        migration.init();
-        migration.setNodeTypesSupportOnly(false);
-        resolveUserAndDefineUpgradeLevel();
-        upgradeRules(failOnVfUpgrade, exceptionOnVfUpgrade, upgradeServices, upgradeVFC, isFailed);
-        assertEquals(MigrationResult.MigrationStatus.FAILED, migration.migrate().getMigrationStatus());
-        verify(janusGraphDao, times(1)).commit();
-        verify(janusGraphDao, times(2)).rollback();
-    }
-
-
-    @Test
-    public void upgradeAllVFsUpgradeFailedOnExceptionWhenSkipFailedVFsIsNotSupported() {
-        final boolean failOnVfUpgrade = false;
-        final boolean upgradeServices = false;
-        final boolean exceptionOnVfUpgrade = true;
-        final boolean upgradeVFC = false;
-        final boolean isFailed = true;
-        configurationManager.getConfiguration().setSkipUpgradeFailedVfs(false);
-        resolveUserAndDefineUpgradeLevel();
-        upgradeRules(failOnVfUpgrade, exceptionOnVfUpgrade, upgradeServices, upgradeVFC, isFailed);
-        migration.init();
-        assertEquals(MigrationResult.MigrationStatus.COMPLETED, migration.migrate().getMigrationStatus());
-        verify(janusGraphDao, times(2)).commit();
-        verify(janusGraphDao, times(0)).rollback();
-    }
-
-    @Test
-    public void upgradeAllIfVFsUpgradeFailedOnExceptionWhenSkipFailedVFsIsSupported() {
-        final boolean failOnVfUpgrade = false;
-        final boolean upgradeServices = true;
-        final boolean exceptionOnFvUpgrade = true;
-        final boolean upgradeVFC = false;
-        final boolean isFailed = false;
-        configurationManager.getConfiguration().setSkipUpgradeFailedVfs(true);
-        resolveUserAndDefineUpgradeLevel();
-        upgradeRules(failOnVfUpgrade, exceptionOnFvUpgrade, upgradeServices, upgradeVFC, isFailed);
-        assertEquals(MigrationResult.MigrationStatus.COMPLETED, migration.migrate().getMigrationStatus());
-        verify(janusGraphDao, times(3)).commit();
-        verify(janusGraphDao, times(1)).rollback();
-    }
-
-
-    @Test
-    public void upgradeAll() {
-        upgradeAllScenario(true);
-        assertEquals(MigrationResult.MigrationStatus.COMPLETED, migration.migrate().getMigrationStatus());
-        verify(janusGraphDao, times(4)).commit();
-        verify(janusGraphDao, times(0)).rollback();
-    }
-
-    @Test
-    public void upgradeAllWhenDeleteLockRetrySucceeded() {
-        when(componentsCleanBusinessLogic.lockDeleteOperation())
-                .thenReturn(StorageOperationStatus.FAILED_TO_LOCK_ELEMENT)
-                .thenReturn(StorageOperationStatus.OK);
-        upgradeAllScenario(true);
-        assertEquals(MigrationResult.MigrationStatus.COMPLETED, migration.migrate().getMigrationStatus());
-        verify(janusGraphDao, times(4)).commit();
-        verify(janusGraphDao, times(0)).rollback();
-    }
-
-    @Test
-    public void upgradeAllWhenVspUpgradeIsRequired() {
-        final boolean failOnVfUpgrade = false;
-        final boolean upgradeServices = true;
-        final boolean exceptionOnFvUpgrade = false;
-        final boolean upgradeVFC = true;
-        final boolean isFailed = true;
-        resolveUserAndDefineUpgradeLevel();
-        upgradeRules(failOnVfUpgrade, exceptionOnFvUpgrade, upgradeServices, upgradeVFC, isFailed);
-        configurationManager.getConfiguration().setSkipUpgradeVSPs(false);
-        assertEquals(MigrationResult.MigrationStatus.COMPLETED, migration.migrate().getMigrationStatus());
-    }
-
-    @Test
-    public void migrationFailedWhenUserNotResolved() {
-        when(userAdminOperation.getUserData(anyString(), eq(false))).thenReturn(Either.right(ActionStatus.MISSING_INFORMATION));
-        when(janusGraphDao.rollback()).thenReturn(JanusGraphOperationStatus.OK);
-        assertEquals(MigrationResult.MigrationStatus.FAILED, migration.migrate().getMigrationStatus());
-    }
-
-    @Test
-    public void verifyThatCheckedOutResourcesMarkedAsDeletedIfUpgradeFailed() {
-        mockCheckoutFlow();
-        when(resourceBusinessLogic.validateAndUpdateResourceFromCsar(any(Resource.class), any(), any(), any(),
-                any()))
-                .thenThrow(new ByResponseFormatComponentException(responseFormat));
-        when(resourceBusinessLogic.deleteResource(anyString(), any()))
-                .thenReturn(responseFormat);
-        mockChangeComponentState();
-        migration.upgradeVFs(vfList, false);
-        verify(resourceBusinessLogic).deleteResource(anyString(), any());
-    }
-
-    @Test
-    public void verifyThatCheckedOutAllottedResourcesMarkedAsDeletedIfUpgradeFailed() {
-        mockCheckoutFlow();
-        when(resourceBusinessLogic.validateAndUpdateResourceFromCsar(any(Resource.class), any(), any(), any(),
-                any()))
-                .thenThrow(new ByResponseFormatComponentException(responseFormat));
-        when(resourceBusinessLogic.deleteResource(anyString(), any()))
-                .thenReturn(responseFormat);
-        mockChangeComponentState();
-        migration.upgradeVFs(vfList, true);
-        verify(resourceBusinessLogic).deleteResource(anyString(), any());
-    }
-
-    @Test
-    public void verifyThatCheckedOutResourceIsNotMarkedAsDeletedIfUpgradeSucceeded() {
-        mockCheckoutFlow();
-        resource.setVersion(UPDATED_VERSION);
-        when(resourceBusinessLogic.validateAndUpdateResourceFromCsar(any(Resource.class), any(), any(), any(),
-                any()))
-                .thenReturn(resource);
-        mockChangeComponentState();
-        migration.upgradeVFs(vfList, true);
-        verify(resourceBusinessLogic, times(0)).deleteResource(anyString(), any());
-    }
-
-    @Test
-    public void verifyThatCheckedOutServicesMarkedAsDeletedIfUpgradeFailed() {
-        List<String> servicesForUpgrade = new ArrayList<>();
-        servicesForUpgrade.add(COMPONENT_UNIQUE_ID);
-
-        Either<Resource, StorageOperationStatus> foundServices = Either.left(resource);
-        mockCheckoutFlow();
-        when(toscaOperationFacade.getToscaElement(any(), any(ComponentParametersView.class)))
-                .thenReturn(Either.left(service));
-        when(toscaOperationFacade.getLatestCertifiedByToscaResourceName(any(), any(), any()))
-                .thenReturn(foundServices);
-        migration.upgradeServices(servicesForUpgrade, component -> true, "services");
-        verify(serviceBusinessLogic, times(0)).deleteService(anyString(), any());
-    }
-
-    @Test
-    public void verifyThatCheckedOutServicesIsNotMarkedAsDeletedIfUpgradeSucceeded() {
-        List<String> servicesForUpgrade = new ArrayList<>();
-        servicesForUpgrade.add(COMPONENT_UNIQUE_ID);
-
-        mockCheckoutFlow();
-        when(toscaOperationFacade.getLatestCertifiedByToscaResourceName(anyString(), any(VertexTypeEnum.class), any(JsonParseFlagEnum.class)))
-                .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND));
-        when(serviceBusinessLogic.deleteService(anyString(), any()))
-                .thenReturn(responseFormat);
-        migration.upgradeServices(servicesForUpgrade, component -> true, "services");
-        verify(serviceBusinessLogic).deleteService(anyString(), any());
-    }
-
-
-    @Test
-    public void unlockDeleteOperationIsPerformedIfItWasLocked() {
-        migration.isLockDeleteOperationSucceeded();
-        migration.unlockDeleteOperation();
-        verify(componentsCleanBusinessLogic).unlockDeleteOperation();
-    }
-
-    @Test
-    public void unlockDeleteOperationIsNotPerformedIfItWasNotLocked() {
-        when(componentsCleanBusinessLogic.lockDeleteOperation()).thenReturn(StorageOperationStatus.GENERAL_ERROR);
-        migration.isLockDeleteOperationSucceeded();
-        migration.unlockDeleteOperation();
-        verify(componentsCleanBusinessLogic, times(0)).unlockDeleteOperation();
-    }
-
-    @Test
-    public void deleteLockSucceededAfterRetry() {
-        when(componentsCleanBusinessLogic.lockDeleteOperation())
-                .thenReturn(StorageOperationStatus.FAILED_TO_LOCK_ELEMENT)
-                .thenReturn(StorageOperationStatus.FAILED_TO_LOCK_ELEMENT)
-                .thenReturn(StorageOperationStatus.FAILED_TO_LOCK_ELEMENT)
-                .thenReturn(StorageOperationStatus.OK);
-        migration.isLockDeleteOperationSucceeded();
-        migration.unlockDeleteOperation();
-        verify(componentsCleanBusinessLogic).unlockDeleteOperation();
-    }
-
-    @Test
-    public void deleteLockFailedAfterRetry() {
-        when(componentsCleanBusinessLogic.lockDeleteOperation())
-                .thenReturn(StorageOperationStatus.FAILED_TO_LOCK_ELEMENT);
-        migration.isLockDeleteOperationSucceeded();
-        migration.unlockDeleteOperation();
-        verify(componentsCleanBusinessLogic, times(0)).unlockDeleteOperation();
-    }
-
-    @Test
-    public void deleteMarkedResourcesWhenLimitIsReached() {
-        ArrayList<NodeTypeEnum> componentsToClean = new ArrayList<>();
-        componentsToClean.add(NodeTypeEnum.Resource);
-        migration.setUser(user);
-        migration.setMarkedAsDeletedResourcesCnt(5);
-        migration.deleteResourcesIfLimitIsReached();
-        verify(componentsCleanBusinessLogic).cleanComponents(componentsToClean, true);
-    }
-
-    @Test
-    public void deleteMarkedResourcesNotCalledWhenLimitIsNotReached() {
-        ArrayList<NodeTypeEnum> componentsToClean = new ArrayList<>();
-        componentsToClean.add(NodeTypeEnum.Resource);
-        migration.setUser(user);
-        migration.setMarkedAsDeletedResourcesCnt(3);
-        migration.deleteResourcesIfLimitIsReached();
-        verify(componentsCleanBusinessLogic, times(0)).cleanComponents(componentsToClean, true);
-    }
-
-    @Test
-    public void deleteMarkedServicesWhenLimitIsReached() {
-        ArrayList<NodeTypeEnum> componentsToClean = new ArrayList<>();
-        componentsToClean.add(NodeTypeEnum.Service);
-        migration.setUser(user);
-        migration.setMarkedAsDeletedServicesCnt(5);
-        migration.deleteServicesIfLimitIsReached();
-        verify(componentsCleanBusinessLogic).cleanComponents(componentsToClean, true);
-    }
-
-    @Test
-    public void deleteMarkedServicesNotCalledWhenLimitIsNotReached() {
-        ArrayList<NodeTypeEnum> componentsToClean = new ArrayList<>();
-        componentsToClean.add(NodeTypeEnum.Service);
-        migration.setUser(user);
-        migration.setMarkedAsDeletedServicesCnt(2);
-        migration.deleteServicesIfLimitIsReached();
-        verify(componentsCleanBusinessLogic, times(0)).cleanComponents(componentsToClean, true);
-    }
-
-    @Test
-    public void getVfUpgradeStatusWhenUpgradeFailedAndItIsInstance() {
-        assertEquals(UpgradeMigration1710.UpgradeStatus.NOT_UPGRADED, migration.getVfUpgradeStatus(false, true));
-    }
-
-    @Test
-    public void getVfUpgradeStatusWhenUpgradeFailedAndItIsNotInstance() {
-        assertEquals(UpgradeMigration1710.UpgradeStatus.NOT_UPGRADED, migration.getVfUpgradeStatus(false, false));
-    }
-
-    @Test
-    public void getVfUpgradeStatusWhenUpgradeSucceededAndItIsInstance() {
-        assertEquals(UpgradeMigration1710.UpgradeStatus.UPGRADED_AS_INSTANCE, migration.getVfUpgradeStatus(true, true));
-    }
-
-    @Test
-    public void getVfUpgradeStatusWhenUpgradeSucceededAndItIsNotInstance() {
-        assertEquals(UpgradeMigration1710.UpgradeStatus.UPGRADED, migration.getVfUpgradeStatus(true, false));
-    }
-
-    private void resolveUserAndDefineUpgradeLevel() {
-        when(userAdminOperation.getUserData(anyString(), eq(false))).thenReturn(Either.left(user));
-        configurationManager.getConfiguration().setToscaConformanceLevel(CONF_LEVEL);
-        configurationManager.getConfiguration().setResourcesForUpgrade(resourcesForUpgrade);
-    }
-
-    private void upgradeAllScenario(boolean upgradeServices) {
-        final boolean failOnVfUpgrade = false;
-        final boolean exceptionOnFvUpgrade = false;
-        final boolean upgradeVFC = false;
-        final boolean isFailed = false;
-        final boolean isProxy = true;
-
-        resolveUserAndDefineUpgradeLevel();
-        mockCheckoutFlow();
-        when(resourceBusinessLogic.validateAndUpdateResourceFromCsar(any(Resource.class), any(), any(), any(),
-                any()))
-                .thenReturn(resource);
-        upgradeRules(failOnVfUpgrade, exceptionOnFvUpgrade, upgradeServices, upgradeVFC, isFailed, isProxy);
-    }
-
-    private void upgradeRules(boolean failedVfUpgrade, boolean exceptionOnVfUpgrade, boolean upgradeService,
-                              boolean upgradeVFCs, boolean isFailed) {
-        upgradeRules(failedVfUpgrade, exceptionOnVfUpgrade, upgradeService, upgradeVFCs, isFailed, false);
-    }
-
-    private void upgradeRules(boolean failedVfUpgrade, boolean exceptionOnVfUpgrade, boolean upgradeService,
-                              boolean upgradeVFCs, boolean isFailed, boolean isProxy) {
-
-        mockNodeTypesUpgrade();
-        Either<Component, StorageOperationStatus> foundResource = Either.left(resource);
-
-        if (failedVfUpgrade) {
-            getToscaElementMockForVfUpgradeFailedScenario(foundResource);
-        } else {
-            if (exceptionOnVfUpgrade) {
-                getToscaElementMockForExceptionOnUpgradeScenario(foundResource, upgradeService);
-            } else {
-                when(toscaOperationFacade.getToscaElement(anyString()))
-                        .thenReturn(foundResource);
-            }
-        }
-        //happy flow
-        if (upgradeService) {
-            mockForUpgradeServiceScenario(foundResource, upgradeVFCs, isFailed);
-        }
-    }
-
-    private void mockNodeTypesUpgrade() {
-        GraphVertex component = createComponent();
-        List<GraphVertex> components = Lists.newArrayList();
-        components.add(component);
-
-        when(janusGraphDao.getByCriteria(any(), any(), any(), any()))
-                .thenReturn(Either.left(components));
-        when(janusGraphDao.getParentVertices(any(GraphVertex.class), any(EdgeLabelEnum.class), any(JsonParseFlagEnum.class)))
-                //1th node to upgrade
-                .thenReturn(Either.left(components))
-                //parent of the 1th node - stop recursion
-                .thenReturn(Either.right(JanusGraphOperationStatus.NOT_FOUND));
-    }
-
-    private GraphVertex createComponent() {
-        GraphVertex component = new GraphVertex();
-        component.setJsonMetadataField(JsonPresentationFields.LIFECYCLE_STATE,LifecycleStateEnum.CERTIFIED.name());
-        component.setJsonMetadataField(JsonPresentationFields.UNIQUE_ID,COMPONENT_UNIQUE_ID);
-        component.setJsonMetadataField(JsonPresentationFields.CI_COMPONENT_VERSION,UPDATED_VERSION);
-        return component;
-    }
-
-    private void mockChangeComponentState() {
-        List<ComponentInstance> instances = Lists.newArrayList();
-        instances.add(createComponentInstance());
-
-        Resource checkedOutResource = new Resource();
-        checkedOutResource.setUniqueId("123400");
-        checkedOutResource.setComponentInstances(instances);
-        Either<Resource, ResponseFormat> fromLifeCycle = Either.left(checkedOutResource);
-        doReturn(fromLifeCycle).when(lifecycleBusinessLogic)
-                .changeComponentState(any(), any(), any(), any(), any(),eq(true), eq(false));
-    }
-
-    private void getToscaElementMockForVfUpgradeFailedScenario(Either<Component, StorageOperationStatus> foundResource) {
-        when(toscaOperationFacade.getToscaElement(anyString()))
-                .thenReturn(foundResource)
-                .thenReturn(foundResource)
-                .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND));
-    }
-
-    private void mockForUpgradeServiceScenario(Either<Component, StorageOperationStatus> foundResource, boolean upgradeVFC, boolean isFailed) {
-        Either<Resource, StorageOperationStatus> foundService = Either.left(resource);
-        if (upgradeVFC) {
-            when(toscaOperationFacade.getToscaElement(anyString()))
-                    .thenReturn(foundResource)
-                    .thenReturn(foundResource)
-                    .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND));
-        }
-        else if (!isFailed) {
-            when(toscaOperationFacade.getToscaElement(any(), any(ComponentParametersView.class)))
-                    .thenReturn(Either.left(resource));
-            when(toscaOperationFacade.getLatestCertifiedByToscaResourceName(any(), any(), any()))
-                    .thenReturn(foundService);
-        }
-    }
-
-    private void getToscaElementMockForExceptionOnUpgradeScenario(Either<Component, StorageOperationStatus> foundResource, boolean upgradeService) {
-        if (upgradeService) {
-            service.setVersion(UPDATED_VERSION);
-            Either<Component, StorageOperationStatus> foundService = Either.left(service);
-            when(toscaOperationFacade.getToscaElement(anyString()))
-                    .thenReturn(foundResource)
-                    .thenReturn(foundResource)
-                    .thenThrow(new RuntimeException())
-                    .thenReturn(foundService);
-        }
-        else {
-            when(toscaOperationFacade.getToscaElement(anyString()))
-                    .thenReturn(foundResource)
-                    .thenReturn(foundResource)
-                    .thenThrow(new RuntimeException());
-        }
-    }
-
-    private void mockCheckoutFlow() {
-        GraphVertex component = new GraphVertex();
-        component.setJsonMetadataField(JsonPresentationFields.LIFECYCLE_STATE, LifecycleStateEnum.CERTIFIED.name());
-        component.setJsonMetadataField(JsonPresentationFields.UNIQUE_ID, COMPONENT_UNIQUE_ID);
-        List<GraphVertex> components = Lists.newArrayList();
-        components.add(component);
-
-        when(toscaOperationFacade.getToscaElement(anyString())).thenReturn(Either.left(resource));
-        when(janusGraphDao.getByCriteria(any(), any(), any(), any()))
-                .thenReturn(Either.left(components));
-        when(csarOperation.getCsarLatestVersion(anyString(), any()))
-                .thenReturn(Either.left("2.0"));
-    }
-
-    private ComponentInstance createComponentInstance() {
-        ComponentInstance instance = new ComponentInstance();
-        instance.setIcon("");
-        instance.setUniqueId("");
-        instance.setName("");
-        instance.setComponentUid("");
-        instance.setCreationTime(1L);
-        instance.setModificationTime(2L);
-        instance.setDescription("");
-        instance.setPosX("");
-        instance.setPosY("");
-        instance.setPropertyValueCounter(1);
-        instance.setNormalizedName("");
-        instance.setOriginType(OriginTypeEnum.CVFC);
-        instance.setCustomizationUUID("");
-        instance.setComponentName("");
-        instance.setComponentVersion(OLD_VERSION);
-        instance.setToscaComponentName("");
-        instance.setInvariantName("");
-        instance.setSourceModelInvariant("");
-        instance.setSourceModelName("");
-        instance.setSourceModelUuid("");
-        instance.setSourceModelUid("");
-        instance.setIsProxy(false);
-        return instance;
-    }
-
-
-}
diff --git a/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/tasks/mig1902/SdcGroupsMigrationTest.java b/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/tasks/mig1902/SdcGroupsMigrationTest.java
deleted file mode 100644
index 328c5f3..0000000
--- a/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/tasks/mig1902/SdcGroupsMigrationTest.java
+++ /dev/null
@@ -1,231 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-package org.openecomp.sdc.asdctool.migration.tasks.mig1902;
-
-import fj.data.Either;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnitRunner;
-import org.openecomp.sdc.asdctool.migration.core.task.MigrationResult;
-import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
-import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
-import org.openecomp.sdc.be.dao.jsongraph.JanusGraphDao;
-import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum;
-import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
-import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum;
-import org.openecomp.sdc.be.datatypes.elements.GroupDataDefinition;
-import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
-import org.openecomp.sdc.be.model.GroupTypeDefinition;
-import org.openecomp.sdc.be.model.PropertyDefinition;
-import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
-import org.openecomp.sdc.be.model.operations.impl.GroupTypeOperation;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyMap;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-@RunWith(MockitoJUnitRunner.class)
-public class SdcGroupsMigrationTest {
-
-    @Mock
-    private JanusGraphDao janusGraphDao;
-    @Mock
-    private GroupTypeOperation groupTypeOperation;
-    @Mock
-    private GraphVertex topologyTemplateVertex;
-    @Mock
-    private GraphVertex groupsVertex;
-
-    @InjectMocks
-    private SdcGroupsMigration groupsMigration;
-
-    @Before
-    public void setUp() {
-        groupsMigration = new SdcGroupsMigration(janusGraphDao, groupTypeOperation);
-        when(janusGraphDao.getVertexById(any())).thenReturn(Either.left(topologyTemplateVertex));
-    }
-
-    @Test
-    public void handleOneContainerWhenErrorHappened() {
-        when(janusGraphDao.getChildVertex(any(GraphVertex.class), eq(EdgeLabelEnum.GROUPS), eq(JsonParseFlagEnum.ParseAll)))
-                .thenReturn(Either.right(JanusGraphOperationStatus.MATCH_NOT_FOUND));
-        StorageOperationStatus status = groupsMigration.handleOneContainer(topologyTemplateVertex);
-        assertEquals(StorageOperationStatus.MATCH_NOT_FOUND, status);
-    }
-
-    @Test
-    public void handleOneContainerWhenNoGroups() {
-        when(janusGraphDao.getChildVertex(any(GraphVertex.class), eq(EdgeLabelEnum.GROUPS), eq(JsonParseFlagEnum.ParseAll)))
-                .thenReturn(Either.right(JanusGraphOperationStatus.NOT_FOUND));
-        StorageOperationStatus status = groupsMigration.handleOneContainer(topologyTemplateVertex);
-        assertEquals(StorageOperationStatus.OK, status);
-    }
-
-    @Test
-    public void handleOneContainerWhenGroupsShouldNotBeUpdated() {
-        when(janusGraphDao.getChildVertex(any(GraphVertex.class), eq(EdgeLabelEnum.GROUPS), eq(JsonParseFlagEnum.ParseAll)))
-                .thenReturn(Either.left(groupsVertex));
-
-        doReturn(buildGroupInstancesMap(new String[] {"org.openecomp.groups.heat.HeatStack", "org.openecomp.groups.VfModule"}, new String[]{}))
-                .when(groupsVertex).getJson();
-        StorageOperationStatus status = groupsMigration.handleOneContainer(topologyTemplateVertex);
-        assertEquals(StorageOperationStatus.OK, status);
-        verify(janusGraphDao, times(0)).commit();
-
-    }
-
-    @Test
-    public void handleOneContainerWhenGroupsShouldBeUpdated() {
-        mockLatestGroupMapCreating();
-        mockUpgradeHappyFlow();
-        StorageOperationStatus status = groupsMigration.handleOneContainer(topologyTemplateVertex);
-        assertEquals(StorageOperationStatus.OK, status);
-        verify(janusGraphDao, times(1)).commit();
-        verify(janusGraphDao, times(0)).rollback();
-    }
-
-    private void mockUpgradeHappyFlow() {
-        when(janusGraphDao.getChildVertex(any(GraphVertex.class), eq(EdgeLabelEnum.GROUPS), eq(JsonParseFlagEnum.ParseAll)))
-                .thenReturn(Either.left(groupsVertex));
-        when(janusGraphDao.updateVertex(any(GraphVertex.class))).thenReturn(Either.left(groupsVertex));
-        when(janusGraphDao.commit()).thenReturn(JanusGraphOperationStatus.OK);
-        doReturn(buildGroupInstancesMap(new String[] {"org.openecomp.groups.NetworkCollection", "org.openecomp.groups.VfcInstanceGroup"},
-                new String[] {"old1", "old2"}))
-                .when(groupsVertex).getJson();
-    }
-
-    @Test
-    public void handleOneContainerWhenGroupsAlreadyUpdated() {
-        mockLatestGroupMapCreating();
-        when(janusGraphDao.getChildVertex(any(GraphVertex.class), eq(EdgeLabelEnum.GROUPS), eq(JsonParseFlagEnum.ParseAll)))
-                .thenReturn(Either.left(groupsVertex));
-        doReturn(buildGroupInstancesMap(new String[] {"org.openecomp.groups.NetworkCollection"},
-                new String[] {"a", "b", "c", "d"}))
-                .when(groupsVertex).getJson();
-        StorageOperationStatus status = groupsMigration.handleOneContainer(topologyTemplateVertex);
-        assertEquals(StorageOperationStatus.OK, status);
-        verify(janusGraphDao, times(0)).commit();
-        verify(janusGraphDao, times(1)).rollback();
-    }
-
-    @Test
-    public void handleOneContainerWhenExceptionIsThrown() {
-        when(janusGraphDao.getChildVertex(any(GraphVertex.class), eq(EdgeLabelEnum.GROUPS), eq(JsonParseFlagEnum.ParseAll)))
-                .thenThrow(new RuntimeException());
-        StorageOperationStatus status = groupsMigration.handleOneContainer(topologyTemplateVertex);
-        assertEquals(StorageOperationStatus.GENERAL_ERROR, status);
-        verify(janusGraphDao, times(0)).commit();
-        verify(janusGraphDao, times(1)).rollback();
-
-    }
-
-    // A temp remark for this test - following Commit hash:    08595ad21b0c409c69e3902232f5575963199e3e [ASDC-641] – Migration workaround for deployment artifact timeout. Reviewer: Lior.
-//    @Test
-//    public void migrateWhenExceptionIsThrown() {
-//        List<GraphVertex> vertexList = new ArrayList<>();
-//        vertexList.add(topologyTemplateVertex);
-//        mockLatestGroupMapCreating();
-//        when(janusGraphDao.getByCriteria(eq(VertexTypeEnum.TOPOLOGY_TEMPLATE), eq(null), anyMap(), eq(JsonParseFlagEnum.ParseAll)))
-//                .thenReturn(Either.left(vertexList));
-//        when(janusGraphDao.getChildVertex(any(GraphVertex.class), eq(EdgeLabelEnum.GROUPS), eq(JsonParseFlagEnum.ParseAll)))
-//                .thenThrow(new RuntimeException());
-//        assertEquals(MigrationResult.MigrationStatus.FAILED, groupsMigration.migrate().getMigrationStatus());
-//        verify(janusGraphDao, times(0)).commit();
-//        verify(janusGraphDao, times(1)).rollback();
-//
-//    }
-
-    @Test
-    public void migrateWhenGroupsShouldBeUpdated() {
-        List<GraphVertex> vertexList = new ArrayList<>();
-        vertexList.add(topologyTemplateVertex);
-        mockLatestGroupMapCreating();
-        when(janusGraphDao.getByCriteria(eq(VertexTypeEnum.TOPOLOGY_TEMPLATE), eq(null), anyMap(), eq(JsonParseFlagEnum.ParseAll)))
-                .thenReturn(Either.left(vertexList));
-        mockUpgradeHappyFlow();
-
-        assertEquals(MigrationResult.MigrationStatus.COMPLETED, groupsMigration.migrate().getMigrationStatus());
-        verify(janusGraphDao, times(1)).commit();
-        verify(janusGraphDao, times(0)).rollback();
-    }
-
-
-    private Map<String, GroupDataDefinition> buildGroupInstancesMap(String[] groupTypes, String [] propertyNames) {
-        Map<String, GroupDataDefinition> groupsMap = new HashMap<>();
-        for (String type: groupTypes) {
-            GroupDataDefinition gr = new GroupDataDefinition();
-            gr.setType(type);
-
-            gr.setProperties(createInstanceProperties(propertyNames));
-            groupsMap.put(gr.getType(), gr);
-        }
-        return groupsMap;
-    }
-
-    private void mockLatestGroupMapCreating() {
-        doReturn(Either.left(createTypeDefinition(new String[] {"a", "b", "c", "d"})))
-                .when(groupTypeOperation).getLatestGroupTypeByType(eq(SdcGroupsMigration.GroupsForUpgrade.NW_COLLECTION_GROUP_NAME.getToscaType()), eq(false));
-        doReturn(Either.left(createTypeDefinition(new String[] {"l", "m", "n", "o", "p"})))
-                .when(groupTypeOperation).getLatestGroupTypeByType(eq(SdcGroupsMigration.GroupsForUpgrade.VFC_INSTANCE_GROUP_NAME.getToscaType()), eq(false));
-        groupsMigration.loadLatestGroupTypeDefinitions();
-
-    }
-
-    private GroupTypeDefinition createTypeDefinition(String[] propertyNames) {
-        GroupTypeDefinition typeDefinition = new GroupTypeDefinition();
-        typeDefinition.setProperties(createTypeProperties(propertyNames));
-        return typeDefinition;
-    }
-
-    private List<PropertyDefinition> createTypeProperties(String[] propertyNames) {
-        List<PropertyDefinition> propertyDefinitionList = new ArrayList<>();
-        for (String name: propertyNames) {
-            PropertyDefinition propertyDefinition = new PropertyDefinition();
-            propertyDefinition.setName(name);
-            propertyDefinitionList.add(propertyDefinition);
-        }
-        return propertyDefinitionList;
-    }
-
-    private List<PropertyDataDefinition> createInstanceProperties(String[] propertyNames) {
-        List<PropertyDataDefinition> propertyDefinitionList = new ArrayList<>();
-        for (String name: propertyNames) {
-            PropertyDefinition propertyDefinition = new PropertyDefinition();
-            propertyDefinition.setName(name);
-            propertyDefinitionList.add(propertyDefinition);
-        }
-        return propertyDefinitionList;
-    }
-
-}
diff --git a/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/tasks/mig1902/SdcResourceIconMigrationTest.java b/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/tasks/mig1902/SdcResourceIconMigrationTest.java
deleted file mode 100644
index f54592d..0000000
--- a/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/tasks/mig1902/SdcResourceIconMigrationTest.java
+++ /dev/null
@@ -1,212 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-package org.openecomp.sdc.asdctool.migration.tasks.mig1902;
-
-import fj.data.Either;
-import org.assertj.core.util.Lists;
-import org.assertj.core.util.Maps;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnitRunner;
-import org.openecomp.sdc.asdctool.migration.core.task.MigrationResult;
-import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
-import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
-import org.openecomp.sdc.be.dao.jsongraph.JanusGraphDao;
-import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
-import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum;
-import org.openecomp.sdc.be.datatypes.elements.ComponentInstanceDataDefinition;
-import org.openecomp.sdc.be.datatypes.elements.CompositionDataDefinition;
-import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
-import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
-import org.openecomp.sdc.be.model.jsonjanusgraph.enums.JsonConstantKeysEnum;
-
-import java.util.HashMap;
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.anyMap;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-@RunWith(MockitoJUnitRunner.class)
-public class SdcResourceIconMigrationTest {
-    @Mock
-    private JanusGraphDao janusGraphDao;
-
-    @Mock
-    private GraphVertex graphVertex;
-
-    @Mock
-    private GraphVertex topologyTemplateVertex;
-
-    @Mock
-    private CompositionDataDefinition compositionDataDefinition;
-
-    @Mock
-    private ComponentInstanceDataDefinition  componentInstanceDataDefinition;
-
-    @InjectMocks
-    private SdcResourceIconMigration iconMigration;
-
-    @Before
-    public void setUp() {
-        iconMigration = new SdcResourceIconMigration(janusGraphDao);
-        when(janusGraphDao.getVertexById(any())).thenReturn(Either.left(topologyTemplateVertex));
-        when(janusGraphDao.commit()).thenReturn(JanusGraphOperationStatus.OK);
-    }
-
-
-    @Test
-    public void migrationFailedWhenNoNodeTypeDefined() {
-        when(janusGraphDao.getByCriteria(eq(VertexTypeEnum.NODE_TYPE), anyMap(), anyMap(), eq(JsonParseFlagEnum.ParseAll)))
-                .thenReturn(Either.left(Lists.emptyList()));
-        assertEquals(MigrationResult.MigrationStatus.FAILED, iconMigration.migrate().getMigrationStatus());
-    }
-
-    @Test
-    public void resourceIsNotUpdatedIfNotVL() {
-        //iconMigration.handleOneContainer(graphVertex);
-        mockInstancesNotFoundFlow();
-
-        iconMigration.updateNodeTypeIconAndStoreInMap(ResourceTypeEnum.VL);
-        assertFalse(iconMigration.updateIconInsideInstance(componentInstanceDataDefinition));
-    }
-
-
-
-    @Test
-    public void resourceIsUpdatedIfCP() {
-        //iconMigration.handleOneContainer(graphVertex);
-        mockInstancesFoundFlow();
-        when(janusGraphDao.updateVertex(any(GraphVertex.class))).thenReturn(Either.left(graphVertex));
-        iconMigration.updateNodeTypeIconAndStoreInMap(ResourceTypeEnum.CP);
-        assertTrue(iconMigration.updateIconInsideInstance(componentInstanceDataDefinition));
-    }
-
-    @Test
-    public void migrateWhenIconsAreUpdated() {
-        mockInstancesFoundFlow();
-        when(janusGraphDao.getByCriteria(eq(VertexTypeEnum.TOPOLOGY_TEMPLATE), eq(null), anyMap(), eq(JsonParseFlagEnum.ParseAll)))
-                .thenReturn(Either.left(Lists.newArrayList(topologyTemplateVertex)));
-        when(compositionDataDefinition.getComponentInstances()).thenReturn(Maps.newHashMap("a", componentInstanceDataDefinition));
-        doReturn(Maps.newHashMap(JsonConstantKeysEnum.COMPOSITION.getValue(), compositionDataDefinition)).when(topologyTemplateVertex).getJson();
-        when(janusGraphDao.updateVertex(any(GraphVertex.class))).thenReturn(Either.left(graphVertex));
-
-        assertEquals(MigrationResult.MigrationStatus.COMPLETED, iconMigration.migrate().getMigrationStatus());
-        verify(janusGraphDao, times(3)).commit();
-    }
-
-    @Test
-    public void migrateWhenIconsNotUpdated() {
-        mockInstancesNotFoundFlow();
-        when(janusGraphDao.getByCriteria(eq(VertexTypeEnum.TOPOLOGY_TEMPLATE), eq(null), anyMap(), eq(JsonParseFlagEnum.ParseAll)))
-                .thenReturn(Either.left(Lists.newArrayList(topologyTemplateVertex)));
-        when(compositionDataDefinition.getComponentInstances()).thenReturn(Maps.newHashMap("a", componentInstanceDataDefinition));
-        doReturn(Maps.newHashMap(JsonConstantKeysEnum.COMPOSITION.getValue(), compositionDataDefinition)).when(topologyTemplateVertex).getJson();
-
-        assertEquals(MigrationResult.MigrationStatus.COMPLETED, iconMigration.migrate().getMigrationStatus());
-        verify(janusGraphDao, times(2)).commit();
-    }
-
-    @Test
-    public void migrateWhenNoInstancesFound() {
-        mockInstancesNotFoundFlow();
-        when(janusGraphDao.getByCriteria(eq(VertexTypeEnum.TOPOLOGY_TEMPLATE), eq(null), anyMap(), eq(JsonParseFlagEnum.ParseAll)))
-                .thenReturn(Either.left(Lists.newArrayList(topologyTemplateVertex)));
-
-        assertEquals(MigrationResult.MigrationStatus.COMPLETED, iconMigration.migrate().getMigrationStatus());
-        verify(janusGraphDao, times(2)).commit();
-    }
-
-    @Test
-    public void migrationFailedWhenInstanceVertexUpdateFailed() {
-        mockInstancesFoundFlow();
-        when(janusGraphDao.getByCriteria(eq(VertexTypeEnum.TOPOLOGY_TEMPLATE), eq(null), anyMap(), eq(JsonParseFlagEnum.ParseAll)))
-                .thenReturn(Either.left(Lists.newArrayList(topologyTemplateVertex)));
-        when(compositionDataDefinition.getComponentInstances()).thenReturn(Maps.newHashMap("a", componentInstanceDataDefinition));
-        doReturn(Maps.newHashMap(JsonConstantKeysEnum.COMPOSITION.getValue(), compositionDataDefinition)).when(topologyTemplateVertex).getJson();
-        when(janusGraphDao.updateVertex(any(GraphVertex.class))).thenReturn(Either.left(graphVertex))
-                .thenReturn(Either.left(graphVertex))
-                .thenReturn(Either.right(JanusGraphOperationStatus.GENERAL_ERROR));
-
-        assertEquals(MigrationResult.MigrationStatus.COMPLETED, iconMigration.migrate().getMigrationStatus());
-        verify(janusGraphDao, times(2)).commit();
-    }
-
-    @Test
-    public void migrationCompletedWhenVertexJsonIsEmpty() {
-        mockInstancesFoundFlow();
-        when(janusGraphDao.getByCriteria(eq(VertexTypeEnum.TOPOLOGY_TEMPLATE), eq(null), anyMap(), eq(JsonParseFlagEnum.ParseAll)))
-                .thenReturn(Either.left(Lists.newArrayList(topologyTemplateVertex)));
-        doReturn(new HashMap<>()).when(topologyTemplateVertex).getJson();
-        when(janusGraphDao.updateVertex(any(GraphVertex.class))).thenReturn(Either.left(graphVertex));
-
-        assertEquals(MigrationResult.MigrationStatus.COMPLETED, iconMigration.migrate().getMigrationStatus());
-        verify(janusGraphDao, times(2)).commit();
-    }
-
-    @Test
-    public void migrationCompletedWhenVertexJsonIsNull() {
-        mockInstancesFoundFlow();
-        when(janusGraphDao.getByCriteria(eq(VertexTypeEnum.TOPOLOGY_TEMPLATE), eq(null), anyMap(), eq(JsonParseFlagEnum.ParseAll)))
-                .thenReturn(Either.left(Lists.newArrayList(topologyTemplateVertex)));
-        doReturn(null).when(topologyTemplateVertex).getJson();
-        when(janusGraphDao.updateVertex(any(GraphVertex.class))).thenReturn(Either.left(graphVertex));
-
-        assertEquals(MigrationResult.MigrationStatus.COMPLETED, iconMigration.migrate().getMigrationStatus());
-        verify(janusGraphDao, times(2)).commit();
-    }
-
-    @Test
-    public void migrationFailedWhenTypeUpdateFailed() {
-        mockInstancesFoundFlow();
-        when(janusGraphDao.updateVertex(any(GraphVertex.class))).thenReturn(Either.right(JanusGraphOperationStatus.GENERAL_ERROR));
-        assertEquals(MigrationResult.MigrationStatus.FAILED, iconMigration.migrate().getMigrationStatus());
-        verify(janusGraphDao, times(0)).commit();
-    }
-
-    private void mockInstancesNotFoundFlow() {
-        List<GraphVertex> nodeTypeVertexList = Lists.newArrayList(graphVertex);
-        when(graphVertex.getMetadataProperty(GraphPropertyEnum.NAME)).thenReturn("vl1");
-        when(componentInstanceDataDefinition.getComponentName()).thenReturn("other");
-        when(janusGraphDao.getByCriteria(eq(VertexTypeEnum.NODE_TYPE), anyMap(), anyMap(), eq(JsonParseFlagEnum.ParseAll)))
-                .thenReturn(Either.left(nodeTypeVertexList));
-        when(janusGraphDao.updateVertex(any(GraphVertex.class))).thenReturn(Either.left(graphVertex));
-    }
-
-    private void mockInstancesFoundFlow() {
-        when(graphVertex.getMetadataProperty(GraphPropertyEnum.NAME)).thenReturn(String.valueOf("cp1"));
-        when(componentInstanceDataDefinition.getComponentName()).thenReturn("cp1");
-        when(janusGraphDao.getByCriteria(eq(VertexTypeEnum.NODE_TYPE), anyMap(), anyMap(), eq(JsonParseFlagEnum.ParseAll)))
-                .thenReturn(Either.left(Lists.newArrayList(graphVertex)));
-    }
-
-
-}
