package com.tinkerpop.rexster;
import com.sun.jersey.api.client.ClientRequest;
import com.sun.jersey.api.client.ClientResponse;
import com.tinkerpop.blueprints.Edge;
import com.tinkerpop.blueprints.Vertex;
import com.tinkerpop.blueprints.impls.tg.TinkerGraph;
import com.tinkerpop.blueprints.impls.tg.TinkerGraphFactory;
import com.tinkerpop.blueprints.util.io.graphson.GraphSONMode;
import com.tinkerpop.blueprints.util.io.graphson.GraphSONUtility;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import org.junit.After;
import org.junit.Before;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
public abstract class AbstractGraphResourceIntegrationTest extends AbstractResourceIntegrationTest {
protected List<GraphTestHolder> testGraphs;
public AbstractGraphResourceIntegrationTest() throws Exception {
super();
}
@Before
public void setUp() throws Exception {
// the @Before in the superclass should be called automatically before this...but isn't
super.setUp();
ClientRequest request = ClientRequest.create().build(createUri("/"), "GET");
ClientResponse response = this.client.handle(request);
JSONObject json = response.getEntity(JSONObject.class);
JSONArray jsonArray = json.optJSONArray("graphs");
TinkerGraph testGraph = TinkerGraphFactory.createTinkerGraph();
this.testGraphs = new ArrayList<GraphTestHolder>();
for (int ix = 0; ix < jsonArray.length(); ix++) {
ClientRequest graphRequest = ClientRequest.create().build(createUri("/" + jsonArray.optString(ix)), "GET");
ClientResponse graphResponse = this.client.handle(graphRequest);
JSONObject graphJson = graphResponse.getEntity(JSONObject.class);
final JSONObject featuresJson = graphJson.optJSONObject("features");
final Map<String, Boolean> features = new HashMap<String, Boolean>();
Iterator<String> keys = featuresJson.keys();
while (keys.hasNext()) {
final String key = keys.next();
features.put(key, featuresJson.optBoolean(key));
}
GraphTestHolder holder = new GraphTestHolder(graphJson.optString("name"),
graphJson.optString("type"), features);
this.testGraphs.add(holder);
for (Vertex v : testGraph.getVertices()) {
postVertex(holder, v);
}
for (Edge e : testGraph.getEdges()) {
postEdge(holder, e);
}
}
}
@After
public void tearDown() throws Exception {
try {
for (GraphTestHolder testGraph : this.testGraphs) {
ClientResponse response = doGraphGet(testGraph, "vertices");
JSONObject verticesJson = response.getEntity(JSONObject.class);
JSONArray verticesToDelete = verticesJson.optJSONArray(Tokens.RESULTS);
for (int ix = 0; ix < verticesToDelete.length(); ix++) {
this.client.handle(ClientRequest.create().build(createUri("/" + testGraph.getGraphName() + "/vertices/" + encode(verticesToDelete.optJSONObject(ix).optString(Tokens._ID))), "DELETE"));
}
if (testGraph.getFeatures().supportsIndices) {
response = doGraphGet(testGraph, "indices");
JSONObject indicesJson = response.getEntity(JSONObject.class);
JSONArray indicesToDelete = indicesJson.optJSONArray(Tokens.RESULTS);
for (int ix = 0; ix < indicesToDelete.length(); ix++) {
this.client.handle(ClientRequest.create().build(createUri("/" + testGraph.getGraphName() + "/indices/" + indicesToDelete.optJSONObject(ix).optString("name")), "DELETE"));
}
}
// todo: hack around titan inability to drop key indices
if (!testGraph.getGraphType().equals("com.thinkaurelius.titan.graphdb.database.StandardTitanGraph")) {
response = doGraphGet(testGraph, "keyindices/vertex");
JSONObject keyIndicesVertexJson = response.getEntity(JSONObject.class);
JSONArray keyIndicesVertexToDelete = keyIndicesVertexJson.optJSONArray(Tokens.RESULTS);
for (int ix = 0; ix < keyIndicesVertexToDelete.length(); ix++) {
this.client.handle(ClientRequest.create().build(createUri("/" + testGraph.getGraphName() + "/keyindices/vertex/" + encode(keyIndicesVertexToDelete.optString(ix))), "DELETE"));
}
response = doGraphGet(testGraph, "keyindices/edge");
JSONObject keyIndicesEdgeJson = response.getEntity(JSONObject.class);
JSONArray keyIndicesEdgeToDelete = keyIndicesEdgeJson.optJSONArray(Tokens.RESULTS);
for (int ix = 0; ix < keyIndicesEdgeToDelete.length(); ix++) {
this.client.handle(ClientRequest.create().build(createUri("/" + testGraph.getGraphName() + "/keyindices/edge/" + keyIndicesEdgeToDelete.optString(ix)), "DELETE"));
}
}
}
} finally {
super.tearDown();
}
}
protected void postVertex(GraphTestHolder graphHolder, Vertex v) throws JSONException {
ClientRequest request = ClientRequest.create().type(RexsterMediaType.APPLICATION_REXSTER_TYPED_JSON).build(createUri("/" + graphHolder.getGraphName() + "/vertices"), "POST");
request.setEntity(typeTheElement(GraphSONUtility.jsonFromElement(v, null, GraphSONMode.NORMAL)));
ClientResponse response = this.client.handle(request);
JSONObject jsonObject = response.getEntity(JSONObject.class);
String id = jsonObject.optJSONObject(Tokens.RESULTS).optString(Tokens._ID);
graphHolder.getVertexIdSet().put(v.getId().toString(), id);
}
protected void postEdge(GraphTestHolder graphHolder, Edge e) throws JSONException {
ClientRequest request = ClientRequest.create().build(createUri("/" + graphHolder.getGraphName() + "/edges"), "POST");
JSONObject jsonEdge = typeTheElement(GraphSONUtility.jsonFromElement(e, null, GraphSONMode.NORMAL));
jsonEdge.put(Tokens._IN_V, graphHolder.getVertexIdSet().get(jsonEdge.optString(Tokens._IN_V)));
jsonEdge.put(Tokens._OUT_V, graphHolder.getVertexIdSet().get(jsonEdge.optString(Tokens._OUT_V)));
request.setEntity(jsonEdge);
List<Object> headerValue = new ArrayList<Object>() {{
add(RexsterMediaType.APPLICATION_REXSTER_TYPED_JSON);
}};
request.getHeaders().put("Content-Type", headerValue);
ClientResponse response = this.client.handle(request);
JSONObject jsonObject = response.getEntity(JSONObject.class);
String id = jsonObject.optJSONObject(Tokens.RESULTS).optString(Tokens._ID);
graphHolder.getEdgeIdSet().put(e.getId().toString(), id);
}
protected void initKeyIndex(GraphTestHolder graphHolder) {
if (graphHolder.getFeatures().supportsKeyIndices) {
ClientRequest.create().build(createUri("/" + graphHolder.getGraphName() + "/keyindices/name"), "POST");
}
}
public static JSONObject typeTheElement(JSONObject json) {
// map is only one level deep for the test graph so this doesn't really need to be recursive
final Iterator it = json.keys();
try {
while (it.hasNext()) {
final String key = (String) it.next();
if (!key.startsWith("_")) {
final Object value = json.opt(key);
if (value instanceof String)
json.put(key, "(s," + value.toString() + ")");
else if (value instanceof Integer)
json.put(key, "(i," + value + ")");
else if (value instanceof Long)
json.put(key, "(l," + value + ")");
else if (value instanceof Float)
json.put(key, "(f," + value + ")");
else if (value instanceof Double)
json.put(key, "(d," + value + ")");
else
json.put(key, value.toString());
}
}
} catch (JSONException jsone) {
}
return json;
}
}