blob: 04680da683d6254e37e1fc4fbe17d831bd270e64 [file] [log] [blame]
/*
* Copyright 2017 HugeGraph Authors
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with this
* work for additional information regarding copyright ownership. The ASF
* licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package com.baidu.hugegraph.serializer;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
import org.apache.tinkerpop.gremlin.structure.Edge;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.apache.tinkerpop.gremlin.structure.util.CloseableIterator;
import com.baidu.hugegraph.HugeException;
import com.baidu.hugegraph.api.API;
import com.baidu.hugegraph.auth.SchemaDefine.UserElement;
import com.baidu.hugegraph.backend.id.Id;
import com.baidu.hugegraph.backend.page.PageInfo;
import com.baidu.hugegraph.iterator.Metadatable;
import com.baidu.hugegraph.schema.EdgeLabel;
import com.baidu.hugegraph.schema.IndexLabel;
import com.baidu.hugegraph.schema.PropertyKey;
import com.baidu.hugegraph.schema.VertexLabel;
import com.baidu.hugegraph.traversal.algorithm.CustomizedCrosspointsTraverser.CrosspointsPaths;
import com.baidu.hugegraph.traversal.algorithm.FusiformSimilarityTraverser.SimilarsMap;
import com.baidu.hugegraph.traversal.algorithm.HugeTraverser;
import com.baidu.hugegraph.traversal.algorithm.SingleSourceShortestPathTraverser.NodeWithWeight;
import com.baidu.hugegraph.traversal.algorithm.SingleSourceShortestPathTraverser.WeightedPaths;
import com.baidu.hugegraph.traversal.optimize.TraversalUtil;
import com.baidu.hugegraph.util.JsonUtil;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
public class JsonSerializer implements Serializer {
private static final int LBUF_SIZE = 1024;
private static JsonSerializer INSTANCE = new JsonSerializer();
private JsonSerializer() {
}
public static JsonSerializer instance() {
return INSTANCE;
}
@Override
public String writeMap(Map<?, ?> map) {
return JsonUtil.toJson(map);
}
@Override
public String writeList(String label, Collection<?> list) {
try (ByteArrayOutputStream out = new ByteArrayOutputStream(LBUF_SIZE)) {
out.write(String.format("{\"%s\": ", label).getBytes(API.CHARSET));
out.write(JsonUtil.toJson(list).getBytes(API.CHARSET));
out.write("}".getBytes(API.CHARSET));
return out.toString(API.CHARSET);
} catch (Exception e) {
throw new HugeException("Failed to serialize %s", e, label);
}
}
private String writeIterator(String label, Iterator<?> iter,
boolean paging) {
// Early throw if needed
iter.hasNext();
// Serialize Iterator
try (ByteArrayOutputStream out = new ByteArrayOutputStream(LBUF_SIZE)) {
out.write("{".getBytes(API.CHARSET));
out.write(String.format("\"%s\":[", label).getBytes(API.CHARSET));
// Write data
boolean first = true;
while (iter.hasNext()) {
if (!first) {
out.write(",".getBytes(API.CHARSET));
} else {
first = false;
}
out.write(JsonUtil.toJson(iter.next()).getBytes(API.CHARSET));
}
out.write("]".getBytes(API.CHARSET));
// Write page
if (paging) {
String page;
if (iter instanceof GraphTraversal<?, ?>) {
page = TraversalUtil.page((GraphTraversal<?, ?>) iter);
} else if (iter instanceof Metadatable) {
page = PageInfo.pageInfo(iter);
} else {
throw new HugeException("Invalid paging iterator: %s",
iter.getClass());
}
if (page != null) {
page = String.format(",\"page\": \"%s\"", page);
} else {
page = ",\"page\": null";
}
out.write(page.getBytes(API.CHARSET));
}
out.write("}".getBytes(API.CHARSET));
return out.toString(API.CHARSET);
} catch (HugeException e) {
throw e;
} catch (Exception e) {
throw new HugeException("Failed to serialize %s", e, label);
} finally {
try {
CloseableIterator.closeIterator(iter);
} catch (Exception e) {
throw new HugeException("Failed to close for %s", e, label);
}
}
}
@Override
public String writePropertyKey(PropertyKey propertyKey) {
return JsonUtil.toJson(propertyKey);
}
@Override
public String writePropertyKeys(List<PropertyKey> propertyKeys) {
return writeList("propertykeys", propertyKeys);
}
@Override
public String writeVertexLabel(VertexLabel vertexLabel) {
return JsonUtil.toJson(vertexLabel);
}
@Override
public String writeVertexLabels(List<VertexLabel> vertexLabels) {
return writeList("vertexlabels", vertexLabels);
}
@Override
public String writeEdgeLabel(EdgeLabel edgeLabel) {
return JsonUtil.toJson(edgeLabel);
}
@Override
public String writeEdgeLabels(List<EdgeLabel> edgeLabels) {
return writeList("edgelabels", edgeLabels);
}
@Override
public String writeIndexlabel(IndexLabel indexLabel) {
return JsonUtil.toJson(indexLabel);
}
@Override
public String writeIndexlabels(List<IndexLabel> indexLabels) {
return writeList("indexlabels", indexLabels);
}
@Override
public String writeCreatedIndexLabel(IndexLabel.CreatedIndexLabel cil) {
StringBuilder builder = new StringBuilder();
long id = cil.task() == null ? 0L : cil.task().asLong();
return builder.append("{\"index_label\": ")
.append(this.writeIndexlabel(cil.indexLabel()))
.append(", \"task_id\": ").append(id).append("}")
.toString();
}
@Override
public String writeVertex(Vertex vertex) {
return JsonUtil.toJson(vertex);
}
@Override
public String writeVertices(Iterator<Vertex> vertices, boolean paging) {
return this.writeIterator("vertices", vertices, paging);
}
@Override
public String writeEdge(Edge edge) {
return JsonUtil.toJson(edge);
}
@Override
public String writeEdges(Iterator<Edge> edges, boolean paging) {
return this.writeIterator("edges", edges, paging);
}
@Override
public String writeIds(List<Id> ids) {
return JsonUtil.toJson(ids);
}
@Override
public String writeUserElement(UserElement elem) {
return this.writeMap(elem.asMap());
}
@Override
public <V extends UserElement> String writeUserElements(String label,
List<V> elems) {
List<Object> list = new ArrayList<>(elems.size());
for (V elem : elems) {
list.add(elem.asMap());
}
return this.writeList(label, list);
}
@Override
public String writePaths(String name, Collection<HugeTraverser.Path> paths,
boolean withCrossPoint,
Iterator<Vertex> vertices) {
List<Map<String, Object>> pathList = new ArrayList<>(paths.size());
for (HugeTraverser.Path path : paths) {
pathList.add(path.toMap(withCrossPoint));
}
Map<String, Object> results;
if (vertices == null) {
results = ImmutableMap.of(name, pathList);
} else {
results = ImmutableMap.of(name, pathList, "vertices", vertices);
}
return JsonUtil.toJson(results);
}
@Override
public String writeCrosspoints(CrosspointsPaths paths,
Iterator<Vertex> iterator,
boolean withPath) {
Map<String, Object> results;
List<Map<String, Object>> pathList;
if (withPath) {
pathList = new ArrayList<>();
for (HugeTraverser.Path path : paths.paths()) {
pathList.add(path.toMap(false));
}
} else {
pathList = ImmutableList.of();
}
results = ImmutableMap.of("crosspoints", paths.crosspoints(),
"paths", pathList,
"vertices", iterator);
return JsonUtil.toJson(results);
}
@Override
public String writeSimilars(SimilarsMap similars,
Iterator<Vertex> vertices) {
return JsonUtil.toJson(ImmutableMap.of("similars", similars.toMap(),
"vertices", vertices));
}
@Override
public String writeWeightedPath(NodeWithWeight path,
Iterator<Vertex> vertices) {
Map<String, Object> pathMap = path == null ?
ImmutableMap.of() : path.toMap();
return JsonUtil.toJson(ImmutableMap.of("path", pathMap,
"vertices", vertices));
}
@Override
public String writeWeightedPaths(WeightedPaths paths,
Iterator<Vertex> vertices) {
Map<Id, Map<String, Object>> pathMap = paths == null ?
ImmutableMap.of() :
paths.toMap();
return JsonUtil.toJson(ImmutableMap.of("paths", pathMap,
"vertices", vertices));
}
@Override
public String writeNodesWithPath(String name, Set<Id> nodes,
Collection<HugeTraverser.Path> paths,
Iterator<Vertex> iterator,
boolean countOnly) {
List<Map<String, Object>> pathList = new ArrayList<>();
for (HugeTraverser.Path path : paths) {
pathList.add(path.toMap(false));
}
Map<String, Object> results;
results = ImmutableMap.of("size", nodes.size(),
name, countOnly ? ImmutableSet.of() : nodes,
"paths", pathList,
"vertices", iterator);
return JsonUtil.toJson(results);
}
}