neo4j :: Neo4jClient
Neo4jClient is needed to communicate through the REST APIvar client = new Neo4jClient("http://neo4j:7474")
assert client.is_okneo4j :: Neo4jClient :: base_url=
Neo4j REST services baseurlneo4j :: Neo4jClient :: defaultinit
neo4j :: Neo4jClient :: delete_node
Remove the entity from baseneo4j :: Neo4jClient :: nodes_with_label
Retrieve all nodes with specifiedlbl
			neo4j :: Neo4jClient :: nodes_with_labels
Retrieve nodes belonging to all the specifiedlabels.
			neo4j :: Neo4jClient :: post
POSTparams to url
			neo4j :: Neo4jClient :: put
PUTparams at url
			neo4j :: Neo4jClient :: service_root
neo4j $ Neo4jClient :: SELF
Type of this instance, automatically specialized in every classneo4j :: Neo4jClient :: base_url=
Neo4j REST services baseurlcore :: Object :: class_factory
Implementation used byget_class to create the specific class.
			core :: Object :: defaultinit
neo4j :: Neo4jClient :: defaultinit
neo4j :: Neo4jClient :: delete_node
Remove the entity from basecore :: Object :: is_same_instance
Return true ifself and other are the same instance (i.e. same identity).
			core :: Object :: is_same_serialized
Isself the same as other in a serialization context?
			core :: Object :: is_same_type
Return true ifself and other have the same dynamic type.
			neo4j :: Neo4jClient :: nodes_with_label
Retrieve all nodes with specifiedlbl
			neo4j :: Neo4jClient :: nodes_with_labels
Retrieve nodes belonging to all the specifiedlabels.
			core :: Object :: output_class_name
Display class name on stdout (debug only).neo4j :: Neo4jClient :: post
POSTparams to url
			neo4j :: Neo4jClient :: put
PUTparams at url
			neo4j :: Neo4jClient :: service_root
