package org.cytoscape.rest.internal.serializer;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Collection;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import org.cytoscape.model.CyIdentifiable;
import org.cytoscape.rest.internal.datamapper.VisualStyleMapper;
import org.cytoscape.view.model.DiscreteRange;
import org.cytoscape.view.model.View;
import org.cytoscape.view.model.VisualProperty;
import org.cytoscape.view.presentation.property.values.VisualPropertyValue;
import org.cytoscape.view.vizmap.VisualMappingFunction;
import org.cytoscape.view.vizmap.VisualPropertyDependency;
import org.cytoscape.view.vizmap.VisualStyle;
import org.cytoscape.view.vizmap.mappings.ContinuousMapping;
import org.cytoscape.view.vizmap.mappings.DiscreteMapping;
import org.cytoscape.view.vizmap.mappings.PassthroughMapping;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.qmino.miredot.annotations.MireDotIgnore;
@MireDotIgnore
public class VisualStyleSerializer {
private final DiscreteMappingSerializer discSerializer = new DiscreteMappingSerializer();
private final PassthroughMappingSerializer passhthroughSerializer = new PassthroughMappingSerializer();
private final ContinuousMappingSerializer continuousSerializer = new ContinuousMappingSerializer();
public final String serializeDefaults(final Collection<VisualProperty<?>> vps, final VisualStyle style) throws IOException {
final JsonFactory factory = new JsonFactory();
// Sort by field name
final SortedMap<String, VisualProperty<?>> names = new TreeMap<String, VisualProperty<?>>();
for(final VisualProperty<?> vp:vps) {
names.put(vp.getIdString(), vp);
}
String result = null;
ByteArrayOutputStream stream = new ByteArrayOutputStream();
JsonGenerator generator = factory.createGenerator(stream);
generator.useDefaultPrettyPrinter();
generator.writeStartObject();
addDefaults(generator, names, style);
generator.writeEndObject();
generator.close();
result = stream.toString("UTF-8");
stream.close();
return result;
}
public final String serializeVisualProperties(final Set<VisualProperty<?>> vps) throws IOException {
final JsonFactory factory = new JsonFactory();
// Sort by field name
final SortedMap<String, VisualProperty<Object>> names = new TreeMap<>();
for(final VisualProperty vp:vps) {
names.put(vp.getIdString(), vp);
}
String result = null;
ByteArrayOutputStream stream = new ByteArrayOutputStream();
JsonGenerator generator = factory.createGenerator(stream);
generator.useDefaultPrettyPrinter();
generator.writeStartArray();
for(final String vpName:names.keySet()) {
final VisualProperty<Object> vp = names.get(vpName);
serializeVisualProperty(generator, vp);
}
generator.writeEndArray();
generator.close();
result = stream.toString("UTF-8");
stream.close();
return result;
}
public final String serializeVisualProperty(final VisualProperty vp) throws IOException {
final JsonFactory factory = new JsonFactory();
String result = null;
ByteArrayOutputStream stream = new ByteArrayOutputStream();
JsonGenerator generator = factory.createGenerator(stream);
generator.useDefaultPrettyPrinter();
serializeVisualProperty(generator, vp);
generator.close();
result = stream.toString("UTF-8");
stream.close();
return result;
}
private final void serializeVisualProperty(final JsonGenerator generator, final VisualProperty<Object> vp) throws IOException {
generator.writeStartObject();
generator.writeStringField("visualProperty", vp.getIdString());
generator.writeStringField("name", vp.getDisplayName());
generator.writeStringField("targetDataType", vp.getTargetDataType().getSimpleName());
generator.writeStringField("default", vp.toSerializableString(vp.getDefault()));
generator.writeEndObject();
}
public final String serializeDefault(final VisualProperty<Object> vp, final VisualStyle style) throws IOException {
final JsonFactory factory = new JsonFactory();
String result = null;
ByteArrayOutputStream stream = new ByteArrayOutputStream();
JsonGenerator generator = factory.createGenerator(stream);
generator.useDefaultPrettyPrinter();
generator.writeStartObject();
generator.writeStringField(VisualStyleMapper.MAPPING_VP, vp.getIdString());
generator.writeFieldName("value");
Object value = style.getDefaultValue(vp);
if(value == null) {
// Use VP default is Style default is not available
value = vp.getDefault();
}
writeValue(vp, value, generator);
generator.writeEndObject();
generator.close();
result = stream.toString("UTF-8");
stream.close();
return result;
}
public final String serializeDiscreteRange(final VisualProperty<Object> vp, final DiscreteRange<Object> range) throws IOException {
final JsonFactory factory = new JsonFactory();
String result = null;
ByteArrayOutputStream stream = new ByteArrayOutputStream();
JsonGenerator generator = factory.createGenerator(stream);
generator.useDefaultPrettyPrinter();
generator.writeStartObject();
generator.writeStringField(VisualStyleMapper.MAPPING_VP, vp.getIdString());
generator.writeArrayFieldStart("values");
for(Object obj: range.values()) {
VisualPropertyValue vpv = (VisualPropertyValue) obj;
generator.writeString(vpv.getSerializableString());
}
generator.writeEndArray();
generator.writeEndObject();
generator.close();
result = stream.toString("UTF-8");
stream.close();
return result;
}
public final String serializeStyle(final Collection<VisualProperty<?>> vps, final VisualStyle style) throws IOException {
final SortedMap<String, VisualProperty<?>> names = new TreeMap<String, VisualProperty<?>>();
for(final VisualProperty<?> vp:vps) {
names.put(vp.getIdString(), vp);
}
final JsonFactory factory = new JsonFactory();
String result = null;
ByteArrayOutputStream stream = new ByteArrayOutputStream();
JsonGenerator generator = factory.createGenerator(stream);
generator.useDefaultPrettyPrinter();
generator.writeStartObject();
generator.writeStringField("title", style.getTitle());
addDefaults(generator, names, style);
addMappings(generator, style);
generator.writeEndObject();
generator.close();
result = stream.toString("UTF-8");
stream.close();
return result;
}
@SuppressWarnings("unchecked")
private void addDefaults(JsonGenerator generator, final SortedMap<String, VisualProperty<?>> names, VisualStyle style) throws IOException {
generator.writeArrayFieldStart("defaults");
for(final String name:names.keySet()) {
final VisualProperty<Object> vp = (VisualProperty<Object>) names.get(name);
Object newValue = style.getDefaultValue(vp);
if(newValue == null) {
newValue = vp.getDefault();
}
generator.writeStartObject();
generator.writeStringField(VisualStyleMapper.MAPPING_VP, vp.getIdString());
generator.writeFieldName("value");
writeValue(vp, newValue, generator);
generator.writeEndObject();
}
generator.writeEndArray();
}
@SuppressWarnings("rawtypes")
private void addMappings(JsonGenerator generator, VisualStyle style) throws JsonProcessingException, IOException {
// Mappings
generator.writeArrayFieldStart("mappings");
for(VisualMappingFunction mapping:style.getAllVisualMappingFunctions()) {
if(mapping instanceof DiscreteMapping) {
discSerializer.serialize((DiscreteMapping) mapping, generator, null);
} else if(mapping instanceof ContinuousMapping) {
continuousSerializer.serialize((ContinuousMapping) mapping, generator, null);
} else if(mapping instanceof PassthroughMapping) {
passhthroughSerializer.serialize((PassthroughMapping) mapping, generator, null);
}
}
generator.writeEndArray();
}
private final void writeValue(final VisualProperty<Object> vp, final Object value, final JsonGenerator generator)
throws IOException {
if(value == null) {
return;
}
final Class<?> type = vp.getRange().getType();
if (type == String.class) {
generator.writeString(value.toString());
} else if (type == Boolean.class) {
generator.writeBoolean((Boolean) value);
} else if (type == Double.class) {
generator.writeNumber((Double) value);
} else if (type == Integer.class) {
generator.writeNumber((Integer) value);
} else if (type == Long.class) {
generator.writeNumber((Long) value);
} else if (type == Float.class) {
generator.writeNumber((Double) value);
} else {
generator.writeString(vp.toSerializableString(value));
}
}
public final String serializeViews(final Collection<? extends View<? extends CyIdentifiable>> views,
final Collection<VisualProperty<?>> visualProperties) throws IOException {
final SortedMap<String, VisualProperty<?>> names = new TreeMap<String, VisualProperty<?>>();
// Sort by field name
for(final VisualProperty<?> vp:visualProperties) {
names.put(vp.getIdString(), vp);
}
final JsonFactory factory = new JsonFactory();
String result = null;
ByteArrayOutputStream stream = new ByteArrayOutputStream();
JsonGenerator generator = factory.createGenerator(stream);
generator.useDefaultPrettyPrinter();
generator.writeStartArray();
for(final View<? extends CyIdentifiable> view:views) {
generator.writeStartObject();
generator.writeNumberField(CyIdentifiable.SUID, view.getModel().getSUID());
generator.writeArrayFieldStart("view");
addKeyValuePair(generator, names, view);
generator.writeEndArray();
generator.writeEndObject();
}
generator.writeEndArray();
generator.close();
result = stream.toString("UTF-8");
stream.close();
return result;
}
public final String serializeView(final View<? extends CyIdentifiable> view, final Collection<VisualProperty<?>> visualProperties) throws IOException {
final SortedMap<String, VisualProperty<?>> names = new TreeMap<String, VisualProperty<?>>();
// Sort by field name
for(final VisualProperty<?> vp:visualProperties) {
names.put(vp.getIdString(), vp);
}
final JsonFactory factory = new JsonFactory();
String result = null;
ByteArrayOutputStream stream = new ByteArrayOutputStream();
JsonGenerator generator = factory.createGenerator(stream);
generator.useDefaultPrettyPrinter();
generator.writeStartArray();
addKeyValuePair(generator, names, view);
generator.writeEndArray();
generator.close();
result = stream.toString("UTF-8");
stream.close();
return result;
}
public final String serializeSingleVisualProp(final View<? extends CyIdentifiable> view,
final VisualProperty<?> vp) throws IOException {
final SortedMap<String, VisualProperty<?>> names = new TreeMap<>();
names.put(vp.getIdString(), vp);
final JsonFactory factory = new JsonFactory();
String result = null;
ByteArrayOutputStream stream = new ByteArrayOutputStream();
JsonGenerator generator = factory.createGenerator(stream);
generator.useDefaultPrettyPrinter();
generator.writeStartObject();
generator.writeStringField(VisualStyleMapper.MAPPING_VP, vp.getIdString());
generator.writeFieldName("value");
writeValue((VisualProperty<Object>) vp, view.getVisualProperty(vp), generator);
generator.writeEndObject();
generator.close();
result = stream.toString("UTF-8");
stream.close();
return result;
}
private final void addKeyValuePair(final JsonGenerator generator, final SortedMap<String, VisualProperty<?>> names,
final View<? extends CyIdentifiable> view) throws IOException {
for(final String name:names.keySet()) {
final VisualProperty<Object> vp = (VisualProperty<Object>) names.get(name);
generator.writeStartObject();
generator.writeStringField(VisualStyleMapper.MAPPING_VP, vp.getIdString());
generator.writeFieldName("value");
writeValue(vp, view.getVisualProperty(vp), generator);
generator.writeEndObject();
}
}
public final String serializeDependecies(final Set<VisualPropertyDependency<?>> dependencies) throws IOException {
// Sort by field name
final SortedMap<String, VisualPropertyDependency<?>> names = new TreeMap<String, VisualPropertyDependency<?>>();
for(final VisualPropertyDependency<?> dep:dependencies) {
names.put(dep.getIdString(), dep);
}
final JsonFactory factory = new JsonFactory();
String result = null;
ByteArrayOutputStream stream = new ByteArrayOutputStream();
JsonGenerator generator = factory.createGenerator(stream);
generator.useDefaultPrettyPrinter();
generator.writeStartArray();
for(String key: names.keySet()) {
addDependency(generator, names.get(key));
}
generator.writeEndArray();
generator.close();
result = stream.toString("UTF-8");
stream.close();
return result;
}
private final void addDependency(final JsonGenerator generator, final VisualPropertyDependency<?> dep) throws IOException {
generator.writeStartObject();
generator.writeStringField(VisualStyleMapper.VP_DEPENDENCY, dep.getIdString());
generator.writeBooleanField("enabled", dep.isDependencyEnabled());
generator.writeEndObject();
}
}