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