# `Neo4jClient` is needed to communicate through the REST API
#
#     var client = new Neo4jClient("http://neo4j:7474")
#     assert client.is_ok
class Neo4jClient
	# Neo4j REST services baseurl
	var base_url: String
	# REST service to get node data
	private var node_url: String
	# REST service to batch
	private var batch_url: String
	# REST service to send cypher requests
	private var cypher_url: String
	init(base_url: String) do
		self.base_url = base_url
		var root = service_root
		assert root isa JsonObject else
			sys.stderr.write "Neo4jClientError: cannot connect to server at <{base_url}>.\n"
		end
		self.node_url = root["node"].to_s
		self.batch_url = root["batch"].to_s
		self.cypher_url = root["cypher"].to_s
	end
	fun service_root: Serializable do return get(base_url / "db/data")
	# Is the connection with the Neo4j server ok?
	fun is_ok: Bool do return service_root isa JsonObject
	# Empty the graph
	fun clear_graph do
		cypher(new CypherQuery.from_string("MATCH (n) OPTIONAL MATCH n-[r]-() DELETE r, n"))
	end
	# Last errors
	var errors = new Array[String]
	# Nodes view stored locally
	private var local_nodes = new HashMap[String, nullable NeoNode]
	# Save the node in base
	#
	#     var client = new Neo4jClient("http://neo4j:7474")
	#
	#     # Create a node
	#     var andres = new NeoNode
	#     andres["name"] = "Andres"
	#     client.save_node(andres)
	#     assert andres.is_linked
	#
	# Once linked, nodes cannot be created twice:
	#
	#     var oldurl = andres.url
	#     client.save_node(andres) # do nothing
	#     assert andres.url == oldurl
	fun save_node(node: NeoNode): Bool do
		if node.is_linked then return true
		node.neo = self
		var batch = new NeoBatch(self)
		batch.save_node(node)
		# batch.create_edges(node.out_edges)
		var errors = batch.execute
		if not errors.is_empty then
			errors.add_all errors
			return false
		end
		local_nodes[node.url.to_s] = node
		return true
	end
	# Load a node from base
	# Data, labels and edges will be loaded lazily.
	fun load_node(url: String): NeoNode do
		if local_nodes.has_key(url) then
			var node = local_nodes[url]
			if node != null then return node
		end
		var node = new NeoNode.from_neo(self, url)
		local_nodes[url] = node
		return node
	end
	# Remove the entity from base
	fun delete_node(node: NeoNode): Bool do
		if not node.is_linked then return false
		var url = node.url.to_s
		delete(url)
		local_nodes[url] = null
		node.url = null
		return true
	end
	# Edges view stored locally
	private var local_edges = new HashMap[String, nullable NeoEdge]
	# Save the edge in base
	# From and to nodes will be created.
	#
	#     var client = new Neo4jClient("http://neo4j:7474")
	#
	#     var andres = new NeoNode
	#     var kate = new NeoNode
	#     var edge = new NeoEdge(andres, "LOVES", kate)
	#     client.save_edge(edge)
	#     assert andres.is_linked
	#     assert kate.is_linked
	#     assert edge.is_linked
	fun save_edge(edge: NeoEdge): Bool do
		if edge.is_linked then return true
		edge.neo = self
		edge.from.out_edges.add edge
		edge.to.in_edges.add edge
		var batch = new NeoBatch(self)
		batch.save_edge(edge)
		var errors = batch.execute
		if not errors.is_empty then
			errors.add_all errors
			return false
		end
		local_edges[edge.url.to_s] = edge
		return true
	end
	# Load a edge from base
	# Data will be loaded lazily.
	fun load_edge(url: String): NeoEdge do
		if local_edges.has_key(url) then
			var node = local_edges[url]
			if node != null then return node
		end
		var edge = new NeoEdge.from_neo(self, url)
		local_edges[url] = edge
		return edge
	end
	# Remove the edge from base
	fun delete_edge(edge: NeoEdge): Bool do
		if not edge.is_linked then return false
		var url = edge.url.to_s
		delete(url)
		local_edges[url] = null
		edge.url = null
		return true
	end
	# Retrieve all nodes with specified `lbl`
	#
	#     var client = new Neo4jClient("http://neo4j:7474")
	#
	#     var andres = new NeoNode
	#     andres.labels.add_all(["Human", "Male"])
	#     client.save_node(andres)
	#     var kate = new NeoNode
	#     kate.labels.add_all(["Human", "Female"])
	#     client.save_node(kate)
	#
	#     var nodes = client.nodes_with_label("Human")
	#     assert nodes.has(andres)
	#     assert nodes.has(kate)
	fun nodes_with_label(lbl: String): Array[NeoNode] do
		var res = get(base_url / "db/data/label/{lbl.to_percent_encoding}/nodes")
		var nodes = new Array[NeoNode]
		for json in res.as(JsonArray) do
			var obj = json.as(JsonObject)
			var node = load_node(obj["self"].to_s)
			node.internal_properties = obj["data"].as(JsonObject)
			nodes.add node
		end
		return nodes
	end
	# Retrieve nodes belonging to all the specified `labels`.
	#
	#     var client = new Neo4jClient("http://neo4j:7474")
	#
	#     var andres = new NeoNode
	#     andres.labels.add_all(["Human", "Male"])
	#     client.save_node(andres)
	#     var kate = new NeoNode
	#     kate.labels.add_all(["Human", "Female"])
	#     client.save_node(kate)
	#
	#     var nodes = client.nodes_with_labels(["Human", "Male"])
	#     assert nodes.has(andres)
	#     assert not nodes.has(kate)
	fun nodes_with_labels(labels: Array[String]): Array[NeoNode] do
		assert not labels.is_empty
		# Build the query.
		var buffer = new Buffer
		buffer.append "match (n) where \{label_0\} in labels(n)"
		for i in [1..labels.length[ do
			buffer.append " and \{label_{i}\} in labels(n)"
		end
		buffer.append " return n"
		var query = new CypherQuery.from_string(buffer.write_to_string)
		for i in [0..labels.length[ do
			query.params["label_{i}"] = labels[i]
		end
		# Retrieve the answer.
		var res = cypher(query)
		var nodes = new Array[NeoNode]
		for json in res.as(JsonObject)["data"].as(JsonArray) do
			var obj = json.as(JsonArray).first.as(JsonObject)
			var node = load_node(obj["self"].to_s)
			node.internal_properties = obj["data"].as(JsonObject)
			nodes.add node
		end
		return nodes
	end
	# Perform a `CypherQuery`
	# see: CypherQuery
	fun cypher(query: CypherQuery): Serializable do
		return post("{cypher_url}", query.to_rest)
	end
	# GET JSON data from `url`
	fun get(url: String): Serializable do
		var request = new JsonGET(url)
		var response = request.execute
		return parse_response(response)
	end
	# POST `params` to `url`
	fun post(url: String, params: Serializable): Serializable do
		var request = new JsonPOST(url)
		request.json_data = params
		var response = request.execute
		return parse_response(response)
	end
	# PUT `params` at `url`
	fun put(url: String, params: Serializable): Serializable do
		var request = new JsonPUT(url)
		request.json_data = params
		var response = request.execute
		return parse_response(response)
	end
	# DELETE `url`
	fun delete(url: String): Serializable do
		var request = new JsonDELETE(url)
		var response = request.execute
		return parse_response(response)
	end
	# Parse the cURL `response` as a JSON string
	private fun parse_response(response: CurlResponse): Serializable do
		if response isa CurlResponseSuccess then
			var str = response.body_str
			if str.is_empty then return new JsonObject
			var res = str.parse_json
			if res isa JsonParseError then
				var e = new NeoError(res.to_s, "JsonParseError")
				e.cause = res
				return e
			end
			if res == null then
				# empty response wrap it in empty object
				return new JsonObject
			else if res isa JsonObject and res.has_key("exception") then
				var error = "Neo4jError::{res["exception"] or else "null"}"
				var msg = ""
				if res.has_key("message") then
					msg = res["message"].to_s
				end
				return new NeoError(msg, error)
			else
				return res
			end
		else if response isa CurlResponseFailed then
			return new NeoError("{response.error_msg} ({response.error_code})", "CurlError")
		else
			return new NeoError("Unexpected response \"{response}\".", "CurlError")
		end
	end
end
					lib/neo4j/neo4j.nit:63,1--343,3