Add lombok support to simple classes
[sdc.git] / catalog-model / src / main / java / org / openecomp / sdc / be / model / jsonjanusgraph / operations / ArchiveOperation.java
1 package org.openecomp.sdc.be.model.jsonjanusgraph.operations;
2
3 import fj.data.Either;
4 import org.openecomp.sdc.be.dao.api.ActionStatus;
5 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
6 import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
7 import org.openecomp.sdc.be.dao.jsongraph.JanusGraphDao;
8 import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum;
9 import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
10 import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum;
11 import org.openecomp.sdc.be.datatypes.elements.ComponentInstanceDataDefinition;
12 import org.openecomp.sdc.be.datatypes.elements.CompositionDataDefinition;
13 import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
14 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
15 import org.openecomp.sdc.be.model.LifecycleStateEnum;
16 import org.openecomp.sdc.be.model.jsonjanusgraph.enums.JsonConstantKeysEnum;
17 import org.openecomp.sdc.be.model.operations.api.IGraphLockOperation;
18 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
19 import org.openecomp.sdc.common.log.wrappers.Logger;
20 import org.springframework.beans.factory.annotation.Autowired;
21 import org.springframework.stereotype.Component;
22
23 import java.util.*;
24 import java.util.stream.Collectors;
25
26 import static org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArchiveOperation.Action.ARCHIVE;
27 import static org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArchiveOperation.Action.RESTORE;
28
29 /**
30  * Created by yavivi on 25/03/2018.
31  */
32 @Component
33 public class ArchiveOperation extends BaseOperation {
34
35     private static final Logger log = Logger.getLogger(ArchiveOperation.class.getName());
36
37     @Autowired
38     private IGraphLockOperation graphLockOperation;
39
40     public enum Action {
41         ARCHIVE, RESTORE;
42     }
43
44     public ArchiveOperation(JanusGraphDao janusGraphDao, IGraphLockOperation graphLockOperation){
45         this.janusGraphDao = janusGraphDao;
46         this.graphLockOperation = graphLockOperation;
47     }
48
49     public Either<List<String>, ActionStatus> archiveComponent(String componentId) {
50         final Either<GraphVertex, JanusGraphOperationStatus> vertexResult = this.janusGraphDao.getVertexById(componentId);
51         if (vertexResult.isLeft()){
52             return doAction(ARCHIVE, vertexResult.left().value());
53         } else {
54             return Either.right(onError(ARCHIVE.name(), componentId, vertexResult.right().value()));
55         }
56     }
57
58     public Either<List<String>, ActionStatus> restoreComponent(String componentId) {
59         final Either<GraphVertex, JanusGraphOperationStatus> vertexResult = this.janusGraphDao.getVertexById(componentId);
60         if (vertexResult.isLeft()){
61             return doAction(RESTORE, vertexResult.left().value());
62         } else {
63             return Either.right(onError(RESTORE.name(), componentId, vertexResult.right().value()));
64         }
65     }
66
67     public ActionStatus onVspRestored(String csarId){
68         return onVspStateChanged(RESTORE, csarId);
69     }
70
71     public ActionStatus onVspArchived(String csarId){
72         return onVspStateChanged(ARCHIVE, csarId);
73     }
74
75     private ActionStatus onVspStateChanged(Action action, String csarId) {
76         Map<GraphPropertyEnum, Object> props = new HashMap<>();
77         props.put(GraphPropertyEnum.CSAR_UUID, csarId);
78         Either<List<GraphVertex>, JanusGraphOperationStatus> vfsE = janusGraphDao
79             .getByCriteria(VertexTypeEnum.TOPOLOGY_TEMPLATE, props);
80         return vfsE.either(vList -> setVspArchived(action, vList), s -> onError("VSP_"+action.name(), csarId, s));
81     }
82
83     private ActionStatus setVspArchived(Action action, List<GraphVertex> vList) {
84         if (!vList.isEmpty()) {
85             //Find & Lock the highest version component
86             GraphVertex highestVersion = this.getHighestVersionFrom(vList.get(0));
87             StorageOperationStatus lockStatus = this.graphLockOperation.lockComponent(highestVersion.getUniqueId(), highestVersion.getType().getNodeType());
88             if (lockStatus != StorageOperationStatus.OK){
89                 return onError(action.name(), highestVersion.getUniqueId(), JanusGraphOperationStatus.ALREADY_LOCKED);
90             }
91
92             try {
93                 //Set isVspArchived flag
94                 for (GraphVertex v : vList) {
95                     boolean val = action == ARCHIVE ? true : false;
96                     v.setJsonMetadataField(JsonPresentationFields.IS_VSP_ARCHIVED, val);
97                     v.addMetadataProperty(GraphPropertyEnum.IS_VSP_ARCHIVED, val);
98                     janusGraphDao.updateVertex(v);
99                 }
100                 return commitAndCheck("VSP_"+action.name(), vList.toString());
101             } finally {
102                 this.graphLockOperation.unlockComponent(highestVersion.getUniqueId(), highestVersion.getType().getNodeType());
103             }
104
105         }
106         return ActionStatus.OK;
107     }
108
109     public List<String> setArchivedOriginsFlagInComponentInstances(GraphVertex compositionService) {
110         List<String> ciUidsWithArchivedOrigins = new LinkedList();
111         Either<List<GraphVertex>, JanusGraphOperationStatus> instanceOfVerticesE = janusGraphDao
112             .getChildrenVertecies(compositionService, EdgeLabelEnum.INSTANCE_OF, JsonParseFlagEnum.NoParse);
113         Either<List<GraphVertex>, JanusGraphOperationStatus> proxyOfVerticesE = janusGraphDao
114             .getChildrenVertecies(compositionService, EdgeLabelEnum.PROXY_OF, JsonParseFlagEnum.NoParse);
115
116         List<GraphVertex> all = new LinkedList<>();
117         if (instanceOfVerticesE.isLeft()){
118             all.addAll(instanceOfVerticesE.left().value());
119         }
120         if (proxyOfVerticesE.isLeft()){
121             all.addAll(proxyOfVerticesE.left().value());
122         }
123
124         List<GraphVertex> archivedOrigins = all.stream().filter(v -> Boolean.TRUE.equals(v.getMetadataProperty(GraphPropertyEnum.IS_ARCHIVED))).collect(Collectors.toList());
125         List<String> archivedOriginsUids = archivedOrigins.stream().map(GraphVertex::getUniqueId).collect(Collectors.toList());
126
127         Map<String, CompositionDataDefinition> compositionsJson = (Map<String, CompositionDataDefinition>) compositionService.getJson();
128
129         if (compositionsJson != null) {
130             CompositionDataDefinition composition = compositionsJson.get(JsonConstantKeysEnum.COMPOSITION.getValue());
131             if (composition != null) {
132
133                 //Get all component instances from composition
134                 Map<String, ComponentInstanceDataDefinition> componentInstances = composition.getComponentInstances();
135
136                 //Extract component instances uids that has archived origins
137                 ciUidsWithArchivedOrigins = componentInstances.
138                         values().
139                         stream().
140                         //filter CIs whose origins are marked as archived (componentUid is in archivedOriginsUids) the second condition handles the PROXY_OF case)
141                         filter(ci -> archivedOriginsUids.contains(ci.getComponentUid()) || archivedOriginsUids.contains(ci.getToscaPresentationValue(JsonPresentationFields.CI_SOURCE_MODEL_UID))).
142                         map(ComponentInstanceDataDefinition::getUniqueId).collect(Collectors.toList());
143
144                 //set archived origins flag
145                 componentInstances.
146                         values().
147                         stream().
148                         filter(ci -> archivedOriginsUids.contains(ci.getComponentUid()) || archivedOriginsUids.contains(ci.getToscaPresentationValue(JsonPresentationFields.CI_SOURCE_MODEL_UID))).
149                         forEach( ci -> ci.setOriginArchived(true));
150
151             }
152         }
153
154         return ciUidsWithArchivedOrigins;
155     }
156
157     private Either<List<String>, ActionStatus> doAction(Action action, GraphVertex componentVertex){
158
159         GraphVertex highestVersion = this.getHighestVersionFrom(componentVertex);
160
161         if (action.equals(ARCHIVE) && isInCheckoutState(highestVersion)) {
162             return Either.right(ActionStatus.INVALID_SERVICE_STATE);
163         }
164
165         //Lock the Highest Version
166         StorageOperationStatus lockStatus = this.graphLockOperation.lockComponent(highestVersion.getUniqueId(), highestVersion.getType().getNodeType());
167         if (lockStatus != StorageOperationStatus.OK){
168             return Either.right(onError(action.name(), componentVertex.getUniqueId(), JanusGraphOperationStatus.ALREADY_LOCKED));
169         }
170
171         //Refetch latest version with full parsing
172         highestVersion = this.janusGraphDao
173             .getVertexById(highestVersion.getUniqueId(), JsonParseFlagEnum.ParseAll).left().value();
174
175         try {
176             //Get Catalog and Archive Roots
177             GraphVertex catalogRoot = janusGraphDao.getVertexByLabel(VertexTypeEnum.CATALOG_ROOT).left().value();
178             GraphVertex archiveRoot = janusGraphDao.getVertexByLabel(VertexTypeEnum.ARCHIVE_ROOT).left().value();
179
180             if (action == ARCHIVE) {
181                 archiveEdges(catalogRoot, archiveRoot, highestVersion);
182             } else if (action == RESTORE) {
183                 restoreEdges(catalogRoot, archiveRoot, highestVersion);
184             }
185             setPropertiesByAction(highestVersion, action);
186             janusGraphDao.updateVertex(highestVersion);
187
188             List<String> affectedComponentIds = handleParents(highestVersion, catalogRoot, archiveRoot, action);
189             ActionStatus sc = commitAndCheck(action.name(), highestVersion.getUniqueId());
190             return  sc == ActionStatus.OK ? Either.left(affectedComponentIds) : Either.right(sc);
191         } finally {
192             this.graphLockOperation.unlockComponent(highestVersion.getUniqueId(), highestVersion.getType().getNodeType());
193         }
194     }
195
196     private ActionStatus commitAndCheck(String action, String componentId) {
197         JanusGraphOperationStatus status = janusGraphDao.commit();
198         if (!status.equals(JanusGraphOperationStatus.OK)){
199             return onError(action, componentId, status);
200         }
201         return ActionStatus.OK;
202     }
203
204     private boolean isInCheckoutState(GraphVertex v) {
205         if (LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT.name().equals(v.getMetadataProperty(GraphPropertyEnum.STATE))){
206             return true;
207         }
208         return false;
209     }
210
211     /**
212      * Walks on children until highest version is reached
213      * @param v
214      * @return
215      */
216     private GraphVertex getHighestVersionFrom(GraphVertex v) {
217         Either<GraphVertex, JanusGraphOperationStatus> childVertexE = janusGraphDao
218             .getChildVertex(v, EdgeLabelEnum.VERSION, JsonParseFlagEnum.NoParse);
219         GraphVertex highestVersionVertex = v;
220
221         while (childVertexE.isLeft()) {
222             highestVersionVertex = childVertexE.left().value();
223             childVertexE = janusGraphDao
224                 .getChildVertex(highestVersionVertex, EdgeLabelEnum.VERSION, JsonParseFlagEnum.NoParse);
225         }
226         return highestVersionVertex;
227     }
228
229     private boolean isHighestVersion(GraphVertex v){
230         Boolean highest = (Boolean) v.getMetadataProperty(GraphPropertyEnum.IS_HIGHEST_VERSION);
231         return highest != null && highest;
232     }
233
234     private List<String> handleParents(GraphVertex v, GraphVertex catalogRoot, GraphVertex archiveRoot, Action action) {
235         Either<GraphVertex, JanusGraphOperationStatus> parentVertexE = janusGraphDao
236             .getParentVertex(v, EdgeLabelEnum.VERSION, JsonParseFlagEnum.ParseAll);
237         List<String> affectedCompIds = new ArrayList();
238         affectedCompIds.add(v.getUniqueId());
239
240         while (parentVertexE.isLeft()){
241             GraphVertex cv = parentVertexE.left().value();
242             affectedCompIds.add(cv.getUniqueId());
243             boolean isHighestVersion = isHighestVersion(cv);
244             if (isHighestVersion){
245                 if (action == ARCHIVE) {
246                     archiveEdges(catalogRoot, archiveRoot, cv);
247                 } else {
248                     restoreEdges(catalogRoot, archiveRoot, cv);
249                 }
250             }
251             setPropertiesByAction(cv, action);
252             janusGraphDao.updateVertex(cv);
253             parentVertexE = janusGraphDao
254                 .getParentVertex(cv, EdgeLabelEnum.VERSION, JsonParseFlagEnum.ParseAll);
255         }
256         return affectedCompIds;
257     }
258
259     private void archiveEdges(GraphVertex catalogRoot, GraphVertex archiveRoot, GraphVertex v) {
260         janusGraphDao.deleteAllEdges(catalogRoot, v, EdgeLabelEnum.CATALOG_ELEMENT);
261         janusGraphDao.createEdge(archiveRoot, v, EdgeLabelEnum.ARCHIVE_ELEMENT, null);
262         setPropertiesByAction(v, ARCHIVE);
263     }
264
265     private void restoreEdges(GraphVertex catalogRoot, GraphVertex archiveRoot, GraphVertex v) {
266         janusGraphDao.deleteAllEdges(archiveRoot, v, EdgeLabelEnum.ARCHIVE_ELEMENT);
267         janusGraphDao.createEdge(catalogRoot, v, EdgeLabelEnum.CATALOG_ELEMENT, null);
268         setPropertiesByAction(v, RESTORE);
269     }
270
271     private void setPropertiesByAction(GraphVertex v, Action action) {
272         long now = System.currentTimeMillis();
273
274         boolean isArchived = action == ARCHIVE ? true : false;
275         v.addMetadataProperty(GraphPropertyEnum.IS_ARCHIVED, isArchived);
276         v.addMetadataProperty(GraphPropertyEnum.ARCHIVE_TIME, now);
277         v.setJsonMetadataField(JsonPresentationFields.IS_ARCHIVED, isArchived);
278         v.setJsonMetadataField(JsonPresentationFields.ARCHIVE_TIME, now);
279     }
280
281     private ActionStatus onError(String action, String componentId, JanusGraphOperationStatus s) {
282         ActionStatus ret = ActionStatus.GENERAL_ERROR;
283         if (s == JanusGraphOperationStatus.NOT_FOUND){
284             ret = ActionStatus.RESOURCE_NOT_FOUND;
285         } else if (s == JanusGraphOperationStatus.ALREADY_LOCKED) {
286             ret = ActionStatus.COMPONENT_IN_USE;
287         }
288         String retCodeVal = ret.name();
289         log.error("error occurred when trying to {} {}. Return code is: {}", action, componentId, retCodeVal);
290         return ret;
291     }
292 }