496db14e5386cb79b003933de75b2c6d246c7293
[sdc.git] /
1 /*
2  * Copyright © 2016-2018 European Support Limited
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.openecomp.sdcrests.item.rest.services;
18
19 import static org.openecomp.sdc.itempermissions.notifications.NotificationConstants.PERMISSION_USER;
20 import static org.openecomp.sdc.versioning.VersioningNotificationConstansts.ITEM_ID;
21 import static org.openecomp.sdc.versioning.VersioningNotificationConstansts.ITEM_NAME;
22 import static org.openecomp.sdc.versioning.VersioningNotificationConstansts.SUBMIT_DESCRIPTION;
23 import static org.openecomp.sdc.versioning.VersioningNotificationConstansts.VERSION_ID;
24 import static org.openecomp.sdc.versioning.VersioningNotificationConstansts.VERSION_NAME;
25
26 import java.util.HashMap;
27 import java.util.List;
28 import java.util.Map;
29 import javax.inject.Named;
30 import javax.ws.rs.core.Response;
31 import org.openecomp.sdc.activitylog.ActivityLogManager;
32 import org.openecomp.sdc.activitylog.ActivityLogManagerFactory;
33 import org.openecomp.sdc.activitylog.dao.type.ActivityLogEntity;
34 import org.openecomp.sdc.activitylog.dao.type.ActivityType;
35 import org.openecomp.sdc.common.errors.CoreException;
36 import org.openecomp.sdc.common.errors.Messages;
37 import org.openecomp.sdc.conflicts.ConflictsManager;
38 import org.openecomp.sdc.conflicts.ConflictsManagerFactory;
39 import org.openecomp.sdc.itempermissions.PermissionsManager;
40 import org.openecomp.sdc.itempermissions.PermissionsManagerFactory;
41 import org.openecomp.sdc.logging.api.Logger;
42 import org.openecomp.sdc.logging.api.LoggerFactory;
43 import org.openecomp.sdc.notification.dtos.Event;
44 import org.openecomp.sdc.notification.factories.NotificationPropagationManagerFactory;
45 import org.openecomp.sdc.notification.services.NotificationPropagationManager;
46 import org.openecomp.sdc.versioning.AsdcItemManager;
47 import org.openecomp.sdc.versioning.AsdcItemManagerFactory;
48 import org.openecomp.sdc.versioning.VersioningManager;
49 import org.openecomp.sdc.versioning.VersioningManagerFactory;
50 import org.openecomp.sdc.versioning.dao.types.Revision;
51 import org.openecomp.sdc.versioning.dao.types.SynchronizationState;
52 import org.openecomp.sdc.versioning.dao.types.Version;
53 import org.openecomp.sdc.versioning.errors.RevisionIdNotFoundErrorBuilder;
54 import org.openecomp.sdc.versioning.types.NotificationEventTypes;
55 import org.openecomp.sdc.versioning.types.VersionCreationMethod;
56 import org.openecomp.sdcrests.item.rest.Versions;
57 import org.openecomp.sdcrests.item.rest.mapping.MapActivityLogEntityToDto;
58 import org.openecomp.sdcrests.item.rest.mapping.MapRevisionToDto;
59 import org.openecomp.sdcrests.item.rest.mapping.MapVersionToDto;
60 import org.openecomp.sdcrests.item.types.ActivityLogDto;
61 import org.openecomp.sdcrests.item.types.CommitRequestDto;
62 import org.openecomp.sdcrests.item.types.RevisionDto;
63 import org.openecomp.sdcrests.item.types.RevisionRequestDto;
64 import org.openecomp.sdcrests.item.types.VersionActionRequestDto;
65 import org.openecomp.sdcrests.item.types.VersionDto;
66 import org.openecomp.sdcrests.item.types.VersionRequestDto;
67 import org.openecomp.sdcrests.wrappers.GenericCollectionWrapper;
68 import org.springframework.context.annotation.Scope;
69 import org.springframework.stereotype.Service;
70
71 @Named
72 @Service("versions")
73 @Scope(value = "prototype")
74 public class VersionsImpl implements Versions {
75
76   private static final String COMMIT_ITEM_ACTION = "Commit_Item";
77   private static final Logger LOGGER = LoggerFactory.getLogger(VersionsImpl.class);
78
79   private PermissionsManager permissionsManager =
80       PermissionsManagerFactory.getInstance().createInterface();
81   private AsdcItemManager asdcItemManager =
82       AsdcItemManagerFactory.getInstance().createInterface();
83   private VersioningManager versioningManager =
84       VersioningManagerFactory.getInstance().createInterface();
85   private ConflictsManager conflictsManager =
86       ConflictsManagerFactory.getInstance().createInterface();
87   private ActivityLogManager activityLogManager =
88       ActivityLogManagerFactory.getInstance().createInterface();
89   private NotificationPropagationManager notifier =
90       NotificationPropagationManagerFactory.getInstance().createInterface();
91
92   @Override
93   public Response list(String itemId, String user) {
94     GenericCollectionWrapper<VersionDto> results = new GenericCollectionWrapper<>();
95     MapVersionToDto mapper = new MapVersionToDto();
96
97     versioningManager.list(itemId)
98         .forEach(version -> results.add(mapper.applyMapping(version, VersionDto.class)));
99     return Response.ok(results).build();
100   }
101
102   @Override
103   public Response create(VersionRequestDto request, String itemId, String baseVersionId,
104                          String user) {
105     Version version = new Version();
106     version.setBaseId(baseVersionId);
107     version.setDescription(request.getDescription());
108
109     version = versioningManager.create(itemId, version, VersionCreationMethod.valueOf(request
110         .getCreationMethod().name()));
111
112     VersionDto versionDto = new MapVersionToDto().applyMapping(version, VersionDto.class);
113
114     activityLogManager.logActivity(new ActivityLogEntity(itemId, version,
115         ActivityType.Create_Version, user, true, "", ""));
116
117     return Response.ok(versionDto).build();
118   }
119
120   @Override
121   public Response get(String itemId, String versionId, String user) {
122     Version version = getVersion(itemId, new Version(versionId));
123     VersionDto versionDto = new MapVersionToDto().applyMapping(version, VersionDto.class);
124     return Response.ok(versionDto).build();
125   }
126
127   @Override
128   public Response getActivityLog(String itemId, String versionId, String user) {
129     GenericCollectionWrapper<ActivityLogDto> results = new GenericCollectionWrapper<>();
130     MapActivityLogEntityToDto mapper = new MapActivityLogEntityToDto();
131
132     activityLogManager.listLoggedActivities(itemId, new Version(versionId))
133         .forEach(loggedActivity -> results
134             .add(mapper.applyMapping(loggedActivity, ActivityLogDto.class)));
135
136     return Response.ok(results).build();
137   }
138
139   @Override
140   public Response listRevisions(String itemId, String versionId, String user) {
141     List<Revision> revisions = versioningManager.listRevisions(itemId, new Version(versionId));
142     filterRevisions(revisions);
143
144     GenericCollectionWrapper<RevisionDto> results = new GenericCollectionWrapper<>();
145     MapRevisionToDto mapper = new MapRevisionToDto();
146     revisions.forEach(revision -> results.add(mapper.applyMapping(revision, RevisionDto.class)));
147     return Response.ok(results).build();
148   }
149
150   @Override
151   public Response actOn(VersionActionRequestDto request, String itemId, String versionId,
152                         String user) {
153     Version version = new Version(versionId);
154     switch (request.getAction()) {
155       case Sync:
156         sync(itemId, version);
157         break;
158       case Commit:
159         if (!permissionsManager.isAllowed(itemId, user, COMMIT_ITEM_ACTION)) {
160           return Response.status(Response.Status.FORBIDDEN)
161               .entity(new Exception(Messages.PERMISSIONS_ERROR.getErrorMessage())).build();
162         }
163         commit(request.getCommitRequest(), itemId, version, user);
164         break;
165       case Revert:
166         revert(request.getRevisionRequest(), itemId, versionId);
167         break;
168       case Clean:
169         versioningManager.clean(itemId, version);
170         break;
171       default:
172         throw new UnsupportedOperationException(String.format("Action %s not supported.", request.getAction()));
173     }
174     return Response.ok().build();
175   }
176
177   private Version getVersion(String itemId, Version version) {
178     Version retrievedVersion = versioningManager.get(itemId, version);
179
180     if (retrievedVersion.getState().getSynchronizationState() != SynchronizationState.Merging &&
181         // looks for sdc applicative conflicts
182         conflictsManager.isConflicted(itemId, retrievedVersion)) {
183       retrievedVersion.getState().setSynchronizationState(SynchronizationState.Merging);
184     }
185     return retrievedVersion;
186   }
187
188   private void sync(String itemId, Version version) {
189     versioningManager.sync(itemId, version);
190     conflictsManager.finalizeMerge(itemId, version);
191   }
192
193   private void commit(CommitRequestDto request, String itemId, Version version, String user) {
194
195     String message = request == null ? "" : request.getMessage();
196
197     versioningManager.publish(itemId, version, message);
198     notifyUsers(itemId, version, message, user, NotificationEventTypes.COMMIT);
199
200     activityLogManager.logActivity(new ActivityLogEntity(itemId, version,
201         ActivityType.Commit, user, true, "", message));
202   }
203
204   private void revert(RevisionRequestDto request, String itemId, String versionId) {
205     if (request.getRevisionId() == null) {
206       throw new CoreException(new RevisionIdNotFoundErrorBuilder().build());
207     }
208
209     versioningManager.revert(itemId, new Version(versionId), request.getRevisionId());
210   }
211
212   private void filterRevisions(List<Revision> revisions) {
213   /* When creating a new item an initial version is created with invalid data.
214      This revision is not an applicable revision. The logic of identifying this revision is:
215      1- only the first version of item has this issue
216      2- only in the first item version there are 2 revisions created
217      3- the second revision is in format "Initial <vlm/vsp>: <name of the vlm/vsp>"
218      4- only if a revision in this format exists we remove the first revision. */
219     int numOfRevisions = revisions.size();
220     if (numOfRevisions > 1 &&
221
222         revisions.get(numOfRevisions - 2).getMessage().matches("Initial .*:.*")) {
223       revisions.remove(numOfRevisions - 1);
224     }
225   }
226
227   private void notifyUsers(String itemId, Version version, String message,
228                            String userName, NotificationEventTypes eventType) {
229     Map<String, Object> eventProperties = new HashMap<>();
230     eventProperties.put(ITEM_NAME, asdcItemManager.get(itemId).getName());
231     eventProperties.put(ITEM_ID, itemId);
232
233     Version ver = versioningManager.get(itemId, version);
234     eventProperties.put(VERSION_NAME, ver.getName());
235     eventProperties.put(VERSION_ID, ver.getId());
236
237     eventProperties.put(SUBMIT_DESCRIPTION, message);
238     eventProperties.put(PERMISSION_USER, userName);
239
240     Event syncEvent = new SyncEvent(eventType.getEventName(), itemId, eventProperties, itemId);
241     try {
242       notifier.notifySubscribers(syncEvent, userName);
243     } catch (Exception e) {
244       LOGGER.error("Failed to send sync notification to users subscribed o item '" + itemId);
245     }
246   }
247
248   private class SyncEvent implements Event {
249     private String eventType;
250     private String originatorId;
251     private Map<String, Object> attributes;
252
253     private String entityId;
254
255     public SyncEvent(String eventType, String originatorId,
256                      Map<String, Object> attributes, String entityId) {
257       this.eventType = eventType;
258       this.originatorId = originatorId;
259       this.attributes = attributes;
260       this.entityId = entityId;
261     }
262
263     @Override
264     public String getEventType() {
265       return eventType;
266     }
267
268     @Override
269     public String getOriginatorId() {
270       return originatorId;
271     }
272
273     @Override
274     public Map<String, Object> getAttributes() {
275       return attributes;
276     }
277
278     @Override
279     public String getEntityId() {
280       return entityId;
281     }
282
283   }
284 }