| /******************************************************************************** |
| * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation |
| * |
| * See the NOTICE file(s) distributed with this work for additional |
| * information regarding copyright ownership. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| ********************************************************************************/ |
| |
| package org.eclipse.mdm.shoppingbasket.boundary; |
| |
| import java.net.URI; |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.stream.Collectors; |
| |
| import javax.inject.Inject; |
| import javax.ws.rs.Consumes; |
| import javax.ws.rs.POST; |
| import javax.ws.rs.Path; |
| import javax.ws.rs.Produces; |
| import javax.ws.rs.WebApplicationException; |
| import javax.ws.rs.core.Context; |
| import javax.ws.rs.core.MediaType; |
| import javax.ws.rs.core.Response; |
| import javax.ws.rs.core.Response.Status; |
| import javax.ws.rs.core.UriInfo; |
| |
| import org.eclipse.mdm.api.base.model.Channel; |
| import org.eclipse.mdm.api.base.model.ChannelGroup; |
| import org.eclipse.mdm.api.base.model.Entity; |
| import org.eclipse.mdm.api.base.model.Measurement; |
| import org.eclipse.mdm.api.base.model.Test; |
| import org.eclipse.mdm.api.base.model.TestStep; |
| import org.eclipse.mdm.api.dflt.ApplicationContext; |
| import org.eclipse.mdm.api.dflt.EntityManager; |
| import org.eclipse.mdm.api.dflt.model.Pool; |
| import org.eclipse.mdm.api.dflt.model.Project; |
| import org.eclipse.mdm.connector.boundary.ConnectorService; |
| import org.eclipse.mdm.shoppingbasket.entity.BasketItem; |
| import org.eclipse.mdm.shoppingbasket.entity.MDMItem; |
| import org.eclipse.mdm.shoppingbasket.entity.ShoppingBasket; |
| import org.eclipse.mdm.shoppingbasket.entity.ShoppingBasketRequest; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| import com.google.common.collect.ImmutableMap; |
| |
| import io.swagger.v3.oas.annotations.tags.Tag; |
| |
| /** |
| * {@link ShoppingBasketResource} resource |
| * |
| */ |
| @Tag(name = "ShoppingBasket") |
| @Path("/shoppingbasket") |
| public class ShoppingBasketResource { |
| |
| private static final Logger LOG = LoggerFactory.getLogger(ShoppingBasketResource.class); |
| |
| private ConnectorService connectorService; |
| |
| @Context |
| private UriInfo uriInfo; |
| |
| private static final Map<Class<? extends Entity>, String> ENTITY2FRAGMENT_URI = ImmutableMap |
| .<Class<? extends Entity>, String>builder().put(Project.class, "projects").put(Pool.class, "pools") |
| .put(Test.class, "tests").put(TestStep.class, "teststeps").put(Measurement.class, "measurements") |
| .put(ChannelGroup.class, "channelgroups").put(Channel.class, "channels").build(); |
| |
| private static final Map<String, Class<? extends Entity>> ENTITYNAME2CLASS = ImmutableMap |
| .<String, Class<? extends Entity>>builder().put("Project", Project.class).put("Pool", Pool.class) |
| .put("Test", Test.class).put("TestStep", TestStep.class).put("Measurement", Measurement.class) |
| .put("ChannelGroup", ChannelGroup.class).put("Channel", Channel.class).build(); |
| |
| /** |
| * @param connectorService {@link ConnectorService} |
| */ |
| @Inject |
| ShoppingBasketResource(ConnectorService connectorService) { |
| this.connectorService = connectorService; |
| } |
| |
| /** |
| * Returns a shopping basket XML file containing the requested MDM items |
| * |
| * @param items list with items the shopping basket should contain. |
| * @return a XML file the the shopping basket information. |
| */ |
| @POST |
| @Consumes(MediaType.APPLICATION_JSON) |
| @Produces(MediaType.APPLICATION_XML) |
| public Response getShoppingbasket(ShoppingBasketRequest items) { |
| try { |
| return Response.ok(convertItemsToShoppingBasket(items), MediaType.APPLICATION_XML_TYPE).build(); |
| } catch (RuntimeException e) { |
| LOG.error(e.getMessage(), e); |
| throw new WebApplicationException(e.getMessage(), e, Status.INTERNAL_SERVER_ERROR); |
| } |
| |
| } |
| |
| /** |
| * Converts a {@link ShoppingBasketRequest} into a {@link ShoppingBasket} by |
| * generating the link and REST URIs for the given MDM items. |
| * |
| * @param items MDM items to convert |
| * @return a shopping basket representing the given MDM items |
| */ |
| private ShoppingBasket convertItemsToShoppingBasket(ShoppingBasketRequest items) { |
| List<BasketItem> basketItems = new ArrayList<>(); |
| Map<String, List<MDMItem>> itemsBySource = items.getItems().stream() |
| .collect(Collectors.groupingBy(MDMItem::getSource)); |
| |
| for (Map.Entry<String, List<MDMItem>> entry : itemsBySource.entrySet()) { |
| ApplicationContext context = connectorService.getContextByName(entry.getKey()); |
| EntityManager em = context.getEntityManager().orElseThrow(() -> new IllegalArgumentException( |
| "Not connected to ApplicationContext with name " + entry.getKey())); |
| |
| List<Entity> entities = entry.getValue().stream().map(i -> getEntity(em, i)).collect(Collectors.toList()); |
| |
| for (Map.Entry<Entity, String> e : em.getLinks(entities).entrySet()) { |
| |
| BasketItem basketItem = new BasketItem(); |
| basketItem.setSource(context.getAdapterType()); |
| basketItem.setLink(e.getValue()); |
| basketItem.setRestURI(getURIForEntity(e.getKey())); |
| |
| basketItems.add(basketItem); |
| } |
| } |
| |
| ShoppingBasket basket = new ShoppingBasket(); |
| basket.setName(items.getName()); |
| basket.setItems(basketItems); |
| return basket; |
| } |
| |
| /** |
| * Generate the REST URI for a Entity |
| * |
| * @param entity Entity |
| * @return the REST URI of the given Entity |
| */ |
| private URI getURIForEntity(Entity entity) { |
| return uriInfo.getBaseUriBuilder().path("environments").path(entity.getSourceName()) |
| .path(getURIFragmentForEntity(entity)).path(entity.getID()).build(); |
| } |
| |
| /** |
| * Returns the URI fragment of a entity. For example, if entity is an instance |
| * of {@link TestStep} the string "teststeps" is returned. |
| * |
| * @param entity |
| * @return the URI fragment of the Entity's EntityType |
| */ |
| private String getURIFragmentForEntity(Entity entity) { |
| |
| for (Map.Entry<Class<? extends Entity>, String> entry : ENTITY2FRAGMENT_URI.entrySet()) { |
| if (entry.getKey().isInstance(entity)) { |
| return entry.getValue(); |
| } |
| } |
| // fallback to generic fragment |
| return entity.getClass().getSimpleName().toLowerCase() + "s"; |
| } |
| |
| /** |
| * Loads the entity specified by the given MDM item. |
| * |
| * @param em {@link EntityManager} used to load the entity. |
| * @param item MDM item to load based on its type and id. |
| * @return the loaded Entity |
| */ |
| private Entity getEntity(EntityManager em, MDMItem item) { |
| for (Map.Entry<String, Class<? extends Entity>> entry : ENTITYNAME2CLASS.entrySet()) { |
| if (item.getType().equals(entry.getKey())) { |
| return em.load(entry.getValue(), item.getId()); |
| } |
| } |
| throw new IllegalArgumentException("Cannot load type: " + item.getType()); |
| } |
| } |