blob: 3983d39d6feb8252df2858eb989dd97ed2d2c339 [file] [log] [blame]
/********************************************************************************
* 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());
}
}