2 * Copyright © 2018 European Support Limited
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package org.openecomp.sdcrests.item.rest.services;
18 import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR;
19 import static javax.ws.rs.core.Response.Status.NOT_FOUND;
20 import static org.openecomp.sdc.itempermissions.notifications.NotificationConstants.PERMISSION_USER;
21 import static org.openecomp.sdc.versioning.VersioningNotificationConstansts.ITEM_ID;
22 import static org.openecomp.sdc.versioning.VersioningNotificationConstansts.ITEM_NAME;
24 import com.google.common.annotations.VisibleForTesting;
25 import java.util.Arrays;
26 import java.util.Collections;
27 import java.util.EnumMap;
28 import java.util.HashMap;
29 import java.util.HashSet;
30 import java.util.List;
32 import java.util.Optional;
34 import java.util.function.Predicate;
35 import java.util.stream.Collectors;
36 import javax.annotation.PostConstruct;
37 import javax.inject.Named;
38 import javax.ws.rs.core.Response;
39 import org.openecomp.sdc.activitylog.dao.type.ActivityLogEntity;
40 import org.openecomp.sdc.activitylog.dao.type.ActivityType;
41 import org.openecomp.sdc.be.csar.storage.StorageFactory;
42 import org.openecomp.sdc.common.errors.ErrorCode.ErrorCodeBuilder;
43 import org.openecomp.sdc.common.errors.ErrorCodeAndMessage;
44 import org.openecomp.sdc.datatypes.model.ItemType;
45 import org.openecomp.sdc.itempermissions.impl.types.PermissionTypes;
46 import org.openecomp.sdc.logging.api.Logger;
47 import org.openecomp.sdc.logging.api.LoggerFactory;
48 import org.openecomp.sdc.notification.dtos.Event;
49 import org.openecomp.sdc.versioning.dao.types.Version;
50 import org.openecomp.sdc.versioning.dao.types.VersionStatus;
51 import org.openecomp.sdc.versioning.types.Item;
52 import org.openecomp.sdc.versioning.types.ItemStatus;
53 import org.openecomp.sdc.versioning.types.NotificationEventTypes;
54 import org.openecomp.sdcrests.item.rest.Items;
55 import org.openecomp.sdcrests.item.rest.mapping.MapItemToDto;
56 import org.openecomp.sdcrests.item.rest.models.SyncEvent;
57 import org.openecomp.sdcrests.item.rest.services.catalog.notification.NotifierFactory;
58 import org.openecomp.sdcrests.item.types.ItemAction;
59 import org.openecomp.sdcrests.item.types.ItemActionRequestDto;
60 import org.openecomp.sdcrests.item.types.ItemDto;
61 import org.openecomp.sdcrests.wrappers.GenericCollectionWrapper;
62 import org.springframework.context.annotation.Scope;
63 import org.springframework.stereotype.Service;
64 import org.springframework.validation.annotation.Validated;
68 @Scope(value = "prototype")
70 public class ItemsImpl implements Items {
72 private static final String ONBOARDING_METHOD = "onboardingMethod";
73 private static final Logger LOGGER = LoggerFactory.getLogger(ItemsImpl.class);
74 private Map<ItemAction, ActionSideAffects> actionSideAffectsMap = new EnumMap<>(ItemAction.class);
75 private ManagersProvider managersProvider;
78 public void initActionSideAffectsMap() {
79 actionSideAffectsMap.put(ItemAction.ARCHIVE, new ActionSideAffects(ActivityType.Archive, NotificationEventTypes.ARCHIVE));
80 actionSideAffectsMap.put(ItemAction.RESTORE, new ActionSideAffects(ActivityType.Restore, NotificationEventTypes.RESTORE));
84 public Response actOn(final ItemActionRequestDto request, final String itemId, final String user) {
85 final var item = getManagersProvider().getItemManager().get(itemId);
87 return Response.status(NOT_FOUND).entity(new Exception("Item does not exist.")).build();
89 final var action = request.getAction();
92 getManagersProvider().getItemManager().archive(item);
95 if (ItemType.vsp.getName().equalsIgnoreCase(item.getType())) {
96 final var artifactStorageManager = new StorageFactory().createArtifactStorageManager();
97 if (artifactStorageManager.isEnabled() && !artifactStorageManager.exists(itemId)) {
98 LOGGER.error("Unable to restore partially deleted item '{}'", itemId);
100 new ErrorCodeBuilder().withId(INTERNAL_SERVER_ERROR.name()).withMessage("Unable to restore partially deleted VSP, re-try VSP deletion").build();
101 return Response.status(INTERNAL_SERVER_ERROR).entity(new ErrorCodeAndMessage(INTERNAL_SERVER_ERROR, errorCode)).build();
104 getManagersProvider().getItemManager().restore(item);
108 actionSideAffectsMap.get(action).execute(item, user);
110 NotifierFactory.getInstance().execute(Collections.singleton(itemId), action);
111 } catch (Exception e) {
112 LOGGER.error("Failed to send catalog notification on item {}", itemId, e);
114 return Response.ok().build();
118 public Response list(String itemStatusFilter, String versionStatusFilter, String itemTypeFilter, String permissionFilter,
119 String onboardingMethodFilter, String user) {
120 Predicate<Item> itemPredicate = createItemPredicate(itemStatusFilter, versionStatusFilter, itemTypeFilter, onboardingMethodFilter,
121 permissionFilter, user);
122 GenericCollectionWrapper<ItemDto> results = new GenericCollectionWrapper<>();
123 MapItemToDto mapper = new MapItemToDto();
124 getManagersProvider().getItemManager().list(itemPredicate).stream()
125 .sorted((o1, o2) -> o2.getModificationTime().compareTo(o1.getModificationTime()))
126 .forEach(item -> results.add(mapper.applyMapping(item, ItemDto.class)));
127 return Response.ok(results).build();
131 public Response getItem(String itemId, String user) {
132 Item item = getManagersProvider().getItemManager().get(itemId);
133 ItemDto itemDto = new MapItemToDto().applyMapping(item, ItemDto.class);
134 return Response.ok(itemDto).build();
137 private Predicate<Item> createItemPredicate(String itemStatusFilter, String versionStatusFilter, String itemTypeFilter,
138 String onboardingMethodFilter, String permissionsFilter, String user) {
139 Predicate<Item> itemPredicate = item -> true;
140 if (itemStatusFilter != null) {
141 validateItemStatusValue(itemStatusFilter);
142 itemPredicate = itemPredicate.and(createItemStatusPredicate(itemStatusFilter));
144 if (versionStatusFilter != null) {
145 validateVersionStatusValue(versionStatusFilter);
146 itemPredicate = itemPredicate.and(createVersionStatusPredicate(versionStatusFilter));
148 if (itemTypeFilter != null) {
149 validateItemTypeValue(itemTypeFilter);
150 itemPredicate = itemPredicate.and(createItemTypePredicate(itemTypeFilter));
152 if (onboardingMethodFilter != null) {
153 validateOnboardingMethodValue(onboardingMethodFilter);
154 itemPredicate = itemPredicate.and(createOnboardingMethodPredicate(onboardingMethodFilter));
156 if (permissionsFilter != null) {
157 validatePermissionValue(permissionsFilter);
158 itemPredicate = itemPredicate.and(createPermissionsPredicate(user, permissionsFilter));
160 return itemPredicate;
163 private String formatFilter(String filterValue) {
164 return filterValue.replace(",", "|");
167 private Predicate<Item> createItemStatusPredicate(String filterValue) {
168 return item -> item.getStatus().name().matches(formatFilter(filterValue));
171 private Predicate<Item> createVersionStatusPredicate(String filterValue) {
172 Set<VersionStatus> versionStatuses = Arrays.stream(filterValue.split(",")).map(VersionStatus::valueOf).collect(Collectors.toSet());
173 return item -> item.getVersionStatusCounters().keySet().stream().anyMatch(versionStatuses::contains);
176 private Predicate<Item> createItemTypePredicate(String filterValue) {
177 return item -> item.getType().matches(formatFilter(filterValue));
180 private Predicate<Item> createOnboardingMethodPredicate(String filterValue) {
181 return item -> !ItemType.vsp.name().equals(item.getType()) || ((String) item.getProperties().get(ONBOARDING_METHOD))
182 .matches(formatFilter(filterValue));
185 private Predicate<Item> createPermissionsPredicate(String user, String filterValue) {
186 String[] permissions = filterValue.split(",");
187 Set<String> itemIds = new HashSet<>();
188 for (String permission : permissions) {
189 itemIds.addAll(getManagersProvider().getPermissionsManager().listUserPermittedItems(user, permission));
191 return item -> itemIds.contains(item.getId());
194 private void validateItemStatusValue(String itemStatusFilter) {
195 String[] values = itemStatusFilter.split(",");
196 for (String value : values) {
197 ItemStatus.valueOf(value);
201 private void validateVersionStatusValue(String versionStatusFilter) {
202 String[] values = versionStatusFilter.split(",");
203 for (String value : values) {
204 VersionStatus.valueOf(value);
208 private void validateItemTypeValue(String itemTypeFilter) {
209 String[] values = itemTypeFilter.split(",");
210 for (String value : values) {
211 ItemType.valueOf(value);
215 private void validateOnboardingMethodValue(String onboardingMethodFilter) {
216 String[] values = onboardingMethodFilter.split(",");
217 for (String value : values) {
218 OnboardingMethod.valueOf(value);
222 private void validatePermissionValue(String permissionsFilter) {
223 String[] values = permissionsFilter.split(",");
224 for (String value : values) {
225 PermissionTypes.valueOf(value);
230 Map<ItemAction, ActionSideAffects> getActionSideAffectsMap() {
231 return actionSideAffectsMap;
234 private ManagersProvider getManagersProvider() {
235 if (managersProvider == null) {
236 managersProvider = new ManagersProvider();
238 return managersProvider;
242 void setManagersProvider(ManagersProvider managersProvider) {
243 this.managersProvider = managersProvider;
246 //Do not delete - is in use, duplicates code to prevent dependency on openecomp-sdc-vendor-software-product-api
247 private enum OnboardingMethod {NetworkPackage, Manual}
249 private class ActionSideAffects {
251 private ActivityType activityType;
252 private NotificationEventTypes notificationType;
254 private ActionSideAffects(ActivityType activityType, NotificationEventTypes notificationType) {
255 this.activityType = activityType;
256 this.notificationType = notificationType;
259 private Version getLatestVersion(String itemId) {
260 List<Version> list = getManagersProvider().getVersioningManager().list(itemId);
261 Optional<Version> max = list.stream().max(Version::compareTo);
262 return max.orElse(null);
265 private void execute(Item item, String user) {
266 notifyUsers(item.getId(), item.getName(), user, this.notificationType);
267 getManagersProvider().getActivityLogManager()
268 .logActivity(new ActivityLogEntity(item.getId(), getLatestVersion(item.getId()), this.activityType, user, true, "", ""));
271 private void notifyUsers(String itemId, String itemName, String userName, NotificationEventTypes eventType) {
272 Map<String, Object> eventProperties = new HashMap<>();
273 eventProperties.put(ITEM_NAME, itemName == null ? getManagersProvider().getItemManager().get(itemId).getName() : itemName);
274 eventProperties.put(ITEM_ID, itemId);
275 eventProperties.put(PERMISSION_USER, userName);
276 Event syncEvent = new SyncEvent(eventType.getEventName(), itemId, eventProperties, itemId);
278 getManagersProvider().getNotificationPropagationManager().notifySubscribers(syncEvent, userName);
279 } catch (Exception e) {
280 LOGGER.error("Failed to send sync notification to users subscribed to item '{}'", itemId, e);