aboutsummaryrefslogtreecommitdiffstats
path: root/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/tasks/mig1802/SdcCatalogMigration.java
blob: d520eee1b803531a887e4f0ac66058ad02fa7d44 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package org.openecomp.sdc.asdctool.migration.tasks.mig1802;

import fj.data.Either;
import org.apache.commons.collections.ListUtils;
import org.apache.tinkerpop.gremlin.structure.Direction;
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.be.dao.jsongraph.GraphVertex;
import org.openecomp.sdc.be.dao.jsongraph.TitanDao;
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.dao.jsongraph.utils.IdBuilderUtils;
import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
import org.openecomp.sdc.be.model.jsontitan.operations.TopologyTemplateOperation;
import org.openecomp.sdc.be.model.jsontitan.operations.ToscaElementOperation;
import org.openecomp.sdc.common.log.wrappers.Logger;
import org.springframework.stereotype.Component;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Component
public class SdcCatalogMigration implements Migration {
    private static final Logger LOGGER = Logger.getLogger(SdcCatalogMigration.class);
    private static final List<ResourceTypeEnum> EXCLUDE_TYPES = Arrays.asList(ResourceTypeEnum.VFCMT, ResourceTypeEnum.Configuration);

    private ToscaElementOperation toscaElementOperation;
    private TitanDao titanDao;

    public SdcCatalogMigration(TopologyTemplateOperation toscaElementOperation, TitanDao titanDao) {
        this.toscaElementOperation = toscaElementOperation;
        this.titanDao = titanDao;
    }

    @Override
    public String description() {
        return "optimize sdc catalog vertices";
    }

    @Override
    public DBVersion getVersion() {
        return DBVersion.from(BigInteger.valueOf(1802), BigInteger.valueOf(0));
    }

    @Override
    public MigrationResult migrate() {
        TitanOperationStatus status = null;
        try {
            status = getOrCreateCatalogRoot()
                    .either(this::associateCatalogRootToCatalogElements,
                            err -> {LOGGER.error("failed to create catalog root. err: {}", err); return err;});
            return status == TitanOperationStatus.OK ? MigrationResult.success() : MigrationResult.error("failed to create and associate catalog root. error: " + status);
        } finally {
            commitOrRollBack(status);
        }
    }

    private void commitOrRollBack(TitanOperationStatus status) {
        if (status == TitanOperationStatus.OK) {
            titanDao.commit();
        } else {
            titanDao.rollback();
        }
    }

    private Either<GraphVertex, TitanOperationStatus> getOrCreateCatalogRoot() {
        LOGGER.info("creating or getting catalog root vertex");
        return titanDao.getVertexByLabel(VertexTypeEnum.CATALOG_ROOT)
                .right()
                .bind(this::createRootCatalogVertexOrError);
    }


    private Either<GraphVertex, TitanOperationStatus> createRootCatalogVertexOrError(TitanOperationStatus titanOperationStatus) {
        return titanOperationStatus == TitanOperationStatus.NOT_FOUND ? createRootCatalogVertex() : Either.right(titanOperationStatus);
    }

    private Either<GraphVertex, TitanOperationStatus> createRootCatalogVertex() {
        LOGGER.info("Creating root catalog vertex");
        GraphVertex catalogRootVertex = new GraphVertex(VertexTypeEnum.CATALOG_ROOT);
        catalogRootVertex.setUniqueId(IdBuilderUtils.generateUniqueId());
        return titanDao.createVertex(catalogRootVertex);
    }

    private Either<List<GraphVertex>, TitanOperationStatus> getAllCatalogVertices() {
        LOGGER.info("fetching all catalog resources");
        return toscaElementOperation.getListOfHighestComponents(ComponentTypeEnum.RESOURCE, EXCLUDE_TYPES, JsonParseFlagEnum.ParseMetadata)
                .right()
                .bind(this::errOrEmptyListIfNotFound)
                .left()
                .bind(this::getAllCatalogVertices);
    }

    private Either<List<GraphVertex>, TitanOperationStatus> errOrEmptyListIfNotFound(TitanOperationStatus err) {
        return TitanOperationStatus.NOT_FOUND.equals(err) ? Either.left(new ArrayList<>()) : Either.right(err);
    }

    @SuppressWarnings("unchecked")
    private Either<List<GraphVertex>, TitanOperationStatus> getAllCatalogVertices(List<GraphVertex> allResourceCatalogVertices) {
        LOGGER.info("number of resources: {}", allResourceCatalogVertices.size());
        LOGGER.info("fetching all catalog services");
        return toscaElementOperation.getListOfHighestComponents(ComponentTypeEnum.SERVICE, EXCLUDE_TYPES, JsonParseFlagEnum.ParseMetadata)
                .right()
                .bind(this::errOrEmptyListIfNotFound)
                .left()
                .map(allServiceVertices -> ListUtils.union(allServiceVertices, allResourceCatalogVertices));
    }

    private TitanOperationStatus associateCatalogRootToCatalogElements(GraphVertex root) {
        return getAllCatalogVertices()
                .either(catalogVertices -> associateCatalogRootToCatalogElements(root, catalogVertices),
                        err -> err);
    }

    private TitanOperationStatus associateCatalogRootToCatalogElements(GraphVertex root, List<GraphVertex> catalogElements) {
        LOGGER.info("number of catalog elements: {}", catalogElements.size());
        LOGGER.info("connect all catalog elements to root edge");
        List<GraphVertex> nonConnectedElements = catalogElements.stream().filter(this::edgeNotAlreadyExists).collect(Collectors.toList());
        int numOfCreatedEdges = 0;
        for (GraphVertex catalogElement : nonConnectedElements) {
                TitanOperationStatus edgeCreationStatus = titanDao.createEdge(root, catalogElement, EdgeLabelEnum.CATALOG_ELEMENT, null);
                if (edgeCreationStatus != TitanOperationStatus.OK) {
                    LOGGER.error("failed to create edge from catalog element to vertex {}", catalogElement.getUniqueId());
                    return edgeCreationStatus;
                }
                LOGGER.debug("created edge from catalog root to element {}", catalogElement.getUniqueId());
                numOfCreatedEdges++;
        }
        LOGGER.info("number edges created: {}", numOfCreatedEdges);
        return TitanOperationStatus.OK;
    }

    private boolean edgeNotAlreadyExists(GraphVertex catalogElement) {
        return !catalogElement.getVertex().edges(Direction.IN, EdgeLabelEnum.CATALOG_ELEMENT.name()).hasNext();
    }


}