afdac0ad6160c3cc14721e3d1e8199d886d4ae54
[sdc.git] /
1 /*
2  * Copyright © 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
23 import java.util.Arrays;
24 import java.util.Collections;
25 import java.util.EnumMap;
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.Optional;
31 import java.util.Set;
32 import java.util.function.Predicate;
33 import java.util.stream.Collectors;
34 import javax.annotation.PostConstruct;
35 import javax.inject.Named;
36 import javax.ws.rs.core.Response;
37 import org.openecomp.sdc.activitylog.ActivityLogManager;
38 import org.openecomp.sdc.activitylog.ActivityLogManagerFactory;
39 import org.openecomp.sdc.activitylog.dao.type.ActivityLogEntity;
40 import org.openecomp.sdc.activitylog.dao.type.ActivityType;
41 import org.openecomp.sdc.datatypes.model.ItemType;
42 import org.openecomp.sdc.itempermissions.PermissionsManager;
43 import org.openecomp.sdc.itempermissions.PermissionsManagerFactory;
44 import org.openecomp.sdc.itempermissions.impl.types.PermissionTypes;
45 import org.openecomp.sdc.logging.api.Logger;
46 import org.openecomp.sdc.logging.api.LoggerFactory;
47 import org.openecomp.sdc.notification.dtos.Event;
48 import org.openecomp.sdc.notification.factories.NotificationPropagationManagerFactory;
49 import org.openecomp.sdc.notification.services.NotificationPropagationManager;
50 import org.openecomp.sdc.versioning.ItemManager;
51 import org.openecomp.sdc.versioning.ItemManagerFactory;
52 import org.openecomp.sdc.versioning.VersioningManager;
53 import org.openecomp.sdc.versioning.VersioningManagerFactory;
54 import org.openecomp.sdc.versioning.dao.types.Version;
55 import org.openecomp.sdc.versioning.dao.types.VersionStatus;
56 import org.openecomp.sdc.versioning.types.Item;
57 import org.openecomp.sdc.versioning.types.ItemStatus;
58 import org.openecomp.sdc.versioning.types.NotificationEventTypes;
59 import org.openecomp.sdcrests.item.rest.Items;
60 import org.openecomp.sdcrests.item.rest.mapping.MapItemToDto;
61 import org.openecomp.sdcrests.item.types.ItemAction;
62 import org.openecomp.sdcrests.item.types.ItemActionRequestDto;
63 import org.openecomp.sdcrests.item.types.ItemDto;
64 import org.openecomp.sdcrests.wrappers.GenericCollectionWrapper;
65 import org.springframework.context.annotation.Scope;
66 import org.springframework.stereotype.Service;
67 import org.springframework.validation.annotation.Validated;
68
69
70 @Named
71 @Service("items")
72 @Scope(value = "prototype")
73 @Validated
74 public class ItemsImpl implements Items {
75
76     private ItemManager itemManager = ItemManagerFactory.getInstance().createInterface();
77
78     private static ActivityLogManager activityLogManager = ActivityLogManagerFactory.getInstance().createInterface();
79
80     private VersioningManager versioningManager = VersioningManagerFactory.getInstance().createInterface();
81
82     private final PermissionsManager permissionsManager = PermissionsManagerFactory.getInstance().createInterface();
83
84     private static final Logger LOGGER = LoggerFactory.getLogger(ItemsImpl.class);
85
86     private NotificationPropagationManager notifier =
87             NotificationPropagationManagerFactory.getInstance().createInterface();
88
89
90
91     private Map<ItemAction, ActionSideAffects> actionSideAffectsMap = new EnumMap<>(ItemAction.class);
92
93     @PostConstruct
94     public void initActionSideAffectsMap() {
95         actionSideAffectsMap
96                 .put(ItemAction.ARCHIVE, new ActionSideAffects(ActivityType.Archive, NotificationEventTypes.ARCHIVE));
97         actionSideAffectsMap
98                 .put(ItemAction.RESTORE, new ActionSideAffects(ActivityType.Restore, NotificationEventTypes.RESTORE));
99     }
100
101     private static final String ONBOARDING_METHOD = "onboardingMethod";
102
103
104     @Override
105     public Response actOn(ItemActionRequestDto request, String itemId, String user) {
106
107         Item item = itemManager.get(itemId);
108         if (item == null) {
109             return Response.status(Response.Status.NOT_FOUND).entity(new Exception("Item does not exist.")).build();
110         }
111
112         switch (request.getAction()) {
113             case ARCHIVE:
114                 itemManager.archive(item);
115                 break;
116             case RESTORE:
117                 itemManager.restore(item);
118                 break;
119             default:
120         }
121
122         actionSideAffectsMap.get(request.getAction()).execute(item, user);
123         try {
124             CatalogNotifier catalogNotifier = new CatalogNotifier();
125             catalogNotifier.execute(Collections.singleton(itemId), request.getAction(), 2);
126         } catch (Exception e){
127             LOGGER.error("Failed to send catalog notification on item " + itemId + " Error: " + e.getMessage());
128         }
129
130         return Response.ok().build();
131     }
132
133     @Override
134     public Response list(String itemStatusFilter, String versionStatusFilter, String itemTypeFilter,
135             String permissionFilter, String onboardingMethodFilter, String user) {
136
137         Predicate<Item> itemPredicate =
138                 createItemPredicate(itemStatusFilter, versionStatusFilter, itemTypeFilter, onboardingMethodFilter,
139                         permissionFilter, user);
140
141         GenericCollectionWrapper<ItemDto> results = new GenericCollectionWrapper<>();
142         MapItemToDto mapper = new MapItemToDto();
143         itemManager.list(itemPredicate).stream()
144                    .sorted((o1, o2) -> o2.getModificationTime().compareTo(o1.getModificationTime()))
145                    .forEach(item -> results.add(mapper.applyMapping(item, ItemDto.class)));
146
147         return Response.ok(results).build();
148
149     }
150
151     @Override
152     public Response getItem(String itemId, String user) {
153         Item item = itemManager.get(itemId);
154         ItemDto itemDto = new MapItemToDto().applyMapping(item, ItemDto.class);
155
156         return Response.ok(itemDto).build();
157     }
158
159     private class SyncEvent implements Event {
160
161         private String eventType;
162         private String originatorId;
163         private Map<String, Object> attributes;
164         private String entityId;
165
166         SyncEvent(String eventType, String originatorId, Map<String, Object> attributes, String entityId) {
167             this.eventType = eventType;
168             this.originatorId = originatorId;
169             this.attributes = attributes;
170             this.entityId = entityId;
171         }
172
173         @Override
174         public String getEventType() {
175             return eventType;
176         }
177
178         @Override
179         public String getOriginatorId() {
180             return originatorId;
181         }
182
183         @Override
184         public Map<String, Object> getAttributes() {
185             return attributes;
186         }
187
188         @Override
189         public String getEntityId() {
190             return entityId;
191         }
192
193     }
194
195     private class ActionSideAffects {
196
197         private ActivityType activityType;
198         private NotificationEventTypes notificationType;
199
200         private ActionSideAffects(ActivityType activityType, NotificationEventTypes notificationType) {
201             this.activityType = activityType;
202             this.notificationType = notificationType;
203
204         }
205
206         private Version getLatestVersion(String itemId) {
207             List<Version> list = versioningManager.list(itemId);
208             Optional<Version> max = list.stream().max(Version::compareTo);
209
210             return max.orElse(null);
211         }
212
213         private void execute(Item item, String user) {
214             notifyUsers(item.getId(), item.getName(), user, this.notificationType);
215             activityLogManager.logActivity(
216                     new ActivityLogEntity(item.getId(), getLatestVersion(item.getId()), this.activityType, user, true,
217                             "", ""));
218         }
219
220         private void notifyUsers(String itemId, String itemName, String userName, NotificationEventTypes eventType) {
221             Map<String, Object> eventProperties = new HashMap<>();
222             eventProperties.put(ITEM_NAME, itemName == null ? itemManager.get(itemId).getName() : itemName);
223             eventProperties.put(ITEM_ID, itemId);
224
225             eventProperties.put(PERMISSION_USER, userName);
226
227             Event syncEvent = new SyncEvent(eventType.getEventName(), itemId, eventProperties, itemId);
228             try {
229                 notifier.notifySubscribers(syncEvent, userName);
230             } catch (Exception e) {
231                 LOGGER.error("Failed to send sync notification to users subscribed to item '" + itemId);
232             }
233         }
234     }
235
236     private Predicate<Item> createItemPredicate(String itemStatusFilter, String versionStatusFilter,
237             String itemTypeFilter, String onboardingMethodFilter, String permissionsFilter, String user) {
238         Predicate<Item> itemPredicate = item -> true;
239
240         if (itemStatusFilter != null) {
241             validateItemStatusValue(itemStatusFilter);
242             itemPredicate = itemPredicate.and(createItemStatusPredicate(itemStatusFilter));
243         }
244         if (versionStatusFilter != null) {
245             validateVersionStatusValue(versionStatusFilter);
246             itemPredicate = itemPredicate.and(createVersionStatusPredicate(versionStatusFilter));
247         }
248         if (itemTypeFilter != null) {
249             validateItemTypeValue(itemTypeFilter);
250             itemPredicate = itemPredicate.and(createItemTypePredicate(itemTypeFilter));
251         }
252         if (onboardingMethodFilter != null) {
253             validateOnboardingMethodValue(onboardingMethodFilter);
254             itemPredicate = itemPredicate.and(createOnboardingMethodPredicate(onboardingMethodFilter));
255         }
256         if (permissionsFilter != null) {
257             validatePermissionValue(permissionsFilter);
258             itemPredicate = itemPredicate.and(createPermissionsPredicate(user, permissionsFilter));
259         }
260         return itemPredicate;
261     }
262
263     private String formatFilter(String filterValue) {
264         return filterValue.replace(",", "|");
265     }
266
267     private Predicate<Item> createItemStatusPredicate(String filterValue) {
268         return item -> item.getStatus().name().matches(formatFilter(filterValue));
269     }
270
271     private Predicate<Item> createVersionStatusPredicate(String filterValue) {
272         Set<VersionStatus> versionStatuses =
273                 Arrays.stream(filterValue.split(",")).map(VersionStatus::valueOf).collect(Collectors.toSet());
274         return item -> item.getVersionStatusCounters().keySet().stream().anyMatch(versionStatuses::contains);
275     }
276
277     private Predicate<Item> createItemTypePredicate(String filterValue) {
278         return item -> item.getType().matches(formatFilter(filterValue));
279     }
280
281     private Predicate<Item> createOnboardingMethodPredicate(String filterValue) {
282         return item -> !ItemType.vsp.name().equals(item.getType()) || ((String) item.getProperties()
283                                                                                     .get(ONBOARDING_METHOD))
284                                                                               .matches(formatFilter(filterValue));
285     }
286
287     private Predicate<Item> createPermissionsPredicate(String user, String filterValue) {
288         String[] permissions = filterValue.split(",");
289         Set<String> itemIds = new HashSet<>();
290         for (String permission : permissions) {
291             itemIds.addAll(permissionsManager.listUserPermittedItems(user, permission));
292         }
293         return item -> itemIds.contains(item.getId());
294     }
295
296     private void validateItemStatusValue(String itemStatusFilter) {
297         String[] values = itemStatusFilter.split(",");
298         for (String value : values) {
299             ItemStatus.valueOf(value);
300         }
301     }
302
303     private void validateVersionStatusValue(String versionStatusFilter) {
304         String[] values = versionStatusFilter.split(",");
305         for (String value : values) {
306             VersionStatus.valueOf(value);
307         }
308
309     }
310
311     private void validateItemTypeValue(String itemTypeFilter) {
312         String[] values = itemTypeFilter.split(",");
313         for (String value : values) {
314             ItemType.valueOf(value);
315         }
316     }
317
318     private void validateOnboardingMethodValue(String onboardingMethodFilter) {
319         String[] values = onboardingMethodFilter.split(",");
320         for (String value : values) {
321             OnboardingMethod.valueOf(value);
322         }
323     }
324
325     private void validatePermissionValue(String permissionsFilter) {
326         String[] values = permissionsFilter.split(",");
327         for (String value : values) {
328             PermissionTypes.valueOf(value);
329         }
330     }
331
332     //Do not delete - is in use, duplicates code to prevent dependency on openecomp-sdc-vendor-software-product-api
333     private enum OnboardingMethod {
334         NetworkPackage, Manual;
335     }
336 }