package org.cytoscape.rest.service;
import static org.junit.Assert.*;
import java.awt.Color;
import java.awt.Paint;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.ToDoubleBiFunction;
import java.util.stream.Collectors;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.cytoscape.model.CyNetwork;
import org.cytoscape.model.CyNode;
import org.cytoscape.rest.internal.resource.StyleResource;
import org.cytoscape.view.model.DiscreteRange;
import org.cytoscape.view.model.VisualProperty;
import org.cytoscape.view.presentation.property.BasicVisualLexicon;
import org.cytoscape.view.presentation.property.values.VisualPropertyValue;
import org.cytoscape.view.vizmap.mappings.ContinuousMapping;
import org.cytoscape.view.vizmap.mappings.ContinuousMappingPoint;
import org.glassfish.jersey.server.ResourceConfig;
import org.junit.Test;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
public class StyleResourceTest extends BasicResourceTest {
@Override
protected Application configure() {
return new ResourceConfig(StyleResource.class);
}
private ObjectMapper mapper = new ObjectMapper();
@Test
public void testGetStyles() throws Exception {
String result = target("/v1/styles").request().get(String.class);
assertNotNull(result);
final JsonNode root = mapper.readTree(result);
assertTrue(root.isArray());
assertEquals(2, root.size());
Set<String> names = new HashSet<>();
for(JsonNode styleName: root) {
names.add(styleName.asText());
}
assertTrue(names.contains("vs1"));
assertTrue(names.contains("mock1"));
assertFalse(names.contains("vs2"));
}
@Test
public void testGetStylesCount() throws Exception {
String result = target("/v1/styles/count").request().get(String.class);
assertNotNull(result);
final JsonNode root = mapper.readTree(result);
int count = root.get("count").asInt();
assertEquals(2, count);
}
@Test
public void testGetStyle() throws Exception {
String result = target("/v1/styles/mock1").request().get(String.class);
assertNotNull(result);
final JsonNode root = mapper.readTree(result);
assertEquals("mock1", root.get("title").asText());
}
@Test
public void testGetDefaultValues() throws Exception {
final Response result = target("/v1/styles/vs1/defaults").request().get();
assertNotNull(result);
final String body = result.readEntity(String.class);
System.out.println(body);
final JsonNode root = mapper.readTree(body);
assertTrue(root.get("defaults").isArray());
final JsonNode defaults = root.get("defaults");
assertEquals(103, defaults.size());
}
@Test
public void testGetRangeValues() throws Exception {
testRange(BasicVisualLexicon.NODE_SHAPE);
testRange(BasicVisualLexicon.NODE_BORDER_LINE_TYPE);
testRange(BasicVisualLexicon.EDGE_LINE_TYPE);
testRange(BasicVisualLexicon.EDGE_SOURCE_ARROW_SHAPE);
testRange(BasicVisualLexicon.EDGE_TARGET_ARROW_SHAPE);
}
private final void testRange(VisualProperty<?> vp) throws JsonProcessingException, IOException {
Set<?> values = ((DiscreteRange<?>)vp.getRange()).values();
Set<String> valueStrings = new HashSet<>();
for(Object val:values) {
VisualPropertyValue vpv = (VisualPropertyValue) val;
valueStrings.add(vpv.getSerializableString());
}
Response result = target("/v1/styles/visualproperties/" + vp.getIdString() + "/values").request().get();
assertNotNull(result);
final String body = result.readEntity(String.class);
System.out.println(body);
final JsonNode root = mapper.readTree(body);
assertTrue(root.isObject());
final JsonNode generatedValues = root.get("values");
assertNotNull(generatedValues);
assertTrue(generatedValues.isArray());
assertEquals(values.size(), generatedValues.size());
for(JsonNode node: generatedValues) {
assertTrue(valueStrings.contains(node.asText()));
}
}
@Test
public void testGetVisualProperties() throws Exception {
Response result = target("/v1/styles/visualproperties").request().get();
assertNotNull(result);
final String body = result.readEntity(String.class);
System.out.println(body);
final JsonNode root = mapper.readTree(body);
assertTrue(root.isArray());
assertEquals(103, root.size());
}
@Test
public void testGetVisualProperty() throws Exception {
final Set<VisualProperty<?>> vps = lexicon.getAllVisualProperties();
for (VisualProperty vp : vps) {
Response result = target("/v1/styles/visualproperties/" + vp.getIdString()).request().get();
assertNotNull(result);
final String body = result.readEntity(String.class);
System.out.println(body);
final JsonNode root = mapper.readTree(body);
assertTrue(root.isObject());
assertEquals(vp.getIdString(), root.get("visualProperty").asText());
assertEquals(vp.getDisplayName(), root.get("name").asText());
assertEquals(vp.getTargetDataType().getSimpleName(), root.get("targetDataType").asText());
String def = vp.toSerializableString(vp.getDefault());
if(def != null)
assertEquals(def,
root.get("default").asText());
}
}
@Test
public void testGetDefaultValue() throws Exception {
final String vp = BasicVisualLexicon.NODE_FILL_COLOR.getIdString();
Response result = target("/v1/styles/vs1/defaults/NODE_FILL_COLOR").request().get();
assertNotNull(result);
assertFalse(result.getStatus() == 500);
assertEquals(200, result.getStatus());
final String body = result.readEntity(String.class);
System.out.println(body);
final JsonNode root = mapper.readTree(body);
assertTrue(root.isObject());
assertEquals(vp, root.get("visualProperty").textValue());
Integer colorValue = ((Color)style.getDefaultValue(BasicVisualLexicon.NODE_FILL_COLOR)).getRGB();
String inHex = Integer.toHexString(colorValue);
final Integer inHexWithoutAlpha = Integer.parseInt(inHex.substring(2), 16);
final String fillColorValue = root.get("value").asText();
final String colorInHex = fillColorValue.substring(1);
System.out.println("Fill: " + colorInHex);
final Integer newColorValue = Integer.parseInt(colorInHex, 16);
assertEquals(inHexWithoutAlpha, newColorValue);
}
@Test
public void testGetMappings() throws Exception {
final Response emptyResult = target("/v1/styles/mock1/mappings").request().get();
assertNotNull(emptyResult);
assertFalse(emptyResult.getStatus() == 500);
assertEquals(200, emptyResult.getStatus());
String body0 = emptyResult.readEntity(String.class);
System.out.println(body0);
final JsonNode root0 = mapper.readTree(body0);
assertTrue(root0.isArray());
assertEquals(0, root0.size());
final Response result = target("/v1/styles/vs1/mappings").request().get();
assertNotNull(result);
System.out.println("res: " + result.toString());
assertFalse(result.getStatus() == 500);
assertEquals(200, result.getStatus());
String body = result.readEntity(String.class);
System.out.println(body);
final JsonNode root = mapper.readTree(body);
assertTrue(root.isArray());
assertEquals(11, root.size());
for(JsonNode mapping:root) {
JsonNode type = mapping.get("mappingType");
assertNotNull(type);
if(type.asText().equals("discrete")) {
testDiscrete(mapping);
} else if(type.asText().equals("continuous")) {
testContinuous(mapping);
} else if(type.asText().equals("passthrough")) {
testPassthrough(mapping);
} else {
fail("No such mapping type: " + type.asText());
}
}
}
private void testDiscrete(JsonNode mapping) {
checkBasicSettings(mapping);
final JsonNode map = mapping.get("map");
assertNotNull(map);
assertTrue(map.isArray());
}
private void testContinuous(JsonNode mapping) {
checkBasicSettings(mapping);
final JsonNode points = mapping.get("points");
assertNotNull(points);
assertTrue(points.isArray());
for(JsonNode point:points) {
JsonNode val = point.get("value");
assertNotNull(val);
assertTrue(val.isNumber());
JsonNode l = point.get("lesser");
assertNotNull(l);
JsonNode eq = point.get("equal");
assertNotNull(eq);
JsonNode g = point.get("greater");
assertNotNull(g);
}
}
private void testPassthrough(JsonNode mapping) {
checkBasicSettings(mapping);
}
private final void checkBasicSettings(JsonNode mapping) {
final JsonNode column = mapping.get("mappingColumn");
assertNotNull(column);
final JsonNode columnType= mapping.get("mappingColumnType");
assertNotNull(columnType);
final JsonNode vp = mapping.get("visualProperty");
assertNotNull(vp);
}
@Test
public void testCreateStyle() throws Exception {
final String style1 = "{ \"title\": \"style1\""
+ "}";
System.out.println("Data: " + style1);
final Entity<String> entity = Entity.entity(style1, MediaType.APPLICATION_JSON_TYPE);
final Response result = target("/v1/styles").request().post(entity);
assertNotNull(result);
System.out.println("res: " + result.toString());
String body = result.readEntity(String.class);
assertFalse(result.getStatus() == 500);
assertEquals(201, result.getStatus());
assertTrue(body.contains("title"));
}
@Test
public void testCreateMapping() throws Exception {
testCreateDiscrete();
testCreateContinuous();
testCreatePassthrough();
}
private void testCreateDiscrete() {
final String edgeWidthMapping = "[{"
+ "\"mappingType\": \"discrete\","
+ "\"mappingColumn\": \"interaction\","
+ "\"mappingColumnType\": \"String\","
+ "\"visualProperty\": \"EDGE_WIDTH\", "
+ "\"map\": ["
+ "{\"key\" : \"pd\", \"value\" : \"20\"},"
+ "{\"key\" : \"pp\", \"value\" : \"1.5\"}"
+ "]}"
+ "]";
// Test String column
Entity<String> entity = Entity.entity(edgeWidthMapping, MediaType.APPLICATION_JSON_TYPE);
Response result = target("/v1/styles/vs1/mappings").request().post(entity);
assertNotNull(result);
assertFalse(result.getStatus() == 500);
assertEquals(201, result.getStatus());
System.out.println("res: " + result.toString());
}
private void testCreateContinuous() {
final String nodeSizeMapping = "[{"
+ "\"mappingType\": \"continuous\","
+ "\"mappingColumn\": \"Degree\","
+ "\"mappingColumnType\": \"Double\","
+ "\"visualProperty\": \"NODE_SIZE\", "
+ "\"points\": ["
+ "{\"value\" : 1, \"lesser\" : \"20\" , \"equal\" : \"20\", \"greater\" : \"20\" },"
+ "{\"value\" : 20, \"lesser\" : \"120\" , \"equal\" : \"120\", \"greater\" : \"220\" }"
+ "]}"
+ "]";
// Test String column
Entity<String> entity = Entity.entity(nodeSizeMapping, MediaType.APPLICATION_JSON_TYPE);
Response result = target("/v1/styles/vs1/mappings").request().post(entity);
System.out.println("result: " + result.toString());
assertNotNull(result);
assertFalse(result.getStatus() == 500);
assertEquals(201, result.getStatus());
System.out.println("res: " + result.toString());
ContinuousMapping<?, Double> mapping = (ContinuousMapping<?, Double>) style.getVisualMappingFunction(BasicVisualLexicon.NODE_SIZE);
assertNotNull(mapping);
assertEquals("Degree", mapping.getMappingColumnName());
assertEquals(Double.class, mapping.getMappingColumnType());
assertEquals(2, mapping.getAllPoints().size());
ContinuousMappingPoint<?, Double> p1 = mapping.getPoint(0);
assertTrue(p1.getValue() instanceof Number);
assertEquals(Double.class, p1.getRange().equalValue.getClass());
}
private void testCreatePassthrough() {
final String edgeLabelMapping = "[{"
+ "\"mappingType\": \"passthrough\","
+ "\"mappingColumn\": \"name\","
+ "\"mappingColumnType\": \"String\","
+ "\"visualProperty\": \"EDGE_LABEL\" }]";
// Test String column
Entity<String> entity = Entity.entity(edgeLabelMapping, MediaType.APPLICATION_JSON_TYPE);
Response result = target("/v1/styles/vs1/mappings").request().post(entity);
assertNotNull(result);
assertFalse(result.getStatus() == 500);
assertEquals(201, result.getStatus());
System.out.println("res: " + result.toString());
}
@Test
public void testUpdateMapping() throws Exception {
final String nodeLabelMapping = "[{"
+ "\"mappingType\": \"passthrough\","
+ "\"mappingColumn\": \"name\","
+ "\"mappingColumnType\": \"String\","
+ "\"visualProperty\": \"NODE_LABEL\" }]";
// Test String column
Entity<String> entity = Entity.entity(nodeLabelMapping, MediaType.APPLICATION_JSON_TYPE);
Response result = target("/v1/styles/vs1/mappings/NODE_LABEL").request().put(entity);
assertNotNull(result);
assertFalse(result.getStatus() == 500);
assertEquals(200, result.getStatus());
System.out.println("res: " + result.toString());
final String nodeTooltipMapping = "[{"
+ "\"mappingType\": \"passthrough\","
+ "\"mappingColumn\": \"name\","
+ "\"mappingColumnType\": \"String\","
+ "\"visualProperty\": \"NODE_TOOLTIP\" }]";
// Test String column
entity = Entity.entity(nodeTooltipMapping, MediaType.APPLICATION_JSON_TYPE);
result = target("/v1/styles/vs1/mappings/NODE_TOOLTIP").request().put(entity);
assertNotNull(result);
assertFalse(result.getStatus() == 500);
assertEquals(404, result.getStatus());
System.out.println("res: " + result.toString());
}
@Test
public void testDeleteStyle() throws Exception {
final Response result = target("/v1/styles/vs1").request().delete();
assertNotNull(result);
assertEquals(200, result.getStatus());
}
@Test
public void testDeleteAllStyles() throws Exception {
final Response result = target("/v1/styles").request().delete();
assertNotNull(result);
assertEquals(200, result.getStatus());
}
@Test
public void testDeleteMapping() throws Exception {
final Response result = target("/v1/styles/vs1/mappings/NODE_LABEL").request().delete();
assertNotNull(result);
assertEquals(200, result.getStatus());
}
private final String createDefaultsJson() throws Exception {
final JsonFactory factory = new JsonFactory();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
JsonGenerator generator = null;
generator = factory.createGenerator(stream);
generator.writeStartArray();
generator.writeStartObject();
generator.writeStringField("visualProperty", BasicVisualLexicon.NODE_FILL_COLOR.getIdString());
generator.writeStringField("value", "blue");
generator.writeEndObject();
generator.writeStartObject();
generator.writeStringField("visualProperty", BasicVisualLexicon.NODE_SIZE.getIdString());
generator.writeNumberField("value", 120);
generator.writeEndObject();
generator.writeStartObject();
generator.writeStringField("visualProperty", BasicVisualLexicon.EDGE_LABEL_FONT_SIZE.getIdString());
generator.writeNumberField("value", 20);
generator.writeEndObject();
generator.writeEndArray();
generator.close();
final String result = stream.toString("UTF-8");
stream.close();
return result;
}
@Test
public void testUpdateDefault() throws Exception {
String newVal = createDefaultsJson();
Entity<String> entity = Entity.entity(newVal, MediaType.APPLICATION_JSON_TYPE);
Response result = target("/v1/styles/vs1/defaults").request().put(entity);
assertNotNull(result);
System.out.println("res: " + result.toString());
assertFalse(result.getStatus() == 500);
assertEquals(200, result.getStatus());
final String body = result.readEntity(String.class);
System.out.println("BODY: " + body);
assertEquals("", body);
// TODO: Add more updated value check
Paint fillColor = style.getDefaultValue(BasicVisualLexicon.NODE_FILL_COLOR);
System.out.println("Fill Color: " + ((Color)fillColor));
assertEquals(Color.blue, fillColor);
}
}