package org.cytoscape.rest.internal.resource;
import java.io.IOException;
import java.io.InputStream;
import java.util.Set;
import javax.inject.Singleton;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.cytoscape.group.CyGroup;
import org.cytoscape.group.CyGroupFactory;
import org.cytoscape.group.CyGroupManager;
import org.cytoscape.model.CyNetwork;
import org.cytoscape.model.CyNode;
import org.cytoscape.model.subnetwork.CySubNetwork;
import org.cytoscape.rest.internal.datamapper.GroupMapper;
import org.cytoscape.rest.internal.serializer.GroupModule;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
@Singleton
@Path("/v1/networks/{networkId}/groups")
public class GroupResource extends AbstractResource {
private final ObjectMapper groupMapper;
private final GroupMapper mapper;
@Context
private CyGroupFactory groupFactory;
@Context
private CyGroupManager groupManager;
public GroupResource() {
super();
this.groupMapper = new ObjectMapper();
this.groupMapper.registerModule(new GroupModule());
this.mapper = new GroupMapper();
}
/**
* @summary Get all groups in the network
*
* @param networkId
* Network SUID
*
* @return List of all groups in the network
*
*/
@GET
@Path("/")
@Produces(MediaType.APPLICATION_JSON)
public String getAllGroups(@PathParam("networkId") Long networkId) {
final CyNetwork network = getCyNetwork(networkId);
final Set<CyGroup> groups = groupManager.getGroupSet(network);
try {
return this.groupMapper.writeValueAsString(groups);
} catch (JsonProcessingException e) {
throw getError("Could not serialize groups.", e, Response.Status.INTERNAL_SERVER_ERROR);
}
}
/**
*
* @summary Get number of groups in the network
*
* @param networkId
* Network SUID
*
* @return Number of groups in the network
*/
@GET
@Path("/count")
@Produces(MediaType.APPLICATION_JSON)
public String getGroupCount(@PathParam("networkId") Long networkId) {
final CyNetwork network = getCyNetwork(networkId);
return getNumberObjectString(JsonTags.COUNT, groupManager.getGroupSet(network).size());
}
/**
* @summary Get group for a node
*
* @param networkId
* Networks SUID
* @param groupNodeId
* Group Node SUID
*
* @return A group where the node belongs to
*/
@GET
@Path("/{groupNodeId}")
@Produces(MediaType.APPLICATION_JSON)
public String getGroup(@PathParam("networkId") Long networkId, @PathParam("groupNodeId") Long nodeId) {
final CyNetwork network = getCyNetwork(networkId);
final CyNode node = network.getNode(nodeId);
if (node == null) {
throw new NotFoundException("Could not find the node with SUID: " + nodeId);
}
final CyGroup group = groupManager.getGroup(node, network);
if (group == null) {
throw new NotFoundException("Could not find group.");
}
try {
return groupMapper.writeValueAsString(group);
} catch (JsonProcessingException e) {
throw getError("Could not serialize Group.", e, Response.Status.INTERNAL_SERVER_ERROR);
}
}
/**
* @summary Delete all groups in the network
*
* @param networkId
* Network SUID
*
*/
@DELETE
@Path("/")
public void deleteAllGroups(@PathParam("networkId") Long networkId) {
final CyNetwork network = getCyNetwork(networkId);
final Set<CyGroup> groups = groupManager.getGroupSet(network);
try {
for (final CyGroup group : groups) {
groupManager.destroyGroup(group);
}
} catch (Exception e) {
throw getError("Could not delete group.", e, Response.Status.INTERNAL_SERVER_ERROR);
}
}
/**
*
* @summary Delete a group
*
* @param networkId
* Network SUID
* @param groupNodeId
* Group node SUID
*/
@DELETE
@Path("/{groupNodeId}")
public void deleteGroup(@PathParam("networkId") Long networkId, @PathParam("groupNodeId") Long groupNodeId) {
final CyGroup group = getGroupById(networkId, groupNodeId);
try {
groupManager.destroyGroup(group);
} catch (Exception e) {
throw getError("Could not delete group.", e, Response.Status.INTERNAL_SERVER_ERROR);
}
}
/**
* @summary Expand group nodes
*
* @param networkId
* Network SUID
* @param groupNodeId
* Group node SUID
*
*/
@GET
@Path("/{groupNodeId}/expand")
public void expandGroup(@PathParam("networkId") Long networkId, @PathParam("groupNodeId") Long groupNodeId) {
toggle(networkId, groupNodeId, false);
}
/**
* @summary Collapse group nodes
*
* @param networkId
* Network SUID
* @param groupNodeId
* Group node SUID
*
*/
@GET
@Path("/{groupNodeId}/collapse")
public void collapseGroup(@PathParam("networkId") Long networkId, @PathParam("groupNodeId") Long groupNodeId) {
toggle(networkId, groupNodeId, true);
}
private final void toggle(final Long networkId, final Long suid, boolean collapse) {
final CyGroup group = getGroupById(networkId, suid);
final CyNetwork network = getCyNetwork(networkId);
try {
if (collapse) {
group.collapse(network);
} else {
group.expand(network);
}
} catch (Exception e) {
throw getError("Could not toggle group state. Collapse: " + collapse, e, Response.Status.INTERNAL_SERVER_ERROR);
}
}
private final CyGroup getGroupById(final Long networkId, final Long suid) {
final CyNetwork network = getCyNetwork(networkId);
CyNode node = network.getNode(suid);
if (node == null) {
node = ((CySubNetwork) network).getRootNetwork().getNode(suid);
if (node == null)
throw new NotFoundException("Could not find the node with SUID: " + suid);
}
final CyGroup group = groupManager.getGroup(node, network);
if (group == null) {
throw new NotFoundException("Could not find group.");
}
return group;
}
/**
* Create a new group from a list of nodes. The Body should be in the following format:
*
* <pre>
* {
* "name": (New group node name),
* "nodes": [
* nodeSUID1, nodeSUID2, ...
* ]
* }
* </pre>
*
*
* @summary Create a new group
*
* @param networkId
* Network SUID
*
* @return New group node's SUID
*
*/
@POST
@Path("/")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String createGroup(@PathParam("networkId") Long networkId, final InputStream is) {
final CyNetwork network = getCyNetwork(networkId);
final ObjectMapper objMapper = new ObjectMapper();
JsonNode rootNode = null;
try {
rootNode = objMapper.readValue(is, JsonNode.class);
} catch (IOException ex) {
throw getError("Could not create JSON root node.", ex, Response.Status.INTERNAL_SERVER_ERROR);
}
try {
final CyGroup newGroup = mapper.createGroup(rootNode, groupFactory, network);
return getNumberObjectString("groupSUID", newGroup.getGroupNode().getSUID());
} catch (Exception e) {
throw getError("Could not create group.", e, Response.Status.INTERNAL_SERVER_ERROR);
}
}
}