Skip to content

Commit

Permalink
Improved documentation for Collections and Tables
Browse files Browse the repository at this point in the history
Also:

Added listType to column description, and upgraded Swagger to 1.5.17
  • Loading branch information
dotasek committed Dec 28, 2017
1 parent ec02d3b commit 668c4d5
Show file tree
Hide file tree
Showing 14 changed files with 228 additions and 67 deletions.
4 changes: 2 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -747,13 +747,13 @@
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.5.13</version>
<version>1.5.17</version>
</dependency>

<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-jersey2-jaxrs</artifactId>
<version>1.5.13</version>
<version>1.5.17</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,6 @@ public class CyRESTConstants {
public final static String getErrorURI(String resourceURI, int code) {
return cyRESTCIRoot + ":" + resourceURI + ":"+ cyRESTCIErrorRoot + ":"+ code;
}

public final static String cxLink = "http://manual.cytoscape.org/en/stable/Supported_Network_File_Formats.html#cytoscape-cx";
}
19 changes: 19 additions & 0 deletions src/main/java/org/cytoscape/rest/internal/model/CyColumnModel.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.cytoscape.rest.internal.model;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

@ApiModel(value="Cytoscape Column", description="A column definition in a Cytoscape table")
public class CyColumnModel {
@ApiModelProperty(value = "Column Name", required=true)
public String name;
@ApiModelProperty(value = "Column Data Type", allowableValues="Double,String,Boolean,Long,Integer,List", required=true)
public String type; //"data type, Double, String, Boolean, Long, Integer",
@ApiModelProperty(value="If the type of this column is list, this specifies the type of data in the list.", required=false)
public Boolean listType;
@ApiModelProperty(value="If true, this column is immutable.", required=true)
public Boolean immutable; //": "Optional: boolean value to specify immutable or not",
@ApiModelProperty(value="If true, this column acts as the primary key for this table.", required=true)
public Boolean primaryKey;// "local": "Optional. If true, it will be a local column"

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.cytoscape.rest.internal.model;

import java.util.List;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

@ApiModel(value="Cytoscape Column Values")
public class CyColumnValuesModel {
@ApiModelProperty(value = "Column Name", required=true)
public String name;
@ApiModelProperty(value = "Column Values", required=true)
public List<?> values;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.cytoscape.rest.internal.model;

import java.util.Collection;

import io.swagger.annotations.ApiModel;

@ApiModel(value="Cytoscape Column with Rows", description="A definition of a column from a Cytoscape table, and a list of its rows.")
public class CyColumnWithRowsModel extends CyColumnModel{
Collection<CyRowModel> rows;
}
16 changes: 16 additions & 0 deletions src/main/java/org/cytoscape/rest/internal/model/CyRowModel.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.cytoscape.rest.internal.model;

import io.swagger.annotations.ApiModel;

@ApiModel(value="Row Data", description="A map of column name to value.\n\n"
+ "```\n"
+ "{\n"
+ " \"id\": 12345,\n"
+ " \"gene_name\": \"brca1\",\n"
+ " \"exp1\": 0.11,\n"
+ " \"exp2\": 0.2\n"
+ "}\n"
+ "```")
public class CyRowModel{

}
27 changes: 27 additions & 0 deletions src/main/java/org/cytoscape/rest/internal/model/CyTableModel.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package org.cytoscape.rest.internal.model;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.gson.annotations.SerializedName;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

@ApiModel(value="Cytoscape Table", description="A Cytoscape table definition", subTypes= {CyTableWithRowsModel.class})
public class CyTableModel {
@ApiModelProperty(value = "Table SUID", required=true)
public Long SUID;

@ApiModelProperty(value = "Title", required=true)
public String title;

@ApiModelProperty(value = "Public", required=true)
@SerializedName("public")
@JsonProperty("public")
public boolean _public;

@ApiModelProperty(value = "Mutable", required=true)
public String mutable;

@ApiModelProperty(value = "Primary Key", required=true)
public String primaryKey;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.cytoscape.rest.internal.model;

import java.util.List;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

@ApiModel(value="Cytoscape Column with Rows", description="A definition of a column from a Cytoscape table, and a list of its rows.", parent=CyTableModel.class)
public class CyTableWithRowsModel extends CyTableModel{
@ApiModelProperty(value = "Rows", required=true)
public List<CyRowModel> rows;
}
12 changes: 0 additions & 12 deletions src/main/java/org/cytoscape/rest/internal/model/UpdateRow.java

This file was deleted.

25 changes: 25 additions & 0 deletions src/main/java/org/cytoscape/rest/internal/model/UpdateTable.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package org.cytoscape.rest.internal.model;

import java.util.List;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

@ApiModel(value="Table Update Data")
public class UpdateTable {
@ApiModelProperty(value = "The column in the target table to use as a key. If not specified, SUID will be used.", example="SUID")
public String key;
@ApiModelProperty(value = "The field in the row data to use as a key. If not specified, SUID will be used.", example="id")
public String dataKey;
@ApiModelProperty(value = "The row data with which to update the table.\n\nEach row entry should consist of pairs of keys and values, including one that supplies a value for the `dataKey` key. \n"
+ "```\n"
+ "[\n"
+ " {\n"
+ " \"id\": 12345,\n"
+ " \"gene_name\": \"brca1\",\n"
+ " \"exp1\": 0.11,\n"
+ " \"exp2\": 0.2\n"
+ " },...\n"
+ "]\n"
+ "```\n", required=true)
public List<CyRowModel> data;
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,19 @@
import org.cytoscape.model.subnetwork.CyRootNetwork;
import org.cytoscape.model.subnetwork.CySubNetwork;
import org.cytoscape.rest.internal.CyNetworkViewWriterFactoryManager;
import org.cytoscape.rest.internal.CyRESTConstants;
import org.cytoscape.rest.internal.datamapper.TableMapper;
import org.cytoscape.rest.internal.model.Count;
import org.cytoscape.rest.internal.model.CyColumnModel;
import org.cytoscape.rest.internal.model.CyTableWithRowsModel;
import org.cytoscape.rest.internal.serializer.TableModule;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
@Api(tags = {CyRESTSwagger.CyRESTSwaggerConfig.COLLECTIONS_TAG})
Expand All @@ -48,6 +53,17 @@ public class CollectionResource extends AbstractResource {
private final ObjectMapper mapper;
private final TableMapper tableMapper;

private static final String COLLECTION_ASCII_ART =
"Cytoscape can contain multiple Root Networks, each with their own Sub-Networks\n```\n" +
"── Root Network 1\n" +
" ├── Sub-Network A\n" +
" └── Sub-Network B\n" +
"── Root Network 2\n" +
" └── Sub-Network C\n" +
"```";

private static final String TABLE_TYPE_DESCRIPTION = "The `default` table contains data relevant to a Root Network. The `shared` table contains data shared by all Sub-Networks of a Root Network.";

public CollectionResource() {
super();
mapper = new ObjectMapper();
Expand Down Expand Up @@ -89,17 +105,18 @@ private final Response getResponse(final Object val) {
@GET
@Path("/count")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value="Get a count of all root networks.")
@ApiOperation(value="Get a count of all root networks.", notes="Returns a count of all root networks.")
public Count getCollectionCount() {
return new Count((long) getRootNetworks().size());
}

@GET
@Path("/")
@Produces(MediaType.APPLICATION_JSON + "; charset=UTF-8")
@ApiOperation(value="Get one or all root networks.", notes="Returns an array of SUIDs.<br><br>If subsuid is set, return a list with only one entry containing the root network SUID of that sub-network.")
@ApiOperation(value="Get one or all root networks.", notes="Returns all Root Networks as an array of SUIDs.\n\n"
+ "If a valid Sub-Network SUID is specified in the `subsuid` parameter, the list will contain only the SUID of that Sub-Network's Root Network.")
public Collection<Long> getCollectionsAsSUID(
@ApiParam(value="Sub-Network SUID", required=false) @QueryParam("subsuid") Long subsuid) {
@ApiParam(value="Sub-Network SUID. If this parameter is used, the Root Network of this Sub-Network will be returned.\n\n" + COLLECTION_ASCII_ART, required=false) @QueryParam("subsuid") Long subsuid) {
if(subsuid == null) {
// Return all collection SUIDs
return getRootNetworks().stream().map(root -> root.getSUID()).collect(Collectors.toSet());
Expand All @@ -125,16 +142,22 @@ public Collection<Long> getCollectionsAsSUID(
@GET
@Path("/{networkId}.cx")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value="Get a collection as CX", notes="If the Network SUID is a root network, this returns that root network. If the Network SUID is a subnetwork, this returns the root network containing that subnetwork.")
@ApiOperation(value="Get a collection as CX", notes="Returns a Root Network or Sub-Network in [CX format]("+CyRESTConstants.cxLink+").\n\nIf the `networkId` parameter is a Root Network, this returns that Root Network.\n\nIf the `networkId` parameter is a Sub-Network, this returns the Root Retwork that contains that Sub-Network.")
public Response getCollectionAsCx(
@ApiParam(value="Network SUID") @PathParam("networkId") Long networkId) {
@ApiParam(value="Root Network or Sub-Network SUID. \n\n" + COLLECTION_ASCII_ART) @PathParam("networkId") Long networkId) {
return getCX(networkId);
}

/**
* The below is literally an exact copy of getCollectionAsCx, and as such is hidden from Swagger
* using the hidden=true field in ApiOperation. It should still remain an endpoint to maintain API.
* @param networkId
* @return
*/
@GET
@Path("/{networkId}")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value="Get a collection", notes="If the Network SUID is a root network, this returns that root network. If the Network SUID is a subnetwork, this returns the root network containing that subnetwork.")
@ApiOperation(value="Get a collection", notes="", hidden=true)
public Response getCollection(
@ApiParam(value="Network SUID") @PathParam("networkId") Long networkId) {
return getCX(networkId);
Expand All @@ -143,9 +166,9 @@ public Response getCollection(
@GET
@Path("/{networkId}/subnetworks")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value="Get SubNetworks")
@ApiOperation(value="Get SubNetworks", notes="Returns a list of SUIDs representing Sub-Networks that belong to the Root Network specified by the `networkId` parameter.")
public Collection<Long> getSubnetworks(
@ApiParam(value="Root Network SUID") @PathParam("networkId") Long networkId
@ApiParam(value="Root Network SUID\n\n" + COLLECTION_ASCII_ART) @PathParam("networkId") Long networkId
) {
final CyRootNetwork root = getRootNetwork(networkId);
final List<CySubNetwork> subnetworks = root.getSubNetworkList();
Expand All @@ -157,9 +180,9 @@ public Collection<Long> getSubnetworks(
@GET
@Path("/{networkId}/tables")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value="Get Tables in a Root Network")
@ApiOperation(value="Get Tables in a Root Network", notes="Returns a collection of tables belonging to the Root Network specified by the `networkId` parameter. ", response=CyTableWithRowsModel.class, responseContainer="list")
public Response getRootTables(
@ApiParam(value="Root Network SUID") @PathParam("networkId") Long networkId) {
@ApiParam(value="Root Network SUID\n\n" + COLLECTION_ASCII_ART) @PathParam("networkId") Long networkId) {
final CyRootNetwork root = getRootNetwork(networkId);
final CyTable table = root.getDefaultNetworkTable();
final CyTable shared = root.getSharedNetworkTable();
Expand All @@ -173,18 +196,19 @@ public Response getRootTables(
@GET
@Path("/{networkId}/tables/{tableType}")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value="Get a specific Table in a Root Network")
@ApiOperation(value="Get a specific Table in a Root Network", response=CyTableWithRowsModel.class, notes="Returns either the `default` or `shared` table from the Root Network specified by the `networkId` parameter.")
public Response getRootTable(
@ApiParam(value="Root Network SUID") @PathParam("networkId") Long networkId,
@ApiParam(value="Table Type", allowableValues="default,shared") @PathParam("tableType") String tableType) {
@ApiParam(value="Root Network SUID\n\n" + COLLECTION_ASCII_ART) @PathParam("networkId") Long networkId,
@ApiParam(value=TABLE_TYPE_DESCRIPTION, allowableValues="default,shared") @PathParam("tableType") String tableType) {
return getResponse(getTable(networkId, tableType));
}

@DELETE
@Path("/{networkId}/tables/{tableType}/columns/{columnName}")
@ApiOperation(value="Delete a column")
public Response deleteColumn(@PathParam("networkId") Long networkId,
@ApiParam(value="Table Type", allowableValues="default,shared") @PathParam("tableType") String tableType,
@ApiOperation(value="Delete a column", notes="Deletes the column specified by the `columnName` parameter from the table specified the `tableType` parameter in the Root Network specified by the `networkId` parameter.")
public Response deleteColumn(
@ApiParam(value="Root Network SUID\n\n" + COLLECTION_ASCII_ART) @PathParam("networkId") Long networkId,
@ApiParam(value=TABLE_TYPE_DESCRIPTION, allowableValues="default,shared") @PathParam("tableType") String tableType,
@ApiParam(value="Column Name") @PathParam("columnName") String columnName) {

final CyTable table = getTable(networkId, tableType);
Expand All @@ -203,10 +227,10 @@ public Response deleteColumn(@PathParam("networkId") Long networkId,

@GET
@Path("/{networkId}/tables/{tableType}/columns")
@ApiOperation(value="Get a list of columns for a table")
@ApiOperation(value="Get a list of columns for a Root Network table", notes="Return a list of the columns in the table specified by the `tableType` parameter in the Root Network specified by the `networkId` parameter.", response=CyColumnModel.class, responseContainer="list")
public Response getColumns(
@ApiParam(value="Root Network SUID") @PathParam("networkId") Long networkId,
@ApiParam(value="Table Type", allowableValues="default,shared") @PathParam("tableType") String tableType) {
@ApiParam(value="Root Network SUID\n\n" + COLLECTION_ASCII_ART) @PathParam("networkId") Long networkId,
@ApiParam(value=TABLE_TYPE_DESCRIPTION, allowableValues="default,shared") @PathParam("tableType") String tableType) {
final CyTable table = getTable(networkId, tableType);

try {
Expand All @@ -232,10 +256,14 @@ private final CyTable getTable(Long networkId, final String tableType) {
@PUT
@Path("/{networkId}/tables/{tableType}")
@Consumes(MediaType.APPLICATION_JSON)
@ApiOperation(value="Update table values")
@ApiOperation(value="Update table values", notes="Updates the values in a table. New columns will be created if they do not exist in the target table.")
@ApiImplicitParams(
@ApiImplicitParam(value="The data with which to update the table.", dataType="org.cytoscape.rest.internal.model.UpdateTable", paramType="body", required=true)
)
public Response updateTable(
@ApiParam(value="Root Network SUID") @PathParam("networkId") Long networkId,
@ApiParam(value="Table Type", allowableValues="default,shared") @PathParam("tableType") String tableType, final InputStream is) {
@ApiParam(value="Root Network SUID\n\n" + COLLECTION_ASCII_ART) @PathParam("networkId") Long networkId,
@ApiParam(value=TABLE_TYPE_DESCRIPTION, allowableValues="default,shared") @PathParam("tableType") String tableType,
@ApiParam(hidden=true) final InputStream is) {
final CyTable table = getTable(networkId, tableType);
if(table == null) {
throw getError("No such table type", new NullPointerException(), Response.Status.NOT_FOUND);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public class JsonTags {
public static final String COLUMN_NAME_OLD = "oldName";
public static final String COLUMN_NAME_NEW = "newName";
public static final String COLUMN_TYPE = "type";
public static final String COLUMN_LIST_TYPE = "listType";
public static final String COLUMN_VALUES = "values";
public static final String COLUMN_IMMUTABLE = "immutable";
public static final String COLUMN_IS_LIST = "list";
Expand Down
Loading

0 comments on commit 668c4d5

Please sign in to comment.