f18de668634b1c4b15c672761c94fdd9b0e2195f
[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 package org.openecomp.sdcrests.item.rest.services;
17
18 import static org.openecomp.sdc.itempermissions.notifications.NotificationConstants.PERMISSION_USER;
19 import static org.openecomp.sdc.versioning.VersioningNotificationConstansts.ITEM_ID;
20 import static org.openecomp.sdc.versioning.VersioningNotificationConstansts.ITEM_NAME;
21
22 import com.google.common.annotations.VisibleForTesting;
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.dao.type.ActivityLogEntity;
38 import org.openecomp.sdc.activitylog.dao.type.ActivityType;
39 import org.openecomp.sdc.datatypes.model.ItemType;
40 import org.openecomp.sdc.itempermissions.impl.types.PermissionTypes;
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.versioning.dao.types.Version;
45 import org.openecomp.sdc.versioning.dao.types.VersionStatus;
46 import org.openecomp.sdc.versioning.types.Item;
47 import org.openecomp.sdc.versioning.types.ItemStatus;
48 import org.openecomp.sdc.versioning.types.NotificationEventTypes;
49 import org.openecomp.sdcrests.item.rest.Items;
50 import org.openecomp.sdcrests.item.rest.mapping.MapItemToDto;
51 import org.openecomp.sdcrests.item.rest.models.SyncEvent;
52 import org.openecomp.sdcrests.item.rest.services.catalog.notification.Notifier;
53 import org.openecomp.sdcrests.item.rest.services.catalog.notification.NotifierFactory;
54 import org.openecomp.sdcrests.item.types.ItemAction;
55 import org.openecomp.sdcrests.item.types.ItemActionRequestDto;
56 import org.openecomp.sdcrests.item.types.ItemDto;
57 import org.openecomp.sdcrests.wrappers.GenericCollectionWrapper;
58 import org.springframework.context.annotation.Scope;
59 import org.springframework.stereotype.Service;
60 import org.springframework.validation.annotation.Validated;
61
62 @Named
63 @Service("items")
64 @Scope(value = "prototype")
65 @Validated
66 public class ItemsImpl implements Items {
67
68     private static final String ONBOARDING_METHOD = "onboardingMethod";
69     private static final Logger LOGGER = LoggerFactory.getLogger(ItemsImpl.class);
70     private Map<ItemAction, ActionSideAffects> actionSideAffectsMap = new EnumMap<>(ItemAction.class);
71     private ManagersProvider managersProvider;
72
73     @PostConstruct
74     public void initActionSideAffectsMap() {
75         actionSideAffectsMap.put(ItemAction.ARCHIVE, new ActionSideAffects(ActivityType.Archive, NotificationEventTypes.ARCHIVE));
76         actionSideAffectsMap.put(ItemAction.RESTORE, new ActionSideAffects(ActivityType.Restore, NotificationEventTypes.RESTORE));
77     }
78
79     @Override
80     public Response actOn(ItemActionRequestDto request, String itemId, String user) {
81         Item item = getManagersProvider().getItemManager().get(itemId);
82         if (item == null) {
83             return Response.status(Response.Status.NOT_FOUND).entity(new Exception("Item does not exist.")).build();
84         }
85         switch (request.getAction()) {
86             case ARCHIVE:
87                 getManagersProvider().getItemManager().archive(item);
88                 break;
89             case RESTORE:
90                 getManagersProvider().getItemManager().restore(item);
91                 break;
92             default:
93         }
94         actionSideAffectsMap.get(request.getAction()).execute(item, user);
95         try {
96             Notifier catalogNotifier = NotifierFactory.getInstance();
97             catalogNotifier.execute(Collections.singleton(itemId), request.getAction());
98         } catch (Exception e) {
99             LOGGER.error("Failed to send catalog notification on item {}", itemId, e);
100         }
101         return Response.ok().build();
102     }
103
104     @Override
105     public Response list(String itemStatusFilter, String versionStatusFilter, String itemTypeFilter, String permissionFilter,
106                          String onboardingMethodFilter, String user) {
107         Predicate<Item> itemPredicate = createItemPredicate(itemStatusFilter, versionStatusFilter, itemTypeFilter, onboardingMethodFilter,
108             permissionFilter, user);
109         GenericCollectionWrapper<ItemDto> results = new GenericCollectionWrapper<>();
110         MapItemToDto mapper = new MapItemToDto();
111         getManagersProvider().getItemManager().list(itemPredicate).stream()
112             .sorted((o1, o2) -> o2.getModificationTime().compareTo(o1.getModificationTime()))
113             .forEach(item -> results.add(mapper.applyMapping(item, ItemDto.class)));
114         return Response.ok(results).build();
115     }
116
117     @Override
118     public Response getItem(String itemId, String user) {
119         Item item = getManagersProvider().getItemManager().get(itemId);
120         ItemDto itemDto = new MapItemToDto().applyMapping(item, ItemDto.class);
121         return Response.ok(itemDto).build();
122     }
123
124     private Predicate<Item> createItemPredicate(String itemStatusFilter, String versionStatusFilter, String itemTypeFilter,
125                                                 String onboardingMethodFilter, String permissionsFilter, String user) {
126         Predicate<Item> itemPredicate = item -> true;
127         if (itemStatusFilter != null) {
128             validateItemStatusValue(itemStatusFilter);
129             itemPredicate = itemPredicate.and(createItemStatusPredicate(itemStatusFilter));
130         }
131         if (versionStatusFilter != null) {
132             validateVersionStatusValue(versionStatusFilter);
133             itemPredicate = itemPredicate.and(createVersionStatusPredicate(versionStatusFilter));
134         }
135         if (itemTypeFilter != null) {
136             validateItemTypeValue(itemTypeFilter);
137             itemPredicate = itemPredicate.and(createItemTypePredicate(itemTypeFilter));
138         }
139         if (onboardingMethodFilter != null) {
140             validateOnboardingMethodValue(onboardingMethodFilter);
141             itemPredicate = itemPredicate.and(createOnboardingMethodPredicate(onboardingMethodFilter));
142         }
143         if (permissionsFilter != null) {
144             validatePermissionValue(permissionsFilter);
145             itemPredicate = itemPredicate.and(createPermissionsPredicate(user, permissionsFilter));
146         }
147         return itemPredicate;
148     }
149
150     private String formatFilter(String filterValue) {
151         return filterValue.replace(",", "|");
152     }
153
154     private Predicate<Item> createItemStatusPredicate(String filterValue) {
155         return item -> item.getStatus().name().matches(formatFilter(filterValue));
156     }
157
158     private Predicate<Item> createVersionStatusPredicate(String filterValue) {
159         Set<VersionStatus> versionStatuses = Arrays.stream(filterValue.split(",")).map(VersionStatus::valueOf).collect(Collectors.toSet());
160         return item -> item.getVersionStatusCounters().keySet().stream().anyMatch(versionStatuses::contains);
161     }
162
163     private Predicate<Item> createItemTypePredicate(String filterValue) {
164         return item -> item.getType().matches(formatFilter(filterValue));
165     }
166
167     private Predicate<Item> createOnboardingMethodPredicate(String filterValue) {
168         return item -> !ItemType.vsp.name().equals(item.getType()) || ((String) item.getProperties().get(ONBOARDING_METHOD))
169             .matches(formatFilter(filterValue));
170     }
171
172     private Predicate<Item> createPermissionsPredicate(String user, String filterValue) {
173         String[] permissions = filterValue.split(",");
174         Set<String> itemIds = new HashSet<>();
175         for (String permission : permissions) {
176             itemIds.addAll(getManagersProvider().getPermissionsManager().listUserPermittedItems(user, permission));
177         }
178         return item -> itemIds.contains(item.getId());
179     }
180
181     private void validateItemStatusValue(String itemStatusFilter) {
182         String[] values = itemStatusFilter.split(",");
183         for (String value : values) {
184             ItemStatus.valueOf(value);
185         }
186     }
187
188     private void validateVersionStatusValue(String versionStatusFilter) {
189         String[] values = versionStatusFilter.split(",");
190         for (String value : values) {
191             VersionStatus.valueOf(value);
192         }
193     }
194
195     private void validateItemTypeValue(String itemTypeFilter) {
196         String[] values = itemTypeFilter.split(",");
197         for (String value : values) {
198             ItemType.valueOf(value);
199         }
200     }
201
202     private void validateOnboardingMethodValue(String onboardingMethodFilter) {
203         String[] values = onboardingMethodFilter.split(",");
204         for (String value : values) {
205             OnboardingMethod.valueOf(value);
206         }
207     }
208
209     private void validatePermissionValue(String permissionsFilter) {
210         String[] values = permissionsFilter.split(",");
211         for (String value : values) {
212             PermissionTypes.valueOf(value);
213         }
214     }
215
216     @VisibleForTesting
217     Map<ItemAction, ActionSideAffects> getActionSideAffectsMap() {
218         return actionSideAffectsMap;
219     }
220
221     private ManagersProvider getManagersProvider() {
222         if (managersProvider == null) {
223             managersProvider = new ManagersProvider();
224         }
225         return managersProvider;
226     }
227
228     @VisibleForTesting
229     void setManagersProvider(ManagersProvider managersProvider) {
230         this.managersProvider = managersProvider;
231     }
232
233     //Do not delete - is in use, duplicates code to prevent dependency on openecomp-sdc-vendor-software-product-api
234     private enum OnboardingMethod {NetworkPackage, Manual}
235
236     private class ActionSideAffects {
237
238         private ActivityType activityType;
239         private NotificationEventTypes notificationType;
240
241         private ActionSideAffects(ActivityType activityType, NotificationEventTypes notificationType) {
242             this.activityType = activityType;
243             this.notificationType = notificationType;
244         }
245
246         private Version getLatestVersion(String itemId) {
247             List<Version> list = getManagersProvider().getVersioningManager().list(itemId);
248             Optional<Version> max = list.stream().max(Version::compareTo);
249             return max.orElse(null);
250         }
251
252         private void execute(Item item, String user) {
253             notifyUsers(item.getId(), item.getName(), user, this.notificationType);
254             getManagersProvider().getActivityLogManager()
255                 .logActivity(new ActivityLogEntity(item.getId(), getLatestVersion(item.getId()), this.activityType, user, true, "", ""));
256         }
257
258         private void notifyUsers(String itemId, String itemName, String userName, NotificationEventTypes eventType) {
259             Map<String, Object> eventProperties = new HashMap<>();
260             eventProperties.put(ITEM_NAME, itemName == null ? getManagersProvider().getItemManager().get(itemId).getName() : itemName);
261             eventProperties.put(ITEM_ID, itemId);
262             eventProperties.put(PERMISSION_USER, userName);
263             Event syncEvent = new SyncEvent(eventType.getEventName(), itemId, eventProperties, itemId);
264             try {
265                 getManagersProvider().getNotificationPropagationManager().notifySubscribers(syncEvent, userName);
266             } catch (Exception e) {
267                 LOGGER.error("Failed to send sync notification to users subscribed to item '{}'", itemId, e);
268             }
269         }
270     }
271 }