[sdc] rebase update
[sdc.git] / asdctool / src / main / java / org / openecomp / sdc / asdctool / impl / migration / MigrationOperationUtils.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.openecomp.sdc.asdctool.impl.migration;
22
23 import com.thinkaurelius.titan.core.PropertyKey;
24 import com.thinkaurelius.titan.core.TitanGraph;
25 import com.thinkaurelius.titan.core.TitanVertex;
26 import com.thinkaurelius.titan.core.schema.TitanManagement;
27 import fj.data.Either;
28 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
29 import org.openecomp.sdc.be.dao.titan.TitanGenericDao;
30 import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33 import org.springframework.beans.factory.annotation.Autowired;
34 import org.springframework.stereotype.Component;
35
36 import java.util.Map;
37 import java.util.Optional;
38
39 @Component("migrationUtils")
40 public class MigrationOperationUtils {
41
42     private static Logger log = LoggerFactory.getLogger(MigrationOperationUtils.class);
43
44     @Autowired
45     private TitanGenericDao titanGenericDao;
46
47     /**
48      * rename a set or property keys
49      *
50      * @param propertyKeys a mapping between the old property key name and the property key name to replace it with
51      *
52      * @return true if rename ended successfully or false otherwise
53      */
54     public boolean renamePropertyKeys(Map<String, String> propertyKeys) {
55         Either<TitanGraph, TitanOperationStatus> graph = titanGenericDao.getGraph();
56         return graph.either((titanGraph) ->  renamePropertyKeys(titanGraph, propertyKeys),
57                             (titanOperationStatus) -> operationFailed(MigrationMsg.FAILED_TO_RETRIEVE_GRAPH.getMessage(titanOperationStatus.name())));
58     }
59
60     private boolean renamePropertyKeys(TitanGraph titanGraph, Map<String, String> propertyKeys) {
61         try {
62             for (Map.Entry<String, String> propertyKeyEntry : propertyKeys.entrySet()) {
63                 boolean renameSucceeded = renamePropertyKey(titanGraph, propertyKeyEntry);
64                 if (!renameSucceeded) {
65                     return false;
66                 }
67             }
68             return true;
69         } catch (RuntimeException e) {
70             log.error(e.getMessage(), e);
71             return false;
72         }
73     }
74
75     private Boolean renamePropertyKey(TitanGraph titanGraph, Map.Entry<String, String> propertyKeyEntry) {
76         String renameFromKey = propertyKeyEntry.getKey();
77         String renameToKey = propertyKeyEntry.getValue();
78         log.info(String.format("renaming property key %s to %s", renameFromKey, renameToKey));
79         return renameProperty(titanGraph, renameFromKey, renameToKey);
80     }
81
82     private Boolean renameProperty(TitanGraph titanGraph, String renameFromKey, String renameToKey) {
83         if (titanGraph.containsPropertyKey(renameFromKey) && titanGraph.containsPropertyKey(renameToKey)) {//new property already exist, we cant rename to it we need to add new and remove old on every vertices which has the old one.
84             return renamePropertyOnEachVertex(titanGraph, renameFromKey, renameToKey);
85         }
86         return renamePropertyOnGraphLevel(titanGraph, renameFromKey, renameToKey);
87     }
88
89     private Boolean renamePropertyOnGraphLevel(TitanGraph titanGraph, String renameFromKey, String renameToKey) {
90         TitanManagement titanManagement = titanGraph.openManagement();
91         return Optional.ofNullable(titanManagement.getPropertyKey(renameFromKey))
92                 .map(propertyKey -> renamePropertyOnGraph(titanManagement, propertyKey, renameToKey))
93                 .orElseGet(() -> {log.info(MigrationMsg.PROPERTY_KEY_NOT_EXIST.getMessage(renameFromKey)); return true;}) ;//if property key not exist rename is considered to be successful
94     }
95
96     private boolean renamePropertyOnEachVertex(TitanGraph graph, String oldKey, String newKey) {
97         addNewPropertyKeyOnVertices(graph, oldKey, newKey);
98         removeOldPropertyKeyFromGraph(graph, oldKey);
99         graph.tx().commit();
100         return true;
101     }
102
103     private void removeOldPropertyKeyFromGraph(TitanGraph graph, String oldKey) {
104         graph.getPropertyKey(oldKey).remove();
105     }
106
107         private void addNewPropertyKeyOnVertices(TitanGraph graph, String oldKey, String newKey) {
108         graph.query().has(oldKey).vertices().forEach(titanVertex -> {
109             copyOldKeyValueAndDropKey(oldKey, newKey, (TitanVertex) titanVertex);
110         });
111     }
112
113     private void copyOldKeyValueAndDropKey(String oldKey, String newKey, TitanVertex titanVertex) {
114         VertexProperty<Object> oldProperty = titanVertex.property(oldKey);
115         Object oldKeyValue = oldProperty.value();
116
117         titanVertex.property(newKey, oldKeyValue);
118         oldProperty.remove();
119     }
120
121     private boolean renamePropertyOnGraph(TitanManagement titanManagement, PropertyKey fromPropertyKey, String toKey) {
122         try {
123             titanManagement.changeName(fromPropertyKey, toKey);
124             titanManagement.commit();
125             return true;
126         } catch (RuntimeException e) {
127             log.error(MigrationMsg.RENAME_KEY_PROPERTY_FAILED.getMessage(fromPropertyKey.name()), e.getMessage());
128             titanManagement.rollback();
129             return false;
130         }
131     }
132
133     private boolean operationFailed(String errorMessage) {
134         log.error(errorMessage);
135         return false;
136     }
137
138
139 }