package org.cytoscape.rest.internal.serializer; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.cytoscape.model.CyColumn; import org.cytoscape.model.CyEdge; import org.cytoscape.model.CyIdentifiable; import org.cytoscape.model.CyRow; import org.cytoscape.rest.internal.resource.JsonTags; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonGenerationException; import com.fasterxml.jackson.core.JsonGenerator; public class GraphObjectSerializer { private static final Pattern REPLACE_INVALID_JS_CHAR_PATTERN = Pattern.compile("^[^a-zA-Z_]+|[^a-zA-Z_0-9]+"); public final String serializeGraphObject(final CyIdentifiable obj, final CyRow row) throws IOException { final JsonFactory factory = new JsonFactory(); String result = null; ByteArrayOutputStream stream = new ByteArrayOutputStream(); JsonGenerator generator = null; generator = factory.createGenerator(stream); generator.writeStartObject(); generator.writeObjectFieldStart("data"); serializeRow(generator, obj, row); generator.writeEndObject(); generator.writeEndObject(); generator.close(); result = stream.toString("UTF-8"); stream.close(); return result; } public final String serializeRow(final CyRow row) throws IOException { final JsonFactory factory = new JsonFactory(); String result = null; ByteArrayOutputStream stream = new ByteArrayOutputStream(); JsonGenerator generator = null; generator = factory.createGenerator(stream); generator.writeStartObject(); serializeSingleRow(generator, row); generator.writeEndObject(); generator.close(); result = stream.toString("UTF-8"); stream.close(); return result; } public final String serializeCell(final CyRow row, final String columnName) throws IOException { final CyColumn column = row.getTable().getColumn(columnName); if (column == null) { throw new IOException("No such column: " + columnName); } final Object value = row.get(columnName, column.getType()); final JsonFactory factory = new JsonFactory(); String result = null; ByteArrayOutputStream stream = new ByteArrayOutputStream(); JsonGenerator generator = null; generator = factory.createGenerator(stream); generator.writeStartObject(); serializeCell(generator, column, value); generator.writeEndObject(); generator.close(); result = stream.toString("UTF-8"); stream.close(); return result; } public final String serializeAllRows(final Collection<CyRow> rows) throws IOException { final JsonFactory factory = new JsonFactory(); String result = null; ByteArrayOutputStream stream = new ByteArrayOutputStream(); JsonGenerator generator = null; generator = factory.createGenerator(stream); generator.writeStartArray(); for (final CyRow row : rows) { generator.writeStartObject(); serializeSingleRow(generator, row); generator.writeEndObject(); } generator.writeEndArray(); generator.close(); result = stream.toString("UTF-8"); stream.close(); return result; } public final String serializeColumns(final Collection<CyColumn> columns) throws IOException { final JsonFactory factory = new JsonFactory(); String result = null; ByteArrayOutputStream stream = new ByteArrayOutputStream(); JsonGenerator generator = null; generator = factory.createGenerator(stream); generator.writeStartArray(); for (final CyColumn column : columns) { generator.writeStartObject(); generator.writeStringField(JsonTags.COLUMN_NAME, column.getName()); generator.writeStringField(JsonTags.COLUMN_TYPE, column.getType().getSimpleName()); generator.writeBooleanField(JsonTags.COLUMN_IMMUTABLE, column.isImmutable()); generator.writeBooleanField(JsonTags.PRIMARY_KEY, column.isPrimaryKey()); generator.writeEndObject(); } generator.writeEndArray(); generator.close(); result = stream.toString("UTF-8"); stream.close(); return result; } public final String serializeColumnValues(final CyColumn column, final Collection<Object> values) throws IOException { final JsonFactory factory = new JsonFactory(); String result = null; ByteArrayOutputStream stream = new ByteArrayOutputStream(); JsonGenerator generator = null; generator = factory.createGenerator(stream); try { generator.writeStartObject(); generator.writeStringField(JsonTags.COLUMN_NAME, column.getName()); generator.writeFieldName(JsonTags.COLUMN_VALUES); generator.writeStartArray(); for (final Object value : values) { if (column.getType() == List.class) { writeList(column.getListElementType(), (List<?>) value, generator); } else { writeValue(column.getType(), value, generator); } } generator.writeEndArray(); generator.writeEndObject(); generator.close(); result = stream.toString("UTF-8"); stream.close(); } catch(Exception e) { e.printStackTrace(); } return result; } private final void serializeSingleRow(final JsonGenerator generator, final CyRow row) throws IOException { final Collection<CyColumn> columns = row.getTable().getColumns(); final Map<String, Object> values = row.getAllValues(); for (final CyColumn col : columns) { final Object value = values.get(col.getName()); if (value == null) continue; Class<?> type = col.getType(); final String columnName = col.getName(); generator.writeFieldName(replaceColumnName(columnName)); if (type == List.class) { writeList(col.getListElementType(), (List<?>) value, generator); } else { writeValue(type, value, generator); } } } private final void serializeRow(JsonGenerator generator, final CyIdentifiable obj, final CyRow row) throws IOException { final Collection<CyColumn> columns = row.getTable().getColumns(); final Map<String, Object> values = row.getAllValues(); if (obj instanceof CyEdge) { final Long sourceId = ((CyEdge) obj).getSource().getSUID(); final Long targetId = ((CyEdge) obj).getTarget().getSUID(); generator.writeNumberField("source", sourceId); generator.writeNumberField("target", targetId); } else { generator.writeNumberField("id", obj.getSUID()); } for (final CyColumn col : columns) { final Object value = values.get(col.getName()); if (value == null) continue; Class<?> type = col.getType(); final String columnName = col.getName(); generator.writeFieldName(replaceColumnName(columnName)); if (type == List.class) { writeList(col.getListElementType(), (List<?>) value, generator); } else { writeValue(type, value, generator); } } } private final void serializeCell(final JsonGenerator generator, final CyColumn col, Object value) throws IOException { Class<?> type = col.getType(); final String columnName = col.getName(); generator.writeFieldName(replaceColumnName(columnName)); if (type == List.class) { writeList(col.getListElementType(), (List<?>) value, generator); } else { writeValue(type, value, generator); } } private final void writeList(final Class<?> type, final List<?> values, final JsonGenerator jgen) throws JsonGenerationException, IOException { if(values == null) { return; } jgen.writeStartArray(); for (final Object value : values) writeValue(type, value, jgen); jgen.writeEndArray(); } private final String replaceColumnName(final String columnName) { final Matcher matcher = REPLACE_INVALID_JS_CHAR_PATTERN.matcher(columnName); return matcher.replaceAll("_"); } private final void writeValue(final Class<?> type, final Object value, final JsonGenerator generator) throws IOException { if(value == null) { return; } 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); } } }