<commit_before>package org.cytoscape.rest.internal.service;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;

import javax.inject.Singleton;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;

import org.cytoscape.io.read.CyNetworkReader;
import org.cytoscape.io.write.CyWriter;
import org.cytoscape.model.CyEdge;
import org.cytoscape.model.CyEdge.Type;
import org.cytoscape.model.CyIdentifiable;
import org.cytoscape.model.CyNetwork;
import org.cytoscape.model.CyNode;
import org.cytoscape.model.CyRow;
import org.cytoscape.model.CyTable;
import org.cytoscape.model.subnetwork.CyRootNetwork;
import org.cytoscape.model.subnetwork.CySubNetwork;
import org.cytoscape.rest.internal.task.RestTaskManager;
import org.cytoscape.task.NetworkCollectionTaskFactory;
import org.cytoscape.task.NetworkTaskFactory;
import org.cytoscape.view.model.CyNetworkView;
import org.cytoscape.view.presentation.property.BasicVisualLexicon;
import org.cytoscape.view.vizmap.VisualStyle;
import org.cytoscape.work.TaskFactory;
import org.cytoscape.work.TaskIterator;
import org.cytoscape.work.TaskManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

@Singleton
@Path("/v1")
// API version
public class NetworkDataService extends AbstractDataService {

	private final static Logger logger = LoggerFactory.getLogger(NetworkDataService.class);

	// Preset types
	private static final String DEF_COLLECTION_PREFIX = "Posted: ";

	public NetworkDataService() {
		super();
	}

	// ////////////////// Count Objects ///////////////////////////

	@GET
	@Path("/" + NETWORKS + "/count")
	@Produces(MediaType.APPLICATION_JSON)
	public String getNetworkCount() {
		return getNumberObjectString("networkCount", networkManager.getNetworkSet().size());
	}

	@GET
	@Path("/" + NETWORKS + "/{id}/nodes/count")
	@Produces(MediaType.APPLICATION_JSON)
	public String getNodeCount(@PathParam("id") Long id) {
		return getNumberObjectString("nodeCount", getCyNetwork(id).getNodeCount());
	}

	@GET
	@Path("/" + NETWORKS + "/{id}/edges/count")
	@Produces(MediaType.APPLICATION_JSON)
	public String getEdgeCount(@PathParam("id") Long id) {
		return getNumberObjectString("edgeCount", getCyNetwork(id).getEdgeCount());
	}

	// /////////////////// Get Operations

	private String getByQuery(final Long id, final String objType, final String column, final String query) {
		final CyNetwork network = getCyNetwork(id);
		CyTable table = null;
		if (objType.equals("nodes")) {
			table = network.getDefaultNodeTable();
		} else if (objType.equals("edges")) {
			table = network.getDefaultEdgeTable();
		} else {
			throw new WebApplicationException("Invalid graph object type: " + objType, 500);
		}

		final Collection<CyRow> rows;
		if (query == null && column == null) {
			rows = table.getAllRows();
		} else if(query == null || column == null) {
			throw new WebApplicationException("Query parameters are incomplete.", 500);
		} else {
			Object rawQuery = getRawValue(query, table.getColumn(column).getType());
			rows = table.getMatchingRows(column, rawQuery);
		}

		final JsonFactory factory = new JsonFactory();
		String result = null;
		ByteArrayOutputStream stream = new ByteArrayOutputStream();
		JsonGenerator generator = null;

		try {
			generator = factory.createGenerator(stream);
			generator.writeStartArray();
			for (final CyRow row : rows) {
				generator.writeNumber(row.get(CyIdentifiable.SUID, Long.class));
			}
			generator.writeEndArray();
			generator.close();
			result = stream.toString();
			stream.close();
		} catch (Exception e) {
			throw new WebApplicationException(e, 500);
		}
		return result;
	}

	private final Object getRawValue(final String queryString, Class<?> type) {
		Object raw = queryString;

		if (type == Boolean.class) {
			raw = Boolean.parseBoolean(queryString);
		} else if (type == Double.class) {
			raw = Double.parseDouble(queryString);
		} else if (type == Integer.class) {
			raw = Integer.parseInt(queryString);
		} else if (type == Long.class) {
			raw = Long.parseLong(queryString);
		} else if (type == Float.class) {
			raw = Float.parseFloat(queryString);
		}
		return raw;
	}

