package org.vertexium.cypher; import org.vertexium.Edge; import org.vertexium.Element; import org.vertexium.Property; import org.vertexium.Vertex; import org.vertexium.cypher.exceptions.VertexiumCypherNotImplemented; import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; import static org.vertexium.util.IterableUtils.count; import static org.vertexium.util.StreamUtils.stream; public class CypherResultWriter { public String columnValueToString(VertexiumCypherQueryContext ctx, Object o) { if (o == null) { return columnNullValueToString(); } else if (o instanceof Optional) { return columnValueToString(ctx, ((Optional<?>) o).orElse(null)); } else if (o instanceof Map) { //noinspection unchecked return columnMapValueToString(ctx, (Map<String, Object>) o); } else if (o instanceof Double) { return columnDoubleValueToString((double) o); } else if (o instanceof Vertex) { return columnVertexToString(ctx, (Vertex) o); } else if (o instanceof Edge) { return columnEdgeToString(ctx, (Edge) o); } else if (o instanceof String) { return columnStringToString(o); } else if (o instanceof VertexiumCypherScope.PathItem) { return columnPathResultToString(ctx, (VertexiumCypherScope.PathItem) o); } else if (o instanceof Iterable) { return columnValueIterableToString(ctx, (Iterable<?>) o); } else { return columnUnknownToString(o); } } private String columnPathResultToString(VertexiumCypherQueryContext ctx, VertexiumCypherScope.PathItem pathResult) { return pathResult.toString(ctx); } private String columnValueIterableToString(VertexiumCypherQueryContext ctx, Iterable<?> list) { return "[" + stream(list).map(item -> columnValueToString(ctx, item)).collect(Collectors.joining(", ")) + "]"; } private String columnUnknownToString(Object o) { return o.toString(); } private String columnStringToString(Object o) { return "'" + o + "'"; } private String columnVertexToString(VertexiumCypherQueryContext ctx, Vertex vertex) { StringBuilder result = new StringBuilder(); result.append("("); int propertyCount = 0; for (Property property : vertex.getProperties()) { if (property.getName().equals(ctx.getLabelPropertyName())) { result.append(":"); result.append(property.getValue()); } else { propertyCount++; } } if (propertyCount > 0) { if (result.length() > "(".length()) { result.append(" "); } result.append(elementPropertiesToString(ctx, vertex)); } result.append(")"); return result.toString(); } private String elementPropertiesToString(VertexiumCypherQueryContext ctx, Element element) { StringBuilder result = new StringBuilder(); boolean first = true; for (Property property : element.getProperties()) { if (property.getName().equals(ctx.getLabelPropertyName())) { continue; } if (first) { result.append("{"); } else { result.append(", "); } result.append(property.getName()); result.append(": "); result.append(columnValueToString(ctx, property.getValue())); first = false; } if (result.length() > 0) { result.append("}"); } return result.toString(); } private String columnEdgeToString(VertexiumCypherQueryContext ctx, Edge edge) { StringBuilder result = new StringBuilder(); result.append("["); result.append(":"); result.append(edge.getLabel()); if (count(edge.getProperties()) > 0) { result.append(" "); result.append(elementPropertiesToString(ctx, edge)); } result.append("]"); return result.toString(); } private String columnDoubleValueToString(double o) { NumberFormat formatter = new DecimalFormat(o < 0 ? ".0#############" : "0.0#############"); return formatter.format(o); } private String columnMapValueToString(VertexiumCypherQueryContext ctx, Map<String, Object> o) { StringBuilder result = new StringBuilder(); result.append("{"); boolean first = true; for (Map.Entry<String, Object> entry : o.entrySet()) { if (!first) { result.append(", "); } result.append(entry.getKey()); result.append(": "); result.append(columnValueToString(ctx, entry.getValue())); first = false; } result.append("}"); return result.toString(); } private String columnNullValueToString() { return "null"; } }