1
0
Fork 0

Merge branch 'devel' of github.com:triAGENS/ArangoDB into devel

Conflicts:
	js/actions/api-traversal.js
This commit is contained in:
Michael Hackstein 2014-06-18 15:56:55 +02:00
commit e37167674b
8 changed files with 310 additions and 764 deletions

View File

@ -12,124 +12,19 @@ The edge definitions for a graph is an Array containing arbitrary many directed
!SUBSECTION Initialize the list
<br />
The edge definitions for a graph is an array containing arbitrary many directed
and/or undirected relations as defined below.
The list of edge definitions of a graph can be managed by the graph module itself.
This function is the entry point for the management and will return the correct list.
<br />
@EXAMPLES
<br />
<br />
```
arangosh> var graph = require("org/arangodb/general-graph");
arangosh> directed-relation = graph._directedRelationDefinition("lives_in", "user", "city");
ReferenceError: Invalid left-hand side in assignment
```
<br />
@startDocuBlock JSF_general_graph_edge_definitions
!SUBSECTION Extend the list
<br />
In order to add more edge definitions to the graph before creating
this function can be used to add more definitions to the initial list.
<br />
@EXAMPLES
<br />
```
arangosh> var graph = require("org/arangodb/general-graph");
arangosh> directed-relation = graph._directedRelationDefinition("lives_in", "user", "city");
ReferenceError: Invalid left-hand side in assignment
```
<br />
@startDocuBlock JSF_general_graph_extend_edge_definitions
!SUBSUBSECTION Undirected Relation
<br />
`general-graph._undirectedRelationDefinition(relationName, vertexCollections)`
*Define an undirected relation.*
<br />
Defines an undirected relation with the name *relationName* using the
list of *vertexCollections*. This relation allows the user to store
edges in any direction between any pair of vertices within the
*vertexCollections*.
<br />
@EXAMPLES
<br />
To define simple relation with only one vertex collection:
<br />
```
arangosh> var graph = require("org/arangodb/general-graph");
arangosh> graph._undirectedRelationDefinition("friend", "user");
{
"collection" : "friend",
"from" : [
"user"
],
"to" : [
"user"
]
}
```
<br />
To define a relation between several vertex collections:
<br />
```
arangosh> var graph = require("org/arangodb/general-graph");
arangosh> graph._undirectedRelationDefinition("marriage", ["female", "male"]);
{
"collection" : "marriage",
"from" : [
"female",
"male"
],
"to" : [
"female",
"male"
]
}
```
@startDocuBlock JSF_general_graph_undirectedRelationDefinition@startDocuBlock
!SUBSUBSECTION Directed Relation
<br />
`general-graph._directedRelationDefinition(relationName, fromVertexCollections, toVertexCollections)`
*Define a directed relation.*
<br />
The *relationName* defines the name of this relation and references to the underlying edge collection.
The *fromVertexCollections* is an Array of document collections holding the start vertices.
The *toVertexCollections* is an Array of document collections holding the target vertices.
Relations are only allowed in the direction from any collection in *fromVertexCollections*
to any collection in *toVertexCollections*.
<br />
@EXAMPLES
<br />
```
arangosh> var graph = require("org/arangodb/general-graph");
arangosh> graph._directedRelationDefinition("has_bought", ["Customer", "Company"], ["Groceries", "Electronics"]);
{
"collection" : "has_bought",
"from" : [
"Customer",
"Company"
],
"to" : [
"Groceries",
"Electronics"
]
}
```
@startDocuBlock JSF_general_graph_directedRelationDefinition
!SUBSECTION Orphan Collections
@ -139,131 +34,21 @@ it will be removed from the orphan collection automatically.
!SUBSUBSECTION Add
Adds a vertex collection to the set of orphan collections of the graph. If the
collection does not exist, it will be created.
<br />
`general-graph._addOrphanCollection(orphanCollectionName, createCollection)`
<br />
* *orphanCollectionName* - string : name of vertex collection.
* *createCollection* - bool : if true the collection will be created if it does not exist. Default: true.
<br />
@EXAMPLES
<br />
```
arangosh> var graph = require("org/arangodb/general-graph")
arangosh> var ed1 = graph._directedRelationDefinition("myEC1", ["myVC1"], ["myVC2"]);
arangosh> var g = graph._create("myGraph", [ed1]);
arangosh> g._addOrphanCollection("myVC3", true);
undefined
```
<br />
@startDocuBlock JSF_general_graph__addVertexCollection
!SUBSUBSECTION Read
Returns all vertex collections of the graph, that are not used in an edge definition.
<br />
`general-graph._getOrphanCollections()`
<br />
@EXAMPLES
<br />
```
arangosh> var graph = require("org/arangodb/general-graph")
arangosh> var ed1 = graph._directedRelationDefinition("myEC1", ["myVC1"], ["myVC2"]);
arangosh> var g = graph._create("myGraph", [ed1]);
arangosh> g._addOrphanCollection("myVC3", true);
undefined
arangosh> g._getOrphanCollections();
[
"myVC3"
]
```
<br />
@startDocuBlock JSF_general_graph__orphanCollections
!SUBSUBSECTION Remove
Removes an orphan collection from the graph and deletes the collection, if it is not
used in any graph.
<br />
`general-graph._removeOrphanCollection()`
<br />
*orphanCollectionName* - string : name of vertex collection.
*dropCollection* - bool : if true the collection will be dropped if it is not used in any graph.
Default: true.
<br />
@EXAMPLES
<br />
```
arangosh> var graph = require("org/arangodb/general-graph")
arangosh> var ed1 = graph._directedRelationDefinition("myEC1", ["myVC1"], ["myVC2"]);
arangosh> var g = graph._create("myGraph", [ed1]);
arangosh> g._addOrphanCollection("myVC3", true);
undefined
arangosh> g._addOrphanCollection("myVC4", true);
undefined
arangosh> g._getOrphanCollections();
[
"myVC3",
"myVC4"
]
arangosh> g._removeOrphanCollection("myVC3");
undefined
arangosh> g._getOrphanCollections();
[
"myVC4"
]
```
<br />
@startDocuBlock JSF_general_graph__removeVertexCollection
!SECTION Create a graph
After having introduced edge definitions and orphan collections a graph can be created.
`general-graph._create(graph-name, edge-definitions, orphan-collections)`
*Create a graph*
<br />
<br />
The creation of a graph requires the name of the graph and a definition of its edges.
<br />
For every type of edge definition a convenience method exists that can be used to create a graph.
Optionaly a list of vertex collections can be added, which are not used in any edge definition.
These collections are refered to as orphan collections within this chapter.
All collections used within the creation process are created if they do not exist.
<br />
* *graph-name*: string - unique identifier of the graph
* *edge-definitions*: array - list of edge definition objects
* *orphan-collections*: array - list of additonal vertex collection names
<br />
@EXAMPLES
<br />
Create an empty graph, edge definitions can be added at runtime:
<br />
```
arangosh> var graph = require("org/arangodb/general-graph");
arangosh> graph._drop("social");
true
```
<br />
Create a graph with edge definitions and orphan collections:
<br />
```
arangosh> var graph = require("org/arangodb/general-graph");
arangosh> graph._drop("social");
true
```
<br />
@startDocuBlock JSF_general_graph_create
!SUBSUBSECTION Complete Example to create a graph
@ -298,343 +83,59 @@ alternative call:
!SUBSECTION List available graphs
@startDocuBlock JSF_general_graph_list_call
`general-graph._list()` *List all graphs.*
<br />
<br />
@startDocuBlock JSF_general_graph_list_info
Lists all graph names stored in this database.
<br />
@EXAMPLES
<br />
<br />
```
arangosh> var graph = require("org/arangodb/general-graph");
arangosh> graph._list();
[
"social"
]
```
@startDocuBlock JSF_general_graph_list_examples
!SUBSECTION Load a graph
`general-graph._graph(graph-name)`
*Load a graph*
<br />
A graph can be loaded by its name.
<br />
* *graph-name*: string - unique identifier of the graph
<br />
@EXAMPLES
<br />
Load a graph:
<br />
```
arangosh> var graph = require("org/arangodb/general-graph");
arangosh> graph._drop("social");
true
```
<br />
@startDocuBlock JSF_general_graph_graph
!SUBSECTION Remove a graph
`general-graph._drop(graph-name, drop-collections)`
*Remove a graph*
<br />
A graph can be dropped by its name.
This will automatically drop al collections contained in the graph as
long as they are not used within other graphs.
To prohibit the drop of collections, the optional parameter *drop-collections* can be set to *false*.
<br />
* *graph-name*: string - unique identifier of the graph
* *drop-collections*: boolean (optional) - Define if collections should be dropped (default: true)
<br />
@EXAMPLES
<br />
Drop a graph:
<br />
```
arangosh> var graph = require("org/arangodb/general-graph");
arangosh> graph._drop("social");
true
```
<br />
@startDocuBlock JSF_general_graph_drop
!SECTION Edge
!SUBSECTION Save
Creates and saves a new vertex in collection *vertexCollectionName*
<br />
`general-graph.vertexCollectionName.save(data)`
<br />
*data*: json - data of vertex
<br />
@EXAMPLES
<br />
```
arangosh> var graph = require("org/arangodb/general-graph");
arangosh> graph._drop("social");
true
```
<br />
@startDocuBlock JSF_general_graph_vertex_collection_save
!SUBSECTION Replace
Replaces the data of a vertex in collection *vertexCollectionName*
<br />
`general-graph.vertexCollectionName.replace(vertexId, data, options)`
<br />
*vertexId*: string - id of the vertex
*data*: json - data of vertex
*options*: json - (optional) - see collection documentation
<br />
@EXAMPLES
<br />
```
arangosh> var examples = require("org/arangodb/graph-examples/example-graph.js");
arangosh> var g = examples.loadGraph("social");
arangosh> g.male.save({neym: "Jon", _key: "john"});
{
"error" : false,
"_id" : "male/john",
"_rev" : "31374924",
"_key" : "john"
}
arangosh> g.male.replace("male/john", {name: "John"});
{
"error" : false,
"_id" : "male/john",
"_rev" : "31571532",
"_key" : "john"
}
```
<br />
@startDocuBlock JSF_general_graph_vertex_collection_replace
!SUBSECTION Update
Updates the data of a vertex in collection *vertexCollectionName*
<br />
`general-graph.vertexCollectionName.update(vertexId, data, options)`
<br />
*vertexId*: string - id of the vertex
*data*: json - data of vertex
*options*: json - (optional) - see collection documentation
<br />
@EXAMPLES
<br />
```
arangosh> var examples = require("org/arangodb/graph-examples/example-graph.js");
arangosh> var g = examples.loadGraph("social");
arangosh> g.female.save({name: "Lynda", _key: "linda"});
{
"error" : false,
"_id" : "female/linda",
"_rev" : "86027478",
"_key" : "linda"
}
arangosh> g.female.update("female/linda", {name: "Linda", _key: "linda"});
{
"error" : false,
"_id" : "female/linda",
"_rev" : "86224086",
"_key" : "linda"
}
```
<br />
@startDocuBlock JSF_general_graph_vertex_collection_update
!SUBSECTION Remove
Removes a vertex in collection *vertexCollectionName*
<br />
`general-graph.vertexCollectionName.remove(vertexId, options)`
<br />
Additionally removes all ingoing and outgoing edges of the vertex recursively
(see [edge remove](#edge.remove)).
<br />
@EXAMPLES
<br />
```
arangosh> var examples = require("org/arangodb/graph-examples/example-graph.js");
arangosh> var g = examples.loadGraph("social");
arangosh> g.male.save({name: "Kermit", _key: "kermit"});
{
"error" : false,
"_id" : "male/kermit",
"_rev" : "89701964",
"_key" : "kermit"
}
arangosh> db._exists("male/kermit")
true
arangosh> g.male.remove("male/kermit")
true
arangosh> db._exists("male/kermit")
false
```
<br />
@startDocuBlock JSF_general_graph_vertex_collection_remove
!SECTION Edge
!SUBSECTION Save
Creates and saves a new edge from vertex *from* to vertex *to* in
collection *edgeCollectionName*
<br />
`general-graph.edgeCollectionName.save(from, to, data)`
<br />
*from*: string - id of outgoing vertex
*to*: string - of ingoing vertex
*data*: json - data of edge
<br />
@EXAMPLES
<br />
```
arangosh> var examples = require("org/arangodb/graph-examples/example-graph.js");
arangosh> var g = examples.loadGraph("social");
arangosh> g.relation.save("male/bob", "female/alice", {type: "married", _key: "bobAndAlice"});
{
"error" : false,
"_id" : "relation/bobAndAlice",
"_rev" : "45923916",
"_key" : "bobAndAlice"
}
```
<br />
If the collections of *from* and *to* are not defined in an edgeDefinition of the graph,
the edge will not be stored.
<br />
<br />
```
arangosh> var examples = require("org/arangodb/graph-examples/example-graph.js");
arangosh> var g = examples.loadGraph("social");
arangosh> g.relation.save("relation/aliceAndBob", "female/alice", {type: "married", _key: "bobAndAlice"});
Edge is not allowed between relation/aliceAndBob and female/alice.
```
@startDocuBlock JSF_general_graph_edge_collection_save
!SUBSECTION Replace
Replaces the data of an edge in collection *edgeCollectionName*
<br />
`general-graph.edgeCollectionName.replace(edgeId, data, options)`
<br />
*edgeId*: string - id of the edge
*data*: json - data of edge
*options*: json - (optional) - see collection documentation
<br />
@EXAMPLES
<br />
```
arangosh> var examples = require("org/arangodb/graph-examples/example-graph.js");
arangosh> var g = examples.loadGraph("social");
arangosh> g.relation.save("female/alice", "female/diana", {typo: "nose", _key: "aliceAndDiana"});
{
"error" : false,
"_id" : "relation/aliceAndDiana",
"_rev" : "27377228",
"_key" : "aliceAndDiana"
}
arangosh> g.relation.replace("relation/aliceAndDiana", {type: "knows"});
{
"error" : false,
"_id" : "relation/aliceAndDiana",
"_rev" : "27573836",
"_key" : "aliceAndDiana"
}
```
<br />
@startDocuBlock JSF_general_graph_edge_collection_replace
!SUBSECTION Update
Updates the data of an edge in collection *edgeCollectionName*
<br />
`general-graph.edgeCollectionName.update(edgeId, data, options)`
<br />
*edgeId*: string - id of the edge
*data*: json - data of edge
*options*: json - (optional) - see collection documentation
<br />
@EXAMPLES
<br />
```
arangosh> var examples = require("org/arangodb/graph-examples/example-graph.js");
arangosh> var g = examples.loadGraph("social");
arangosh> g.relation.save("female/alice", "female/diana", {type: "knows", _key: "aliceAndDiana"});
{
"error" : false,
"_id" : "relation/aliceAndDiana",
"_rev" : "132365900",
"_key" : "aliceAndDiana"
}
arangosh> g.relation.update("relation/aliceAndDiana", {type: "quarrelled", _key: "aliceAndDiana"});
{
"error" : false,
"_id" : "relation/aliceAndDiana",
"_rev" : "132562508",
"_key" : "aliceAndDiana"
}
```
<br />
@startDocuBlock JSF_general_graph_edge_collection_update
!SUBSECTION Remove
Removes an edge in collection *edgeCollectionName*
<br />
`general-graph.edgeCollectionName.remove(edgeId, options)`
<br />
If this edge is used as a vertex by another edge, the other edge will be removed (recursively).
<br />
@EXAMPLES
<br />
```
arangosh> var examples = require("org/arangodb/graph-examples/example-graph.js");
arangosh> var g = examples.loadGraph("social");
arangosh> g.relation.save("female/alice", "female/diana", {_key: "aliceAndDiana"});
{
"error" : false,
"_id" : "relation/aliceAndDiana",
"_rev" : "146914892",
"_key" : "aliceAndDiana"
}
arangosh> db._exists("relation/aliceAndDiana")
true
arangosh> g.relation.remove("relation/aliceAndDiana")
true
arangosh> db._exists("relation/aliceAndDiana")
false
```
<br />
@startDocuBlock JSF_general_graph_edge_collection_remove

View File

@ -819,6 +819,10 @@ int ArangoServer::startupServer () {
if (startServer) {
++concurrency;
}
#ifdef __APPLE__
system("say -v hysterical 'welcome to ArangoDB'");
#endif
}
else if (mode == OperationMode::MODE_UNITTESTS || mode == OperationMode::MODE_SCRIPT) {
if (concurrency == 1) {

View File

@ -47,21 +47,21 @@ var graph = require("org/arangodb/general-graph");
////////////////////////////////////////////////////////////////////////////////
/// @brief create a "bad parameter" error
////////////////////////////////////////////////////////////////////////////////
function badParam (req, res, message) {
actions.resultBad(req,
res,
arangodb.ERROR_HTTP_BAD_PARAMETER,
actions.resultBad(req,
res,
arangodb.ERROR_HTTP_BAD_PARAMETER,
message);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create a "not found" error
////////////////////////////////////////////////////////////////////////////////
function notFound (req, res, code, message) {
actions.resultNotFound(req,
res,
actions.resultNotFound(req,
res,
code,
message);
}
@ -77,9 +77,9 @@ function notFound (req, res, code, message) {
/// Starts a traversal starting from a given vertex and following.
/// edges contained in a given edgeCollection. The request must
/// contain the following attributes.
///
///
/// - `startVertex`: id of the startVertex, e.g. `"users/foo"`.
///
///
/// - `edgeCollection`: **Deprecated** name of the collection that contains the edges.
///
/// - `graphName`: name of the graph that contains the edges.
@ -95,15 +95,15 @@ function notFound (req, res, code, message) {
/// If there is at least one `"exclude"` or `"prune"` respectivly
/// is contained, it's effect will occur.
///
/// - `minDepth` (optional, ANDed with any existing filters):
/// - `minDepth` (optional, ANDed with any existing filters):
/// visits only nodes in at least the given depth
///
/// - `maxDepth` (optional, ANDed with any existing filters):
/// - `maxDepth` (optional, ANDed with any existing filters):
/// visits only nodes in at most the given depth
///
/// - `visitor` (optional): body (JavaScript) code of custom visitor function
/// function signature: (config, result, vertex, path) -> void
/// visitor function can do anything, but its return value is ignored. To
/// visitor function can do anything, but its return value is ignored. To
/// populate a result, use the `result` variable by reference
///
/// - `direction` (optional): direction for traversal
@ -120,7 +120,7 @@ function notFound (req, res, code, message) {
/// expander must return an array of the connections for `vertex`
/// each connection is an object with the attributes `edge` and `vertex`
/// - `sort` (optional): body (JavaScript) code of a custom comparison function
/// for the edges. The signature of this function is
/// for the edges. The signature of this function is
/// (l, r) -> integer (where l and r are edges) and must
/// return -1 if l is smaller than, +1 if l is greater than,
/// and 0 if l and r are equal. The reason for this is the
@ -157,8 +157,8 @@ function notFound (req, res, code, message) {
///
/// If the Traversal is successfully executed `HTTP 200` will be returned.
/// Additionally the `result` object will be returned by the traversal.
///
/// For successful traversals, the returned JSON object has the
///
/// For successful traversals, the returned JSON object has the
/// following properties:
///
/// - `error`: boolean flag to indicate if an error occurred (`false`
@ -193,7 +193,7 @@ function notFound (req, res, code, message) {
/// will respond with `HTTP 400`.
///
/// @RESTRETURNCODE{404}
/// The server will responded with `HTTP 404` if the specified edge collection
/// The server will responded with `HTTP 404` if the specified edge collection
/// does not exist, or the specified start vertex cannot be found.
///
/// @RESTRETURNCODE{500}
@ -256,7 +256,7 @@ function notFound (req, res, code, message) {
/// var g = examples.loadGraph("knows_graph");
/// var a = g.persons.document("alice")._id;
/// var url = "/_api/traversal";
/// var body = {
/// var body = {
/// startVertex: a,
/// graphName: g.__name,
/// direction: "any",
@ -382,12 +382,8 @@ function notFound (req, res, code, message) {
/// var examples = require("org/arangodb/graph-examples/example-graph.js");
/// var g = examples.loadGraph("knows_graph");
/// var a = g.persons.document("alice")._id;
/// var cv = "persons";
/// var ce = "knows";
/// var users = db._collection(cv);
/// var knows = db._collection(ce);
/// var url = "/_api/traversal";
/// var body = {
/// var body = {
/// startVertex: a,
/// graphName: g.__name,
/// expander: "var connections = [ ];" +
@ -397,15 +393,15 @@ function notFound (req, res, code, message) {
/// "vertex: require(\"internal\").db._document(e._from), " +
/// "edge: e" +
/// "});" +
/// "});" +
/// "});" +
/// "}" +
/// "if (vertex.name === \"Eve\") {" +
/// "config.datasource.getOutEdges(vertex).forEach(function (e) {" +
/// "connections.push({" +
/// "vertex: require(\"internal\").db._document(e._to), " +
/// "edge: e" +
/// "});" +
/// "});" +
/// "});" +
/// "});" +
/// "}" +
/// "return connections;"
/// };
@ -424,8 +420,8 @@ function notFound (req, res, code, message) {
/// var g = examples.loadGraph("knows_graph");
/// var a = g.persons.document("alice")._id;
/// var url = "/_api/traversal";
/// var body = {
/// startVertex: a,
/// var body = {
/// startVertex: a,
/// graphName: g.__name,
/// direction: "any",
/// strategy: "depthfirst"
@ -445,7 +441,7 @@ function notFound (req, res, code, message) {
/// var g = examples.loadGraph("knows_graph");
/// var a = g.persons.document("alice")._id;
/// var url = "/_api/traversal";
/// var body = {
/// var body = {
/// startVertex: a,
/// graphName: g.__name,
/// direction: "any",
@ -466,7 +462,7 @@ function notFound (req, res, code, message) {
/// var g = examples.loadGraph("knows_graph");
/// var a = g.persons.document("alice")._id;
/// var url = "/_api/traversal";
/// var body = {
/// var body = {
/// startVertex: a,
/// graphName: g.__name,
/// direction: "any",
@ -488,12 +484,12 @@ function notFound (req, res, code, message) {
/// var g = examples.loadGraph("knows_graph");
/// var a = g.persons.document("alice")._id;
/// var url = "/_api/traversal";
/// var body = {
/// var body = {
/// startVertex: a,
/// graphName: g.__name,
/// direction: "any",
/// uniqueness: {
/// vertices: "none",
/// vertices: "none",
/// edges: "global"
/// }
/// };
@ -551,7 +547,7 @@ function post_api_traversal(req, res) {
// check start vertex
// -----------------------------------------
if (json.startVertex === undefined ||
if (json.startVertex === undefined ||
typeof json.startVertex !== "string") {
return badParam(req, res, "missing or invalid startVertex");
}
@ -570,7 +566,7 @@ function post_api_traversal(req, res) {
if (json.graphName === undefined) {
// check edge collection
// -----------------------------------------
if (json.edgeCollection === undefined) {
return badParam(req, res, "missing graphname");
}
@ -585,7 +581,7 @@ function post_api_traversal(req, res) {
catch (ignore) {
}
if (edgeCollection === undefined ||
if (edgeCollection === undefined ||
edgeCollection === null) {
return notFound(req, res, arangodb.ERROR_ARANGO_COLLECTION_NOT_FOUND,
"invalid edgeCollection");
@ -593,17 +589,16 @@ function post_api_traversal(req, res) {
} else if (typeof json.graphName !== "string") {
return badParam(req, res, "invalid graphname");
} else {
if (!graph._exists(json.graphName)) {
return badParam(req, res, "invalid graphname");
}
datasource = traversal.generalGraphDatasourceFactory(json.graphName);
}
if (!graph._exists(json.graphName)) {
return badParam(req, res, "invalid graphname");
}
datasource = traversal.generalGraphDatasourceFactory(json.graphName);
// set up filters
// -----------------------------------------
var filters = [ ];
if (json.minDepth !== undefined) {
filters.push(traversal.minDepthFilter);
@ -624,7 +619,7 @@ function post_api_traversal(req, res) {
if (filters.length === 0) {
filters.push(traversal.visitAllFilter);
}
// set up visitor
// -----------------------------------------
@ -676,14 +671,14 @@ function post_api_traversal(req, res) {
return badParam(req, res, "invalid sort function");
}
}
// assemble config object
// -----------------------------------------
var config = {
params: json,
datasource: datasource,
strategy: json.strategy,
strategy: json.strategy,
order: json.order,
itemOrder: json.itemOrder,
expander: expander,
@ -699,11 +694,11 @@ function post_api_traversal(req, res) {
if (edgeCollection !== undefined) {
config.edgeCollection = edgeCollection;
}
// assemble result object
// -----------------------------------------
var result = {
var result = {
visited: {
vertices: [ ],
paths: [ ]
@ -714,12 +709,12 @@ function post_api_traversal(req, res) {
try {
var init = new Function('result', json.init);
init(result);
}
}
catch (err7) {
return badParam(req, res, "invalid init function");
}
}
// run the traversal
// -----------------------------------------
@ -747,7 +742,7 @@ function post_api_traversal(req, res) {
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief gateway
/// @brief gateway
////////////////////////////////////////////////////////////////////////////////
actions.defineHttp({
@ -757,8 +752,8 @@ actions.defineHttp({
callback : function (req, res) {
try {
switch (req.requestType) {
case actions.POST:
post_api_traversal(req, res);
case actions.POST:
post_api_traversal(req, res);
break;
default:

View File

@ -126,9 +126,10 @@ exports.checkAndMarkNonce = function (value) {
////////////////////////////////////////////////////////////////////////////////
exports.constantEquals = function (a, b) {
var length = a.length > b.length ? a.length : b.length;
var result = true;
for (var i = 0; i < length; i++) {
var length, result, i;
length = a.length > b.length ? a.length : b.length;
result = true;
for (i = 0; i < length; i++) {
if (a.charCodeAt(i) !== b.charCodeAt(i)) {
result = false;
}

View File

@ -1487,11 +1487,15 @@ var _edgeDefinitions = function () {
var _extendEdgeDefinitions = function (edgeDefinition) {
var args = arguments, i = 0;
Object.keys(args).forEach(function (x) {
i++;
if (i === 1) {return;}
edgeDefinition.push(args[x]);
});
Object.keys(args).forEach(
function (x) {
i++;
if (i === 1) {
return;
}
edgeDefinition.push(args[x]);
}
);
};
////////////////////////////////////////////////////////////////////////////////
@ -1634,6 +1638,211 @@ var createHiddenProperty = function(obj, name, value) {
});
obj[name] = value;
};
////////////////////////////////////////////////////////////////////////////////
/// @brief helper for updating binded collections
////////////////////////////////////////////////////////////////////////////////
var removeEdge = function (edgeId, options, self) {
options = options || {};
var edgeCollection = edgeId.split("/")[0];
var graphs = getGraphCollection().toArray();
self.__idsToRemove.push(edgeId);
self.__collectionsToLock.push(edgeCollection);
graphs.forEach(
function(graph) {
var edgeDefinitions = graph.edgeDefinitions;
if (graph.edgeDefinitions) {
edgeDefinitions.forEach(
function(edgeDefinition) {
var from = edgeDefinition.from;
var to = edgeDefinition.to;
var collection = edgeDefinition.collection;
// if collection of edge to be deleted is in from or to
if (from.indexOf(edgeCollection) !== -1 || to.indexOf(edgeCollection) !== -1) {
//search all edges of the graph
var edges = db[collection].toArray();
edges.forEach(
function (edge) {
// if from is
if(self.__idsToRemove.indexOf(edge._id) === -1) {
if (edge._from === edgeId || edge._to === edgeId) {
removeEdge(edge._id, options, self);
}
}
}
);
}
}
);
}
}
);
return;
};
var bindEdgeCollections = function(self, edgeCollections) {
_.each(edgeCollections, function(key) {
var obj = db._collection(key);
var wrap = wrapCollection(obj);
// save
var old_save = wrap.save;
wrap.save = function(from, to, data) {
//check, if edge is allowed
self.__edgeDefinitions.forEach(
function(edgeDefinition) {
if (edgeDefinition.collection === key) {
var fromCollection = from.split("/")[0];
var toCollection = to.split("/")[0];
if (! _.contains(edgeDefinition.from, fromCollection)
|| ! _.contains(edgeDefinition.to, toCollection)) {
throw "Edge is not allowed between " + from + " and " + to + ".";
}
}
}
);
return old_save(from, to, data);
};
// remove
wrap.remove = function(edgeId, options) {
var result;
//if _key make _id (only on 1st call)
if (edgeId.indexOf("/") === -1) {
edgeId = key + "/" + edgeId;
}
removeEdge(edgeId, options, self);
try {
db._executeTransaction({
collections: {
write: self.__collectionsToLock
},
action: function (params) {
var db = require("internal").db;
params.ids.forEach(
function(edgeId) {
if (params.options) {
db._remove(edgeId, params.options);
} else {
db._remove(edgeId);
}
}
);
},
params: {
ids: self.__idsToRemove,
options: options
}
});
result = true;
} catch (e) {
result = false;
}
self.__idsToRemove = [];
self.__collectionsToLock = [];
return result;
};
self[key] = wrap;
});
};
var bindVertexCollections = function(self, vertexCollections) {
_.each(vertexCollections, function(key) {
var obj = db._collection(key);
var result;
var wrap = wrapCollection(obj);
var old_remove = wrap.remove;
wrap.remove = function(vertexId, options) {
//delete all edges using the vertex in all graphs
var graphs = getGraphCollection().toArray();
var vertexCollectionName = vertexId.split("/")[0];
self.__collectionsToLock.push(vertexCollectionName);
graphs.forEach(
function(graph) {
var edgeDefinitions = graph.edgeDefinitions;
if (graph.edgeDefinitions) {
edgeDefinitions.forEach(
function(edgeDefinition) {
var from = edgeDefinition.from;
var to = edgeDefinition.to;
var collection = edgeDefinition.collection;
if (from.indexOf(vertexCollectionName) !== -1
|| to.indexOf(vertexCollectionName) !== -1
) {
var edges = db._collection(collection).toArray();
edges.forEach(
function(edge) {
if (edge._from === vertexId || edge._to === vertexId) {
removeEdge(edge._id, options, self);
}
}
);
}
}
);
}
}
);
try {
db._executeTransaction({
collections: {
write: self.__collectionsToLock
},
action: function (params) {
var db = require("internal").db;
params.ids.forEach(
function(edgeId) {
if (params.options) {
db._remove(edgeId, params.options);
} else {
db._remove(edgeId);
}
}
);
if (params.options) {
db._remove(params.vertexId, params.options);
} else {
db._remove(params.vertexId);
}
},
params: {
ids: self.__idsToRemove,
options: options,
vertexId: vertexId
}
});
result = true;
} catch (e) {
result = false;
}
self.__idsToRemove = [];
self.__collectionsToLock = [];
return result;
};
self[key] = wrap;
});
};
var updateBindCollections = function(graph) {
//remove all binded collections
Object.keys(graph).forEach(
function(key) {
if(key.substring(0,1) !== "_") {
delete graph[key];
}
}
);
graph.__edgeDefinitions.forEach(
function(edgeDef) {
bindEdgeCollections(graph, [edgeDef.collection]);
bindVertexCollections(graph, edgeDef.from);
bindVertexCollections(graph, edgeDef.to);
}
);
bindVertexCollections(graph, graph.__orphanCollections);
};
////////////////////////////////////////////////////////////////////////////////
/// @brief constructor.
@ -1834,187 +2043,8 @@ var Graph = function(graphName, edgeDefinitions, vertexCollections, edgeCollecti
createHiddenProperty(this, "__idsToRemove", []);
createHiddenProperty(this, "__collectionsToLock", []);
createHiddenProperty(this, "__orphanCollections", orphanCollections);
updateBindCollections(self);
// fills this.__idsToRemove and this.__collectionsToLock
var removeEdge = function (edgeId, options) {
options = options || {};
var edgeCollection = edgeId.split("/")[0];
var graphs = getGraphCollection().toArray();
self.__idsToRemove.push(edgeId);
self.__collectionsToLock.push(edgeCollection);
graphs.forEach(
function(graph) {
var edgeDefinitions = graph.edgeDefinitions;
if (graph.edgeDefinitions) {
edgeDefinitions.forEach(
function(edgeDefinition) {
var from = edgeDefinition.from;
var to = edgeDefinition.to;
var collection = edgeDefinition.collection;
// if collection of edge to be deleted is in from or to
if (from.indexOf(edgeCollection) !== -1 || to.indexOf(edgeCollection) !== -1) {
//search all edges of the graph
var edges = db[collection].toArray();
edges.forEach(
function (edge) {
// if from is
if(self.__idsToRemove.indexOf(edge._id) === -1) {
if (edge._from === edgeId || edge._to === edgeId) {
removeEdge(edge._id, options);
}
}
}
);
}
}
);
}
}
);
return;
};
_.each(vertexCollections, function(obj, key) {
var result;
var wrap = wrapCollection(obj);
var old_remove = wrap.remove;
wrap.remove = function(vertexId, options) {
//delete all edges using the vertex in all graphs
var graphs = getGraphCollection().toArray();
var vertexCollectionName = vertexId.split("/")[0];
self.__collectionsToLock.push(vertexCollectionName);
graphs.forEach(
function(graph) {
var edgeDefinitions = graph.edgeDefinitions;
if (graph.edgeDefinitions) {
edgeDefinitions.forEach(
function(edgeDefinition) {
var from = edgeDefinition.from;
var to = edgeDefinition.to;
var collection = edgeDefinition.collection;
if (from.indexOf(vertexCollectionName) !== -1
|| to.indexOf(vertexCollectionName) !== -1
) {
var edges = db._collection(collection).toArray();
edges.forEach(
function(edge) {
if (edge._from === vertexId || edge._to === vertexId) {
removeEdge(edge._id, options);
}
}
);
}
}
);
}
}
);
try {
db._executeTransaction({
collections: {
write: self.__collectionsToLock
},
action: function (params) {
var db = require("internal").db;
params.ids.forEach(
function(edgeId) {
if (params.options) {
db._remove(edgeId, params.options);
} else {
db._remove(edgeId);
}
}
);
if (params.options) {
db._remove(params.vertexId, params.options);
} else {
db._remove(params.vertexId);
}
},
params: {
ids: self.__idsToRemove,
options: options,
vertexId: vertexId
}
});
result = true;
} catch (e) {
result = false;
}
self.__idsToRemove = [];
self.__collectionsToLock = [];
return result;
};
self[key] = wrap;
});
_.each(edgeCollections, function(obj, key) {
var wrap = wrapCollection(obj);
// save
var old_save = wrap.save;
wrap.save = function(from, to, data) {
//check, if edge is allowed
edgeDefinitions.forEach(
function(edgeDefinition) {
if (edgeDefinition.collection === key) {
var fromCollection = from.split("/")[0];
var toCollection = to.split("/")[0];
if (! _.contains(edgeDefinition.from, fromCollection)
|| ! _.contains(edgeDefinition.to, toCollection)) {
throw "Edge is not allowed between " + from + " and " + to + ".";
}
}
}
);
return old_save(from, to, data);
};
// remove
wrap.remove = function(edgeId, options) {
var result;
//if _key make _id (only on 1st call)
if (edgeId.indexOf("/") === -1) {
edgeId = key + "/" + edgeId;
}
removeEdge(edgeId, options);
try {
db._executeTransaction({
collections: {
write: self.__collectionsToLock
},
action: function (params) {
var db = require("internal").db;
params.ids.forEach(
function(edgeId) {
if (params.options) {
db._remove(edgeId, params.options);
} else {
db._remove(edgeId);
}
}
);
},
params: {
ids: self.__idsToRemove,
options: options
}
});
result = true;
} catch (e) {
result = false;
}
self.__idsToRemove = [];
self.__collectionsToLock = [];
return result;
};
self[key] = wrap;
});
};
@ -2206,6 +2236,7 @@ var _drop = function(graphId, dropCollections) {
return true;
};
////////////////////////////////////////////////////////////////////////////////
/// @brief return all edge collections of the graph.
////////////////////////////////////////////////////////////////////////////////
@ -2907,9 +2938,11 @@ Graph.prototype._extendEdgeDefinitions = function(edgeDefinition) {
findOrCreateCollectionsByEdgeDefinitions([edgeDefinition]);
this.__edgeDefinitions.push(edgeDefinition);
db._graphs.update(this.__name, {edgeDefinitions: this.__edgeDefinitions});
this.__edgeCollections[edgeDefinition.collection] = db[edgeDefinition.collection];
edgeDefinition.from.forEach(
function(vc) {
self[vc] = db[vc];
//remove from __orphanCollections
var orphanIndex = self.__orphanCollections.indexOf(vc);
if (orphanIndex !== -1) {
@ -2923,6 +2956,7 @@ Graph.prototype._extendEdgeDefinitions = function(edgeDefinition) {
);
edgeDefinition.to.forEach(
function(vc) {
self[vc] = db[vc];
//remove from __orphanCollections
var orphanIndex = self.__orphanCollections.indexOf(vc);
if (orphanIndex !== -1) {
@ -2934,6 +2968,7 @@ Graph.prototype._extendEdgeDefinitions = function(edgeDefinition) {
}
}
);
updateBindCollections(this);
};
@ -3066,6 +3101,7 @@ Graph.prototype._editEdgeDefinitions = function(edgeDefinition) {
changeEdgeDefinitionsForGraph(graph, edgeDefinition, newCollections, possibleOrphans, self);
}
);
updateBindCollections(this);
};
@ -3133,6 +3169,8 @@ Graph.prototype._deleteEdgeDefinition = function(edgeCollection) {
}
}
);
updateBindCollections(this);
};
////////////////////////////////////////////////////////////////////////////////
@ -3187,6 +3225,8 @@ Graph.prototype._addVertexCollection = function(vertexCollectionName, createColl
}
this.__orphanCollections.push(vertexCollectionName);
this[vertexCollectionName] = db[vertexCollectionName];
updateBindCollections(this);
db._graphs.update(this.__name, {orphanCollections: this.__orphanCollections});
};
@ -3263,6 +3303,7 @@ Graph.prototype._removeVertexCollection = function(vertexCollectionName, dropCol
throw err;
}
this.__orphanCollections.splice(index, 1);
delete this[vertexCollectionName];
db._graphs.update(this.__name, {orphanCollections: this.__orphanCollections});
if (dropCollection === true) {
@ -3271,6 +3312,7 @@ Graph.prototype._removeVertexCollection = function(vertexCollectionName, dropCol
db._drop(vertexCollectionName);
}
}
updateBindCollections(this);
};

View File

@ -135,7 +135,8 @@ extend(Controller.prototype, {
return this.applicationContext.collection(name);
},
addInjector: function(name, factory) {
addInjector: function (name, factory) {
'use strict';
if (factory === undefined) {
_.extend(this.injectors, name);
} else {

View File

@ -89,9 +89,11 @@ constructRoute = function (method, route, callback, controller) {
return {
url: constructUrlObject(route, undefined, method),
action: {
callback: function(req, res) {
Object.keys(controller.injectors).forEach(function(key) {
if (Object.prototype.hasOwnProperty.call(controller.injected, key)) return;
callback: function (req, res) {
Object.keys(controller.injectors).forEach(function (key) {
if (Object.prototype.hasOwnProperty.call(controller.injected, key)) {
return;
}
var injector = controller.injectors[key];
if (typeof injector === 'function') {
controller.injected[key] = injector();

View File

@ -1,4 +1,4 @@
/*jslint indent: 2, nomen: true, maxlen: 120, todo: true, white: false, sloppy: false */
/*jslint indent: 2, nomen: true, maxlen: 120, white: false, sloppy: false */
/*global module, require, exports */
////////////////////////////////////////////////////////////////////////////////