	@GET
	@Path("/" + NETWORKS)
	@Produces(MediaType.APPLICATION_JSON)
	public String getNetworks() {
		final Set<CyNetwork> networks = networkManager.getNetworkSet();
		StringBuilder result = new StringBuilder();
		result.append("[");

		for (final CyNetwork network : networks) {
			result.append(getNetworkString(network));
			result.append(",");
		}
		String jsonString = result.toString();
		jsonString = jsonString.substring(0, jsonString.length() - 1);

		return jsonString + "]";
	}

	@GET
	@Path("/" + NETWORKS + "/{id}/")
	@Produces(MediaType.APPLICATION_JSON)
	public String getNetwork(@PathParam("id") Long id) {
		return getNetworkString(getCyNetwork(id));
	}

	/**
	 * Get edges as array of SUID
	 * 
	 * @param id
	 * @return
	 */
	@GET
	@Path("/" + NETWORKS + "/{id}/nodes")
	@Produces(MediaType.APPLICATION_JSON)
	public String getNodes(@PathParam("id") Long id, @QueryParam("column") String column,
			@QueryParam("query") String query) {
		return getByQuery(id, "nodes", column, query);
	}

	@GET
	@Path("/" + NETWORKS + "/{id}/edges")
	@Produces(MediaType.APPLICATION_JSON)
	public String getEdges(@PathParam("id") Long id, @QueryParam("column") String column,
			@QueryParam("query") String query) {
		return getByQuery(id, "edges", column, query);
	}

	/**
	 * Returns a node or an edge.
	 * 
	 * @param id
	 * @param objType
	 * @param objId
	 * @return
	 */
	@GET
	@Path("/" + NETWORKS + "/{id}/{objType}/{objId}")
	@Produces(MediaType.APPLICATION_JSON)
	public String getGraphObject(@PathParam("id") Long id, @PathParam("objType") String objType,
			@PathParam("objId") Long suid) {
		final CyNetwork network = getCyNetwork(id);

		CyIdentifiable obj = null;
		try {<commit_msg>Get by query API implemented for Networks.<commit_after>package org.cytoscape.rest.internal.service;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.inject.Singleton;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;

import org.cytoscape.io.read.CyNetworkReader;
import org.cytoscape.io.write.CyWriter;
import org.cytoscape.model.CyEdge;
import org.cytoscape.model.CyEdge.Type;
import org.cytoscape.model.CyIdentifiable;
import org.cytoscape.model.CyNetwork;
import org.cytoscape.model.CyNode;
import org.cytoscape.model.CyRow;
import org.cytoscape.model.CyTable;
import org.cytoscape.model.subnetwork.CyRootNetwork;
import org.cytoscape.model.subnetwork.CySubNetwork;
import org.cytoscape.rest.internal.task.RestTaskManager;
import org.cytoscape.task.NetworkCollectionTaskFactory;
import org.cytoscape.task.NetworkTaskFactory;
import org.cytoscape.view.model.CyNetworkView;
import org.cytoscape.view.presentation.property.BasicVisualLexicon;
import org.cytoscape.view.vizmap.VisualStyle;
import org.cytoscape.work.TaskFactory;
import org.cytoscape.work.TaskIterator;
import org.cytoscape.work.TaskManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

@Singleton
@Path("/v1")
// API version
public class NetworkDataService extends AbstractDataService {

	private final static Logger logger = LoggerFactory.getLogger(NetworkDataService.class);

	// Preset types
	private static final String DEF_COLLECTION_PREFIX = "Posted: ";

	public NetworkDataService() {
		super();
	}


	@GET
	@Path("/" + NETWORKS + "/count")
	@Produces(MediaType.APPLICATION_JSON)
	public String getNetworkCount() {
		return getNumberObjectString("networkCount", networkManager.getNetworkSet().size());
	}


	@GET
	@Path("/" + NETWORKS + "/{id}/nodes/count")
	@Produces(MediaType.APPLICATION_JSON)
	public String getNodeCount(@PathParam("id") Long id) {
		return getNumberObjectString("nodeCount", getCyNetwork(id).getNodeCount());
	}


	@GET
	@Path("/" + NETWORKS + "/{id}/edges/count")
	@Produces(MediaType.APPLICATION_JSON)
	public String getEdgeCount(@PathParam("id") Long id) {
		return getNumberObjectString("edgeCount", getCyNetwork(id).getEdgeCount());
	}



	private String getByQuery(final Long id, final String objType, final String column, final String query) {
		final CyNetwork network = getCyNetwork(id);
		CyTable table = null;
		if (objType.equals("nodes")) {
			table = network.getDefaultNodeTable();
		} else if (objType.equals("edges")) {
			table = network.getDefaultEdgeTable();
		} else {
			throw new WebApplicationException("Invalid graph object type: " + objType, 500);
		}

		final Collection<CyRow> rows;
		if (query == null && column == null) {
			rows = table.getAllRows();
		} else if(query == null || column == null) {
			throw new WebApplicationException("Query parameters are incomplete.", 500);
		} else {
			Object rawQuery = getRawValue(query, table.getColumn(column).getType());
			rows = table.getMatchingRows(column, rawQuery);
		}

		final JsonFactory factory = new JsonFactory();
		String result = null;
		ByteArrayOutputStream stream = new ByteArrayOutputStream();
		JsonGenerator generator = null;

		try {
			generator = factory.createGenerator(stream);
			generator.writeStartArray();
			for (final CyRow row : rows) {
				generator.writeNumber(row.get(CyIdentifiable.SUID, Long.class));
			}
			generator.writeEndArray();
			generator.close();
			result = stream.toString();
			stream.close();
		} catch (Exception e) {
			throw new WebApplicationException(e, 500);
		}
		return result;
	}

	private final Object getRawValue(final String queryString, Class<?> type) {
		Object raw = queryString;

		if (type == Boolean.class) {
			raw = Boolean.parseBoolean(queryString);
		} else if (type == Double.class) {
			raw = Double.parseDouble(queryString);
		} else if (type == Integer.class) {
			raw = Integer.parseInt(queryString);
		} else if (type == Long.class) {
			raw = Long.parseLong(queryString);
		} else if (type == Float.class) {
			raw = Float.parseFloat(queryString);
		}
		return raw;
	}

	@GET
	@Path("/" + NETWORKS)
	@Produces(MediaType.APPLICATION_JSON)
	public String getNetworks(@QueryParam("column") String column, @QueryParam("query") String query) {
		if(column == null && query == null) {
			return getNetworks(networkManager.getNetworkSet());
		} else {
			return getNetworksByQuery(query, column);
		}
	}


	private final String getNetworksByQuery(final String query, final String column) {
		final Set<CyNetwork> networks = networkManager.getNetworkSet();
		final Set<CyNetwork> matchedNetworks = new HashSet<CyNetwork>();
		
		for(final CyNetwork network:networks) {
			final CyTable table=network.getDefaultNetworkTable();
			final Object rawQuery = getRawValue(query, table.getColumn(column).getType());
			final Collection<CyRow> rows = table.getMatchingRows(column, rawQuery);
			if(rows.isEmpty() == false) {
				matchedNetworks.add(network);
			}
		}
		return getNetworks(matchedNetworks);
	}


	private final String getNetworks(final Set<CyNetwork> networks) {
		StringBuilder result = new StringBuilder();
		result.append("[");

		for (final CyNetwork network : networks) {
			result.append(getNetworkString(network));
			result.append(",");
		}
		String jsonString = result.toString();
		jsonString = jsonString.substring(0, jsonString.length() - 1);

		return jsonString + "]";
	}


	@GET
	@Path("/" + NETWORKS + "/{id}")
	@Produces(MediaType.APPLICATION_JSON)
	public String getNetwork(@PathParam("id") Long id) {
		return getNetworkString(getCyNetwork(id));
	}


	/**
	 * Get edges as array of SUID
	 * 
	 * @param id
	 * @return
	 */
	@GET
	@Path("/" + NETWORKS + "/{id}/nodes")
	@Produces(MediaType.APPLICATION_JSON)
	public String getNodes(@PathParam("id") Long id, @QueryParam("column") String column,
			@QueryParam("query") String query) {
		return getByQuery(id, "nodes", column, query);
	}

	@GET
	@Path("/" + NETWORKS + "/{id}/edges")
	@Produces(MediaType.APPLICATION_JSON)
	public String getEdges(@PathParam("id") Long id, @QueryParam("column") String column,
			@QueryParam("query") String query) {
		return getByQuery(id, "edges", column, query);
	}



	/**
	 * Returns a node or an edge.
	 * 
	 * @param id
	 * @param objType
	 * @param objId
	 * @return
	 */
	@GET
	@Path("/" + NETWORKS + "/{id}/{objType}/{objId}")
	@Produces(MediaType.APPLICATION_JSON)
	public String getGraphObject(@PathParam("id") Long id, @PathParam("objType") String objType,
			@PathParam("objId") Long suid) {
		final CyNetwork network = getCyNetwork(id);

		CyIdentifiable obj = null;
		try {
{'fraction_non_alphanumeric': 0.13769686461494005, 'fraction_numerical': 0.0020228290709435053, 'mean_word_length': 4.751142501038637, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 8}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3837244', 'n_tokens_mistral': 4811, 'n_tokens_neox': 4373, 'n_words': 956}