1
0
Fork 0

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

This commit is contained in:
Michael Hackstein 2014-06-16 16:29:38 +02:00
commit f0d65ce57b
14 changed files with 1115 additions and 558 deletions

View File

@ -26,12 +26,8 @@ There are different types of edge defintions:
!SUBSECTION Edge Definitions
The edge definitions for a graph is an Array containing arbitrary many directed and/or undirected relations as defined below.
The edge definitons array is initialised with the following call:
<!-- @startDocuBlock @startDocuBlock JSF_general_graph_edgeDefinitions -->
```js
> var edgeDefinitions = graph._edgeDefinitions(edgeDefinition1,......edgeDefinitionN);
```
To add further edge definitions to the array one must call:
@ -42,11 +38,87 @@ To add further edge definitions to the array one must call:
!SUBSUBSECTION Undirected Relation
<!-- @startDocuBlock JSF_general_graph_undirectedRelationDefinition -->
<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"
]
}
```
!SUBSUBSECTION Directed Relation
<!-- @startDocuBlock JSF_general_graph_undirectedRelationDefinition -->
<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"
]
}
```
!SUBSUBSECTION Complete Example to create a graph
@ -81,20 +153,74 @@ alternative call:
!SUBSECTION Orphan Collections
Each graph has an orphan collection. It consists of arbitrary many vertex collection (type *document*), that are not
used in an edge definition of the graph. If the graph is extended with an edge definition, which is part of the orphan
collection, it will be removed from the orphan collection automatically.
used in an edge definition of the graph. If the graph is extended with an edge definition using one of the orphans,
it will be removed from the orphan collection automatically.
!SUBSUBSECTION Add
<!-- @startDocuBlock JSF_general_graph__addOrphanCollection -->
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, ed2]);
ReferenceError: ed2 is not defined
```
<br />
!SUBSUBSECTION Read
<!-- @startDocuBlock JSF_general_graph__getOrphanCollections -->
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]);
[ArangoError 1925: graph already exists]
```
<br />
!SUBSUBSECTION Remove
<!-- @startDocuBlock JSF_general_graph__removeOrphanCollection -->
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]);
[ArangoError 1925: graph already exists]
```
<br />
!SUBSECTION Read a graph
@ -126,47 +252,324 @@ dropCollections: bool - optional. *true* all collections of the graph will be de
!SUBSECTION Save
<!-- @startDocuBlock JSF_general_graph_vertex_collection_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 examples = require("org/arangodb/graph-examples/example-graph.js");
arangosh> var g = examples.loadGraph("social");
arangosh> g.male.save({name: "Floyd", _key: "floyd"});
{
"error" : false,
"_id" : "male/floyd",
"_rev" : "91260521",
"_key" : "floyd"
}
```
<br />
!SUBSECTION Replace
<!-- @startDocuBlock JSF_general_graph_vertex_collection_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" : "31360617",
"_key" : "john"
}
arangosh> g.male.replace("male/john", {name: "John"});
{
"error" : false,
"_id" : "male/john",
"_rev" : "31557225",
"_key" : "john"
}
```
<br />
!SUBSECTION Update
<!-- @startDocuBlock JSF_general_graph_vertex_collection_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" : "79201897",
"_key" : "linda"
}
arangosh> g.female.update({name: "Linda", _key: "linda"});
TypeError: Object #<Object> has no method 'split'
```
<br />
!SUBSECTION Remove
<!-- @startDocuBlock JSF_general_graph_vertex_collection_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" : "83068521",
"_key" : "kermit"
}
arangosh> db._exists("male/kermit")
true
arangosh> g.male.remove("male/kermit")
true
arangosh> db._exists("male/kermit")
false
```
<br />
!SECTION Edge
!SUBSECTION Save
<!-- @startDocuBlock JSF_general_graph_edge_collection_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" : "45909609",
"_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.
```
!SUBSECTION Replace
<!-- @startDocuBlock JSF_general_graph_edge_collection_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" : "27362921",
"_key" : "aliceAndDiana"
}
arangosh> g.relation.replace("relation/aliceAndDiana", {type: "knows"});
{
"error" : false,
"_id" : "relation/aliceAndDiana",
"_rev" : "27559529",
"_key" : "aliceAndDiana"
}
```
<br />
!SUBSECTION Update
<!-- @startDocuBlock JSF_general_graph_edge_collection_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" : "127108713",
"_key" : "aliceAndDiana"
}
arangosh> g.relation.update("relation/aliceAndDiana", {type: "quarrelled", _key: "aliceAndDiana"});
{
"error" : false,
"_id" : "relation/aliceAndDiana",
"_rev" : "127305321",
"_key" : "aliceAndDiana"
}
```
<br />
!SUBSECTION Remove
<!-- @startDocuBlock JSF_general_graph_edge_collection_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" : "141657705",
"_key" : "aliceAndDiana"
}
arangosh> db._exists("relation/aliceAndDiana")
true
arangosh> g.relation.remove("relation/aliceAndDiana")
true
arangosh> db._exists("relation/aliceAndDiana")
false
```
<br />
!SECTION Vertices
!SUBSECTION Get vertex *from* of an edge
<!-- @startDocuBlock JSF_general_graph_getFromVertex -->
Get the vertex of an edge defined as *_from*
<br />
`general-graph._getFromVertex(edgeId)`
<br />
Returns the vertex defined with the attribute *_from* of the edge with *edgeId* as its *_id*.
<br />
@EXAMPLES
<br />
```
arangosh> var examples = require("org/arangodb/graph-examples/example-graph.js");
arangosh> var g = examples.loadGraph("social");
arangosh> g._getFromVertex("relation/aliceAndBob")
{
"name" : "Alice",
"_id" : "female/alice",
"_rev" : "175670889",
"_key" : "alice"
}
```
<br />
!SUBSECTION Get vertex *to* of an edge
<!-- @startDocuBlock JSF_general_graph_getToVertex -->
Get the vertex of an edge defined as *_to*
<br />
`general-graph._getToVertex(edgeId)`
<br />
Returns the vertex defined with the attribute *_to* of the edge with *edgeId* as its *_id*.
<br />
@EXAMPLES
<br />
```
arangosh> var examples = require("org/arangodb/graph-examples/example-graph.js");
arangosh> var g = examples.loadGraph("social");
arangosh> g._getToVertex("relation/aliceAndBob")
{
"name" : "Bob",
"_id" : "male/bob",
"_rev" : "40666729",
"_key" : "bob"
}
```
<br />

View File

@ -307,6 +307,7 @@ void ArangoClient::parse (ProgramOptions& options,
int argc,
char* argv[],
string const& initFilename) {
// if options are invalid, exit directly
if (! options.parse(description, argc, argv)) {
LOG_FATAL_AND_EXIT("%s", options.lastError().c_str());

View File

@ -216,6 +216,8 @@
"ERROR_GRAPH_VERTEX_COL_DOES_NOT_EXIST" : { "code" : 1926, "message" : "collection does not exist" },
"ERROR_GRAPH_WRONG_COLLECTION_TYPE_VERTEX" : { "code" : 1927, "message" : "not a vertex collection" },
"ERROR_GRAPH_NOT_IN_ORPHAN_COLLECTION" : { "code" : 1928, "message" : "not in orphan collection" },
"ERROR_GRAPH_COLLECTION_USED_IN_EDGE_DEF" : { "code" : 1929, "message" : "collection used in edge def" },
"ERROR_GRAPH_EDGE_COLLECTION_NOT_USED" : { "code" : 1930, "message" : "edge collection not used in graph" },
"ERROR_SESSION_UNKNOWN" : { "code" : 1950, "message" : "unknown session" },
"ERROR_SESSION_EXPIRED" : { "code" : 1951, "message" : "session expired" },
"SIMPLE_CLIENT_UNKNOWN_ERROR" : { "code" : 2000, "message" : "unknown client error" },

View File

@ -2033,7 +2033,8 @@ var checkIfMayBeDropped = function(colName, graphName, graphs) {
var _drop = function(graphId, dropCollections) {
var gdb = getGraphCollection();
var gdb = getGraphCollection(),
graphs;
if (!gdb.exists(graphId)) {
var err = new ArangoError();
@ -2050,7 +2051,7 @@ var _drop = function(graphId, dropCollections) {
var from = edgeDefinition.from;
var to = edgeDefinition.to;
var collection = edgeDefinition.collection;
var graphs = getGraphCollection().toArray();
graphs = getGraphCollection().toArray();
if (checkIfMayBeDropped(collection, graph._key, graphs)) {
db._drop(collection);
}
@ -2070,6 +2071,20 @@ var _drop = function(graphId, dropCollections) {
);
}
);
//drop orphans
graphs = getGraphCollection().toArray();
if (!graph.orphanCollections) {
graph.orphanCollections = [];
}
graph.orphanCollections.forEach(
function(oC) {
if (checkIfMayBeDropped(oC, graph._key, graphs)) {
try {
db._drop(oC);
} catch (e) {}
}
}
);
}
gdb.remove(graphId);
@ -2482,9 +2497,10 @@ Graph.prototype._amountCommonProperties = function(vertex1Example, vertex2Exampl
////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_general_graph__extendEdgeDefinitions
/// Extends the edge definitions of a graph. If the edge collection of the edge definition
/// to add is already used in the graph or used in a different graph with different from
/// an to collections an error is thrown.
/// Extends the edge definitions of a graph. If an orphan collection is used in this
/// edge definitino, it will be removed from the orphenage. If the edge collection of
/// the edge definition to add is already used in the graph or used in a different
/// graph with different from an to collections an error is thrown.
///
/// `general-graph._extendEdgeDefinitions(edgeDefinition)`
///
@ -2570,19 +2586,78 @@ Graph.prototype._extendEdgeDefinitions = function(edgeDefinition) {
};
////////////////////////////////////////////////////////////////////////////////
/// @brief internal function for editing edge definitions
////////////////////////////////////////////////////////////////////////////////
var changeEdgeDefinitionsForGraph = function(graph, edgeDefinition, newCollections, possibleOrphans, self) {
var oldCollections = [];
var graphCollections = [];
var graphObj = _graph(graph._key);
var eDs = graph.edgeDefinitions;
//replace edgeDefintion
eDs.forEach(
function(eD, id) {
if(eD.collection === edgeDefinition.collection) {
oldCollections = _.union(oldCollections, eD.from);
oldCollections = _.union(oldCollections, eD.to);
eDs[id].from = edgeDefinition.from;
eDs[id].to = edgeDefinition.to;
db._graphs.update(graph._key, {edgeDefinitions: eDs});
if (graph._key === self.__name) {
self.__edgeDefinitions[id].from = edgeDefinition.from;
self.__edgeDefinitions[id].to = edgeDefinition.to;
}
} else {
//collect all used collections
graphCollections = _.union(graphCollections, eD.from);
graphCollections = _.union(graphCollections, eD.to);
}
}
);
//remove used collection from orphanage
newCollections.forEach(
function(nc) {
if (graph._key === self.__name) {
if (self.__vertexCollections[nc] === undefined) {
self.__vertexCollections[nc] = db[nc];
}
try {
graphObj._removeOrphanCollection(nc);
} catch (e) {
}
}
}
);
//move unused collections to orphanage
possibleOrphans.forEach(
function(po) {
if (graphCollections.indexOf(po) === -1) {
delete graphObj.__vertexCollections[po];
graphObj._addOrphanCollection(po);
}
}
);
};
////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_general_graph__editEdgeDefinition
/// Edits the edge definitions of a graph. The edge definition used as argument will
/// replace the existing edge definition the corresponding edge definition in graphs
/// edge definitions. Other graphs with the same edge definition will be modified, too.
/// replace the existing edge definition of the graph which has the same collection.
/// Vertex Collections of the replaced edge definition, that are not used in the new
/// definition will transform to an orphan. Orphans that are used in this new edge
/// definition will be deleted from the list of orphans. Other graphs with the same edge
/// definition will be modified, too.
///
/// `general-graph._editEdgeDefinition(edgeDefinition, dropCollections)`
/// `general-graph._editEdgeDefinition(edgeDefinition)`
///
/// *edgeDefinition* - [string] : the edge definition to replace the existing edge
/// definition with the same attribut *collection*.
/// *dropCollections* - bool : True, all collections that are not used anymore in any
/// graph will be removed. Default: true.
/// definition with the same attribute *collection*.
///
/// @EXAMPLES
///
@ -2597,13 +2672,9 @@ Graph.prototype._extendEdgeDefinitions = function(edgeDefinition) {
/// @endDocuBlock
///
////////////////////////////////////////////////////////////////////////////////
Graph.prototype._editEdgeDefinitions = function(edgeDefinition, dropCollections) {
var self = this;
var dropCandidates;
var currentEdgeDefinition = {};
var exOrphanCandidates = [];
var effectedGraphs = [];
Graph.prototype._editEdgeDefinitions = function(edgeDefinition) {
var self = this;
//check, if in graphs edge definition
if (this.__edgeCollections[edgeDefinition.collection] === undefined) {
@ -2613,108 +2684,33 @@ Graph.prototype._editEdgeDefinitions = function(edgeDefinition, dropCollections)
throw err;
}
findOrCreateCollectionsByEdgeDefinitions([edgeDefinition]);
//evaluate collections to add to orphanage
var possibleOrphans = [];
var currentEdgeDefinition;
this.__edgeDefinitions.forEach(
function(ed) {
if (edgeDefinition.collection === ed.collection) {
currentEdgeDefinition = ed;
}
}
);
var currentCollections = _.union(currentEdgeDefinition.from, currentEdgeDefinition.to);
var newCollections = _.union(edgeDefinition.from, edgeDefinition.to);
currentCollections.forEach(
function(colName) {
if (newCollections.indexOf(colName) === -1) {
possibleOrphans.push(colName);
}
}
);
//change definition for ALL graphs
var graphs = getGraphCollection().toArray();
graphs.forEach(
function(graph) {
var eDs = graph.edgeDefinitions;
eDs.forEach(
function(eD, id) {
if(eD.collection === edgeDefinition.collection) {
currentEdgeDefinition.from = eD.from;
currentEdgeDefinition.to = eD.to;
eDs[id].from = edgeDefinition.from;
eDs[id].to = edgeDefinition.to;
db._graphs.update(graph._key, {edgeDefinitions: eDs});
effectedGraphs.push(graph._key);
if (graph._key === self.__name) {
self.__edgeDefinitions[id].from = edgeDefinition.from;
self.__edgeDefinitions[id].to = edgeDefinition.to;
}
}
}
);
}
);
findOrCreateCollectionsByEdgeDefinitions([edgeDefinition]);
if (dropCollections !== false) {
graphs = getGraphCollection().toArray();
//eval collection to be dropped
dropCandidates = currentEdgeDefinition.from;
currentEdgeDefinition.to.forEach(
function (col) {
if (dropCandidates.indexOf(col) === -1) {
dropCandidates.push(col);
}
}
);
dropCandidates.forEach(
function(dc) {
if (checkIfMayBeDropped(dc, null, graphs)) {
db._drop(dc);
}
}
);
}
//push "new" collections into vertexCollections
edgeDefinition.from.forEach(
function(vc) {
if (self.__vertexCollections[vc] === undefined) {
exOrphanCandidates.push(vc);
self.__vertexCollections[vc] = db[vc];
}
}
);
edgeDefinition.to.forEach(
function(vc) {
if (self.__vertexCollections[vc] === undefined) {
exOrphanCandidates.push(vc);
self.__vertexCollections[vc] = db[vc];
}
}
);
//remove "old" collections from vertexCollections
dropCandidates.forEach(
function(dropCanditate) {
var drop = true;
self.__edgeDefinitions.forEach(
function(eD) {
eD.from.forEach(
function(vC) {
if (vC === dropCanditate) {
drop = false;
}
}
);
}
);
if (drop) {
delete self.__vertexCollections[dropCanditate];
}
}
);
//orphans treatment
effectedGraphs.forEach(
function(gN) {
var g;
if (gN === self.__name) {
g = self;
} else {
g = _graph(gN);
}
var orphans = g._getOrphanCollections();
exOrphanCandidates.forEach(
function(eOC) {
if (orphans.indexOf(eOC) !== -1) {
g._removeOrphanCollection(eOC);
}
}
);
changeEdgeDefinitionsForGraph(graph, edgeDefinition, newCollections, possibleOrphans, self);
}
);
@ -2725,14 +2721,12 @@ Graph.prototype._editEdgeDefinitions = function(edgeDefinition, dropCollections)
/// @startDocuBlock JSF_general_graph__deleteEdgeDefinition
/// Deletes an edge definition defined by the edge collection of a graph. If the
/// collections defined in the edge definition (collection, from, to) are not used
/// in another graph, they will be removed.
/// in another edge definition of the graph, they will be moved to the orphanage.
///
/// `general-graph._deleteEdgeDefinition(edgeCollectionName, dropCollections)`
/// `general-graph._deleteEdgeDefinition(edgeCollectionName)`
///
/// *edgeCollectionName* - string : name of edge collection defined in *collection* of the edge
/// definition.
/// *dropCollections* - bool : True, all collections are removed, if not used in another edge
/// definition (including other graphs). Default: true.
///
/// @EXAMPLES
///
@ -2741,56 +2735,49 @@ Graph.prototype._editEdgeDefinitions = function(edgeDefinition, dropCollections)
/// var ed1 = examples._directedRelationDefinition("myEC1", ["myVC1"], ["myVC2"]);
/// var ed2 = examples._directedRelationDefinition("myEC2", ["myVC1"], ["myVC3"]);
/// var g = examples._create("myGraph", [ed1, ed2]);
/// g._deleteEdgeDefinition("myEC1", true);
/// g._deleteEdgeDefinition("myEC1");
/// @END_EXAMPLE_ARANGOSH_OUTPUT
///
/// @endDocuBlock
///
////////////////////////////////////////////////////////////////////////////////
Graph.prototype._deleteEdgeDefinition = function(edgeCollection, dropCollections) {
Graph.prototype._deleteEdgeDefinition = function(edgeCollection) {
//check, if in graphs edge definition
if (this.__edgeCollections[edgeCollection] === undefined) {
var err = new ArangoError();
err.errorNum = arangodb.errors.ERROR_GRAPH_EDGE_COLLECTION_NOT_USED.code;
err.errorMessage = arangodb.errors.ERROR_GRAPH_EDGE_COLLECTION_NOT_USED.message;
throw err;
}
var edgeDefinitions = this.__edgeDefinitions,
vertexCollections = [],
definitionFound = false,
self = this,
usedVertexCollections = [],
possibleOrphans = [],
index;
edgeDefinitions.forEach(
function(edgeDefinition, idx) {
if (edgeDefinition.collection === edgeCollection) {
definitionFound = true;
if (dropCollections !== false) {
//get all vertex collections
var vertexCols = edgeDefinition.from.concat(edgeDefinition.to);
vertexCols.forEach(
function(vertexCol) {
if (vertexCollections.indexOf(vertexCol) === -1) {
vertexCollections.push(vertexCol);
}
}
);
}
index = idx;
possibleOrphans = edgeDefinition.from;
possibleOrphans = _.union(possibleOrphans, edgeDefinition.to);
} else {
usedVertexCollections = _.union(usedVertexCollections, edgeDefinition.from);
usedVertexCollections = _.union(usedVertexCollections, edgeDefinition.to);
}
}
);
if (definitionFound) {
edgeDefinitions.splice(index, 1);
this.__edgeDefinitions = edgeDefinitions;
db._graphs.update(this.__name, {edgeDefinitions: this.__edgeDefinitions});
}
if (dropCollections !== false) {
if (checkIfMayBeDropped(edgeCollection, this.__name, getGraphCollection().toArray())) {
db._drop(edgeCollection);
}
vertexCollections.forEach(
function(vC) {
if (checkIfMayBeDropped(vC, this.__name, getGraphCollection().toArray())) {
db._drop(vC);
}
this.__edgeDefinitions.splice(index, 1);
possibleOrphans.forEach(
function(po) {
if (usedVertexCollections.indexOf(po) === -1) {
self.__orphanCollections.push(po);
}
);
}
}
);
};
////////////////////////////////////////////////////////////////////////////////
@ -2816,17 +2803,17 @@ Graph.prototype._deleteEdgeDefinition = function(edgeCollection, dropCollections
///
////////////////////////////////////////////////////////////////////////////////
Graph.prototype._addOrphanCollection = function(vertexCollection, createCollection) {
Graph.prototype._addOrphanCollection = function(orphanCollectionName, createCollection) {
//check edgeCollection
var ec = db._collection(vertexCollection);
var ec = db._collection(orphanCollectionName);
var err;
if (ec === null) {
if (createCollection !== false) {
db._create(vertexCollection);
db._create(orphanCollectionName);
} else {
err = new ArangoError();
err.errorNum = arangodb.errors.ERROR_GRAPH_VERTEX_COL_DOES_NOT_EXIST.code;
err.errorMessage = vertexCollection + arangodb.errors.ERROR_GRAPH_VERTEX_COL_DOES_NOT_EXIST.message;
err.errorMessage = orphanCollectionName + arangodb.errors.ERROR_GRAPH_VERTEX_COL_DOES_NOT_EXIST.message;
throw err;
}
} else if (ec.type() !== 2) {
@ -2835,8 +2822,14 @@ Graph.prototype._addOrphanCollection = function(vertexCollection, createCollecti
err.errorMessage = arangodb.errors.ERROR_GRAPH_WRONG_COLLECTION_TYPE_VERTEX.message;
throw err;
}
if (this.__vertexCollections[orphanCollectionName] !== undefined) {
err = new ArangoError();
err.errorNum = arangodb.errors.ERROR_GRAPH_COLLECTION_USED_IN_EDGE_DEF.code;
err.errorMessage = arangodb.errors.ERROR_GRAPH_COLLECTION_USED_IN_EDGE_DEF.message;
throw err;
}
this.__orphanCollections.push(vertexCollection);
this.__orphanCollections.push(orphanCollectionName);
db._graphs.update(this.__name, {orphanCollections: this.__orphanCollections});
};

View File

@ -378,7 +378,7 @@ function cmdUsage () {
var fm = "foxx-manager";
printf("Example usage:\n");
printf(" %s install <foxx> <mount-point>\n", fm);
printf(" %s install <foxx> <mount-point> option1=value1\n", fm);
printf(" %s uninstall <mount-point>\n\n", fm);
printf("Further help:\n");
@ -460,6 +460,43 @@ function fetchDirectoryForInstall (name) {
return exports.fetch("directory", name).app;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief extracts command-line options
////////////////////////////////////////////////////////////////////////////////
function extractCommandLineOptions (args) {
'use strict';
var options = {};
var nargs = [];
var i;
var re1 = /^([\-_a-zA-Z0-9]*)=(.*)$/;
var re2 = /^(0|.0|([0-9]*(\.[0-9]*)?))$/;
for (i = 0; i < args.length; ++i) {
var a = args[i];
var m = re1.exec(a);
if (m !== null) {
var k = m[1];
var v = m[2];
if (re2.test(v)) {
options[k] = parseFloat(v);
}
else {
options[k] = v;
}
}
else {
nargs.push(args[i]);
}
}
return { 'options': options, 'args': nargs };
}
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// -----------------------------------------------------------------------------
@ -481,17 +518,37 @@ exports.run = function (args) {
var printf = arangodb.printf;
var res;
function extractOptions () {
var co = extractCommandLineOptions(args);
if (3 < co.args.length) {
var options = JSON.parse(co.args[3]);
if (options.hasOwnProperty("configuration")) {
var k;
for (k in co.options) {
if (co.options.hasOwnProperty(k)) {
options.configuration[k] = co.options[k];
}
}
}
else {
options.configuration = co.options;
}
return options;
}
return { configuration: co.options };
}
try {
if (type === 'fetch') {
exports.fetch(args[1], args[2], args[3]);
}
else if (type === 'mount') {
if (3 < args.length) {
exports.mount(args[1], args[2], JSON.parse(args[3]));
}
else {
exports.mount(args[1], args[2]);
}
exports.mount(args[1], args[2], extractOptions());
}
else if (type === 'rescan') {
exports.rescan();
@ -506,16 +563,13 @@ exports.run = function (args) {
exports.unmount(args[1]);
}
else if (type === 'install') {
if (3 < args.length) {
res = exports.install(args[1], args[2], JSON.parse(args[3]));
}
else {
res = exports.install(args[1], args[2]);
}
var options = extractOptions();
res = exports.install(args[1], args[2], options);
printf("Application %s installed successfully at mount point %s\n",
res.appId,
res.mount);
printf("options used: %s", JSON.stringify(options));
}
else if (type === 'replace') {
if (3 < args.length) {

View File

@ -216,6 +216,8 @@
"ERROR_GRAPH_VERTEX_COL_DOES_NOT_EXIST" : { "code" : 1926, "message" : "collection does not exist" },
"ERROR_GRAPH_WRONG_COLLECTION_TYPE_VERTEX" : { "code" : 1927, "message" : "not a vertex collection" },
"ERROR_GRAPH_NOT_IN_ORPHAN_COLLECTION" : { "code" : 1928, "message" : "not in orphan collection" },
"ERROR_GRAPH_COLLECTION_USED_IN_EDGE_DEF" : { "code" : 1929, "message" : "collection used in edge def" },
"ERROR_GRAPH_EDGE_COLLECTION_NOT_USED" : { "code" : 1930, "message" : "edge collection not used in graph" },
"ERROR_SESSION_UNKNOWN" : { "code" : 1950, "message" : "unknown session" },
"ERROR_SESSION_EXPIRED" : { "code" : 1951, "message" : "session expired" },
"SIMPLE_CLIENT_UNKNOWN_ERROR" : { "code" : 2000, "message" : "unknown client error" },

View File

@ -2032,7 +2032,8 @@ var checkIfMayBeDropped = function(colName, graphName, graphs) {
var _drop = function(graphId, dropCollections) {
var gdb = getGraphCollection();
var gdb = getGraphCollection(),
graphs;
if (!gdb.exists(graphId)) {
var err = new ArangoError();
@ -2049,7 +2050,7 @@ var _drop = function(graphId, dropCollections) {
var from = edgeDefinition.from;
var to = edgeDefinition.to;
var collection = edgeDefinition.collection;
var graphs = getGraphCollection().toArray();
graphs = getGraphCollection().toArray();
if (checkIfMayBeDropped(collection, graph._key, graphs)) {
db._drop(collection);
}
@ -2069,6 +2070,20 @@ var _drop = function(graphId, dropCollections) {
);
}
);
//drop orphans
graphs = getGraphCollection().toArray();
if (!graph.orphanCollections) {
graph.orphanCollections = [];
}
graph.orphanCollections.forEach(
function(oC) {
if (checkIfMayBeDropped(oC, graph._key, graphs)) {
try {
db._drop(oC);
} catch (e) {}
}
}
);
}
gdb.remove(graphId);
@ -2481,9 +2496,10 @@ Graph.prototype._amountCommonProperties = function(vertex1Example, vertex2Exampl
////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_general_graph__extendEdgeDefinitions
/// Extends the edge definitions of a graph. If the edge collection of the edge definition
/// to add is already used in the graph or used in a different graph with different from
/// an to collections an error is thrown.
/// Extends the edge definitions of a graph. If an orphan collection is used in this
/// edge definitino, it will be removed from the orphenage. If the edge collection of
/// the edge definition to add is already used in the graph or used in a different
/// graph with different from an to collections an error is thrown.
///
/// `general-graph._extendEdgeDefinitions(edgeDefinition)`
///
@ -2492,10 +2508,10 @@ Graph.prototype._amountCommonProperties = function(vertex1Example, vertex2Exampl
/// @EXAMPLES
///
/// @EXAMPLE_ARANGOSH_OUTPUT{general_graph__extendEdgeDefinitions}
/// var examples = require("org/arangodb/graph-examples/example-graph.js");
/// var ed1 = examples._directedRelationDefinition("myEC1", ["myVC1"], ["myVC2"]);
/// var ed2 = examples._directedRelationDefinition("myEC2", ["myVC1"], ["myVC3"]);
/// var g = examples._create("myGraph", [ed1]);
/// var graph = require("org/arangodb/general-graph")
/// var ed1 = graph._directedRelationDefinition("myEC1", ["myVC1"], ["myVC2"]);
/// var ed2 = graph._directedRelationDefinition("myEC2", ["myVC1"], ["myVC3"]);
/// var g = graph._create("myGraph", [ed1]);
/// g._extendEdgeDefinitions(ed2);
/// @END_EXAMPLE_ARANGOSH_OUTPUT
///
@ -2569,40 +2585,95 @@ Graph.prototype._extendEdgeDefinitions = function(edgeDefinition) {
};
////////////////////////////////////////////////////////////////////////////////
/// @brief internal function for editing edge definitions
////////////////////////////////////////////////////////////////////////////////
var changeEdgeDefinitionsForGraph = function(graph, edgeDefinition, newCollections, possibleOrphans, self) {
var oldCollections = [];
var graphCollections = [];
var graphObj = _graph(graph._key);
var eDs = graph.edgeDefinitions;
//replace edgeDefintion
eDs.forEach(
function(eD, id) {
if(eD.collection === edgeDefinition.collection) {
oldCollections = _.union(oldCollections, eD.from);
oldCollections = _.union(oldCollections, eD.to);
eDs[id].from = edgeDefinition.from;
eDs[id].to = edgeDefinition.to;
db._graphs.update(graph._key, {edgeDefinitions: eDs});
if (graph._key === self.__name) {
self.__edgeDefinitions[id].from = edgeDefinition.from;
self.__edgeDefinitions[id].to = edgeDefinition.to;
}
} else {
//collect all used collections
graphCollections = _.union(graphCollections, eD.from);
graphCollections = _.union(graphCollections, eD.to);
}
}
);
//remove used collection from orphanage
newCollections.forEach(
function(nc) {
if (graph._key === self.__name) {
if (self.__vertexCollections[nc] === undefined) {
self.__vertexCollections[nc] = db[nc];
}
try {
graphObj._removeOrphanCollection(nc);
} catch (e) {
}
}
}
);
//move unused collections to orphanage
possibleOrphans.forEach(
function(po) {
if (graphCollections.indexOf(po) === -1) {
delete graphObj.__vertexCollections[po];
graphObj._addOrphanCollection(po);
}
}
);
};
////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_general_graph__editEdgeDefinition
/// Edits the edge definitions of a graph. The edge definition used as argument will
/// replace the existing edge definition the corresponding edge definition in graphs
/// edge definitions. Other graphs with the same edge definition will be modified, too.
/// replace the existing edge definition of the graph which has the same collection.
/// Vertex Collections of the replaced edge definition, that are not used in the new
/// definition will transform to an orphan. Orphans that are used in this new edge
/// definition will be deleted from the list of orphans. Other graphs with the same edge
/// definition will be modified, too.
///
/// `general-graph._editEdgeDefinition(edgeDefinition, dropCollections)`
/// `general-graph._editEdgeDefinition(edgeDefinition)`
///
/// *edgeDefinition* - [string] : the edge definition to replace the existing edge
/// definition with the same attribut *collection*.
/// *dropCollections* - bool : True, all collections that are not used anymore in any
/// graph will be removed. Default: true.
/// definition with the same attribute *collection*.
///
/// @EXAMPLES
///
/// @EXAMPLE_ARANGOSH_OUTPUT{general_graph__editEdgeDefinition}
/// var examples = require("org/arangodb/graph-examples/example-graph.js");
/// var ed1 = examples._directedRelationDefinition("myEC1", ["myVC1"], ["myVC2"]);
/// var ed2 = examples._directedRelationDefinition("myEC1", ["myVC2"], ["myVC3"]);
/// var g = examples._create("myGraph", [ed1, ed2]);
/// var graph = require("org/arangodb/general-graph")
/// var ed1 = graph._directedRelationDefinition("myEC1", ["myVC1"], ["myVC2"]);
/// var ed2 = graph._directedRelationDefinition("myEC1", ["myVC2"], ["myVC3"]);
/// var g = graph._create("myGraph", [ed1, ed2]);
/// g._editEdgeDefinition(ed2, true);
/// @END_EXAMPLE_ARANGOSH_OUTPUT
///
/// @endDocuBlock
///
////////////////////////////////////////////////////////////////////////////////
Graph.prototype._editEdgeDefinitions = function(edgeDefinition, dropCollections) {
var self = this;
var dropCandidates;
var currentEdgeDefinition = {};
var exOrphanCandidates = [];
var effectedGraphs = [];
Graph.prototype._editEdgeDefinitions = function(edgeDefinition) {
var self = this;
//check, if in graphs edge definition
if (this.__edgeCollections[edgeDefinition.collection] === undefined) {
@ -2612,108 +2683,33 @@ Graph.prototype._editEdgeDefinitions = function(edgeDefinition, dropCollections)
throw err;
}
findOrCreateCollectionsByEdgeDefinitions([edgeDefinition]);
//evaluate collections to add to orphanage
var possibleOrphans = [];
var currentEdgeDefinition;
this.__edgeDefinitions.forEach(
function(ed) {
if (edgeDefinition.collection === ed.collection) {
currentEdgeDefinition = ed;
}
}
);
var currentCollections = _.union(currentEdgeDefinition.from, currentEdgeDefinition.to);
var newCollections = _.union(edgeDefinition.from, edgeDefinition.to);
currentCollections.forEach(
function(colName) {
if (newCollections.indexOf(colName) === -1) {
possibleOrphans.push(colName);
}
}
);
//change definition for ALL graphs
var graphs = getGraphCollection().toArray();
graphs.forEach(
function(graph) {
var eDs = graph.edgeDefinitions;
eDs.forEach(
function(eD, id) {
if(eD.collection === edgeDefinition.collection) {
currentEdgeDefinition.from = eD.from;
currentEdgeDefinition.to = eD.to;
eDs[id].from = edgeDefinition.from;
eDs[id].to = edgeDefinition.to;
db._graphs.update(graph._key, {edgeDefinitions: eDs});
effectedGraphs.push(graph._key);
if (graph._key === self.__name) {
self.__edgeDefinitions[id].from = edgeDefinition.from;
self.__edgeDefinitions[id].to = edgeDefinition.to;
}
}
}
);
}
);
findOrCreateCollectionsByEdgeDefinitions([edgeDefinition]);
if (dropCollections !== false) {
graphs = getGraphCollection().toArray();
//eval collection to be dropped
dropCandidates = currentEdgeDefinition.from;
currentEdgeDefinition.to.forEach(
function (col) {
if (dropCandidates.indexOf(col) === -1) {
dropCandidates.push(col);
}
}
);
dropCandidates.forEach(
function(dc) {
if (checkIfMayBeDropped(dc, null, graphs)) {
db._drop(dc);
}
}
);
}
//push "new" collections into vertexCollections
edgeDefinition.from.forEach(
function(vc) {
if (self.__vertexCollections[vc] === undefined) {
exOrphanCandidates.push(vc);
self.__vertexCollections[vc] = db[vc];
}
}
);
edgeDefinition.to.forEach(
function(vc) {
if (self.__vertexCollections[vc] === undefined) {
exOrphanCandidates.push(vc);
self.__vertexCollections[vc] = db[vc];
}
}
);
//remove "old" collections from vertexCollections
dropCandidates.forEach(
function(dropCanditate) {
var drop = true;
self.__edgeDefinitions.forEach(
function(eD) {
eD.from.forEach(
function(vC) {
if (vC === dropCanditate) {
drop = false;
}
}
);
}
);
if (drop) {
delete self.__vertexCollections[dropCanditate];
}
}
);
//orphans treatment
effectedGraphs.forEach(
function(gN) {
var g;
if (gN === self.__name) {
g = self;
} else {
g = _graph(gN);
}
var orphans = g._getOrphanCollections();
exOrphanCandidates.forEach(
function(eOC) {
if (orphans.indexOf(eOC) !== -1) {
g._removeOrphanCollection(eOC);
}
}
);
changeEdgeDefinitionsForGraph(graph, edgeDefinition, newCollections, possibleOrphans, self);
}
);
@ -2724,72 +2720,63 @@ Graph.prototype._editEdgeDefinitions = function(edgeDefinition, dropCollections)
/// @startDocuBlock JSF_general_graph__deleteEdgeDefinition
/// Deletes an edge definition defined by the edge collection of a graph. If the
/// collections defined in the edge definition (collection, from, to) are not used
/// in another graph, they will be removed.
/// in another edge definition of the graph, they will be moved to the orphanage.
///
/// `general-graph._deleteEdgeDefinition(edgeCollectionName, dropCollections)`
/// `general-graph._deleteEdgeDefinition(edgeCollectionName)`
///
/// *edgeCollectionName* - string : name of edge collection defined in *collection* of the edge
/// definition.
/// *dropCollections* - bool : True, all collections are removed, if not used in another edge
/// definition (including other graphs). Default: true.
///
/// @EXAMPLES
///
/// @EXAMPLE_ARANGOSH_OUTPUT{general_graph__deleteEdgeDefinition}
/// var examples = require("org/arangodb/graph-examples/example-graph.js");
/// var ed1 = examples._directedRelationDefinition("myEC1", ["myVC1"], ["myVC2"]);
/// var ed2 = examples._directedRelationDefinition("myEC2", ["myVC1"], ["myVC3"]);
/// var g = examples._create("myGraph", [ed1, ed2]);
/// g._deleteEdgeDefinition("myEC1", true);
/// var graph = require("org/arangodb/general-graph")
/// var ed1 = graph._directedRelationDefinition("myEC1", ["myVC1"], ["myVC2"]);
/// var ed2 = graph._directedRelationDefinition("myEC2", ["myVC1"], ["myVC3"]);
/// var g = graph._create("myGraph", [ed1, ed2]);
/// g._deleteEdgeDefinition("myEC1");
/// @END_EXAMPLE_ARANGOSH_OUTPUT
///
/// @endDocuBlock
///
////////////////////////////////////////////////////////////////////////////////
Graph.prototype._deleteEdgeDefinition = function(edgeCollection, dropCollections) {
Graph.prototype._deleteEdgeDefinition = function(edgeCollection) {
//check, if in graphs edge definition
if (this.__edgeCollections[edgeCollection] === undefined) {
var err = new ArangoError();
err.errorNum = arangodb.errors.ERROR_GRAPH_EDGE_COLLECTION_NOT_USED.code;
err.errorMessage = arangodb.errors.ERROR_GRAPH_EDGE_COLLECTION_NOT_USED.message;
throw err;
}
var edgeDefinitions = this.__edgeDefinitions,
vertexCollections = [],
definitionFound = false,
self = this,
usedVertexCollections = [],
possibleOrphans = [],
index;
edgeDefinitions.forEach(
function(edgeDefinition, idx) {
if (edgeDefinition.collection === edgeCollection) {
definitionFound = true;
if (dropCollections !== false) {
//get all vertex collections
var vertexCols = edgeDefinition.from.concat(edgeDefinition.to);
vertexCols.forEach(
function(vertexCol) {
if (vertexCollections.indexOf(vertexCol) === -1) {
vertexCollections.push(vertexCol);
}
}
);
}
index = idx;
possibleOrphans = edgeDefinition.from;
possibleOrphans = _.union(possibleOrphans, edgeDefinition.to);
} else {
usedVertexCollections = _.union(usedVertexCollections, edgeDefinition.from);
usedVertexCollections = _.union(usedVertexCollections, edgeDefinition.to);
}
}
);
if (definitionFound) {
edgeDefinitions.splice(index, 1);
this.__edgeDefinitions = edgeDefinitions;
db._graphs.update(this.__name, {edgeDefinitions: this.__edgeDefinitions});
}
if (dropCollections !== false) {
if (checkIfMayBeDropped(edgeCollection, this.__name, getGraphCollection().toArray())) {
db._drop(edgeCollection);
}
vertexCollections.forEach(
function(vC) {
if (checkIfMayBeDropped(vC, this.__name, getGraphCollection().toArray())) {
db._drop(vC);
}
this.__edgeDefinitions.splice(index, 1);
possibleOrphans.forEach(
function(po) {
if (usedVertexCollections.indexOf(po) === -1) {
self.__orphanCollections.push(po);
}
);
}
}
);
};
////////////////////////////////////////////////////////////////////////////////
@ -2805,9 +2792,9 @@ Graph.prototype._deleteEdgeDefinition = function(edgeCollection, dropCollections
/// @EXAMPLES
///
/// @EXAMPLE_ARANGOSH_OUTPUT{general_graph__addOrphanCollection}
/// var examples = require("org/arangodb/graph-examples/example-graph.js");
/// var ed1 = examples._directedRelationDefinition("myEC1", ["myVC1"], ["myVC2"]);
/// var g = examples._create("myGraph", [ed1, ed2]);
/// var graph = require("org/arangodb/general-graph")
/// var ed1 = graph._directedRelationDefinition("myEC1", ["myVC1"], ["myVC2"]);
/// var g = graph._create("myGraph", [ed1]);
/// g._addOrphanCollection("myVC3", true);
/// @END_EXAMPLE_ARANGOSH_OUTPUT
///
@ -2815,17 +2802,17 @@ Graph.prototype._deleteEdgeDefinition = function(edgeCollection, dropCollections
///
////////////////////////////////////////////////////////////////////////////////
Graph.prototype._addOrphanCollection = function(vertexCollection, createCollection) {
Graph.prototype._addOrphanCollection = function(orphanCollectionName, createCollection) {
//check edgeCollection
var ec = db._collection(vertexCollection);
var ec = db._collection(orphanCollectionName);
var err;
if (ec === null) {
if (createCollection !== false) {
db._create(vertexCollection);
db._create(orphanCollectionName);
} else {
err = new ArangoError();
err.errorNum = arangodb.errors.ERROR_GRAPH_VERTEX_COL_DOES_NOT_EXIST.code;
err.errorMessage = vertexCollection + arangodb.errors.ERROR_GRAPH_VERTEX_COL_DOES_NOT_EXIST.message;
err.errorMessage = orphanCollectionName + arangodb.errors.ERROR_GRAPH_VERTEX_COL_DOES_NOT_EXIST.message;
throw err;
}
} else if (ec.type() !== 2) {
@ -2834,8 +2821,14 @@ Graph.prototype._addOrphanCollection = function(vertexCollection, createCollecti
err.errorMessage = arangodb.errors.ERROR_GRAPH_WRONG_COLLECTION_TYPE_VERTEX.message;
throw err;
}
if (this.__vertexCollections[orphanCollectionName] !== undefined) {
err = new ArangoError();
err.errorNum = arangodb.errors.ERROR_GRAPH_COLLECTION_USED_IN_EDGE_DEF.code;
err.errorMessage = arangodb.errors.ERROR_GRAPH_COLLECTION_USED_IN_EDGE_DEF.message;
throw err;
}
this.__orphanCollections.push(vertexCollection);
this.__orphanCollections.push(orphanCollectionName);
db._graphs.update(this.__name, {orphanCollections: this.__orphanCollections});
};
@ -2849,9 +2842,9 @@ Graph.prototype._addOrphanCollection = function(vertexCollection, createCollecti
/// @EXAMPLES
///
/// @EXAMPLE_ARANGOSH_OUTPUT{general_graph__getOrphanCollections}
/// var examples = require("org/arangodb/graph-examples/example-graph.js");
/// var ed1 = examples._directedRelationDefinition("myEC1", ["myVC1"], ["myVC2"]);
/// var g = examples._create("myGraph", [ed1]);
/// var graph = require("org/arangodb/general-graph")
/// var ed1 = graph._directedRelationDefinition("myEC1", ["myVC1"], ["myVC2"]);
/// var g = graph._create("myGraph", [ed1]);
/// g._addOrphanCollection("myVC3", true);
/// g._getOrphanCollections();
/// @END_EXAMPLE_ARANGOSH_OUTPUT
@ -2878,9 +2871,9 @@ Graph.prototype._getOrphanCollections = function() {
/// @EXAMPLES
///
/// @EXAMPLE_ARANGOSH_OUTPUT{general_graph__removeOrphanCollections}
/// var examples = require("org/arangodb/graph-examples/example-graph.js");
/// var ed1 = examples._directedRelationDefinition("myEC1", ["myVC1"], ["myVC2"]);
/// var g = examples._create("myGraph", [ed1]);
/// var graph = require("org/arangodb/general-graph")
/// var ed1 = graph._directedRelationDefinition("myEC1", ["myVC1"], ["myVC2"]);
/// var g = graph._create("myGraph", [ed1]);
/// g._addOrphanCollection("myVC3", true);
/// g._addOrphanCollection("myVC4", true);
/// g._getOrphanCollections();

View File

@ -60,8 +60,52 @@ function GeneralGraphCreationSuite() {
)
);
var gN1 = "UnitTestEdgeDefDeleteGraph1",
gN2 = "UnitTestEdgeDefDeleteGraph2",
ec1 = "UnitTestEdgeDefDeleteEdgeCol1",
ec2 = "UnitTestEdgeDefDeleteEdgeCol2",
ec3 = "UnitTestEdgeDefDeleteEdgeCol3",
vc1 = "UnitTestEdgeDefDeleteVertexCol1",
vc2 = "UnitTestEdgeDefDeleteVertexCol2",
vc3 = "UnitTestEdgeDefDeleteVertexCol3",
vc4 = "UnitTestEdgeDefDeleteVertexCol4",
vc5 = "UnitTestEdgeDefDeleteVertexCol5",
vc6 = "UnitTestEdgeDefDeleteVertexCol6";
return {
setUp: function() {
try {
graph._drop(gN1);
} catch(ignore) {
}
try {
graph._drop(gN2);
} catch(ignore) {
}
},
tearDown: function() {
db._drop(ec1);
db._drop(ec2);
db._drop(ec3);
db._drop(vc1);
db._drop(vc2);
db._drop(vc3);
db._drop(vc4);
db._drop(vc5);
db._drop(vc6);
try {
graph._drop(gN1);
} catch(ignore) {
}
try {
graph._drop(gN2);
} catch(ignore) {
}
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test: Graph Creation
////////////////////////////////////////////////////////////////////////////////
@ -413,58 +457,39 @@ function GeneralGraphCreationSuite() {
},
test_deleteEdgeDefinitionFromExistingGraph: function() {
var gN1 = "UnitTestEdgeDefDeleteGraph1",
gN2 = "UnitTestEdgeDefDeleteGraph2",
ec1 = "UnitTestEdgeDefDeleteEdgeCol1",
ec2 = "UnitTestEdgeDefDeleteEdgeCol2",
ec3 = "UnitTestEdgeDefDeleteEdgeCol3",
vc1 = "UnitTestEdgeDefDeleteVertexCol1",
vc2 = "UnitTestEdgeDefDeleteVertexCol2",
vc3 = "UnitTestEdgeDefDeleteVertexCol3",
vc4 = "UnitTestEdgeDefDeleteVertexCol4",
vc5 = "UnitTestEdgeDefDeleteVertexCol5";
try {
graph._drop(gN1);
} catch(ignore) {
}
try {
graph._drop(gN2);
} catch(ignore) {
}
test_deleteEdgeDefinitionFromExistingGraph1: function() {
var dr1 = graph._directedRelationDefinition(ec1, [vc1], [vc1, vc2]),
dr2 = graph._directedRelationDefinition(ec2, [vc3], [vc4, vc5]),
dr3 = graph._directedRelationDefinition(ec3, [vc4], [vc5]),
g1 = graph._create(gN1, [dr1, dr2, dr3]),
g2 = graph._create(gN2, [dr3]);
g1._deleteEdgeDefinition(ec1, false);
assertEqual([dr2, dr3], g1.__edgeDefinitions);
g1._deleteEdgeDefinition(ec2, true);
assertEqual([dr3], g1.__edgeDefinitions);
assertTrue(db._collection(vc3) === null);
assertFalse(db._collection(vc4) === null);
assertFalse(db._collection(vc5) === null);
g1 = graph._create(gN1, [dr1]);
try {
graph._drop(gN1);
} catch(ignore) {
}
try {
graph._drop(gN2);
} catch(ignore) {
g1._deleteEdgeDefinition(ec1);
} catch (e) {
assertEqual(
e.errorMessage,
arangodb.errors.ERROR_GRAPH_EDGE_COLLECTION_NOT_USED.message
);
}
},
test_deleteEdgeDefinitionFromExistingGraph2: function() {
var dr1 = graph._directedRelationDefinition(ec1, [vc1], [vc1, vc2]),
dr2 = graph._directedRelationDefinition(ec2, [vc3], [vc4, vc5]),
dr3 = graph._directedRelationDefinition(ec3, [vc4], [vc5]),
g1 = graph._create(gN1, [dr1, dr2, dr3]);
assertEqual([dr1, dr2, dr3], g1.__edgeDefinitions);
g1._deleteEdgeDefinition(ec1);
assertEqual([dr2, dr3], g1.__edgeDefinitions);
assertEqual([vc1, vc2], g1._getOrphanCollections());
g1._deleteEdgeDefinition(ec2);
assertEqual([dr3], g1.__edgeDefinitions);
assertEqual([vc1, vc2, vc3], g1._getOrphanCollections());
},
test_extendEdgeDefinitionFromExistingGraph1: function() {
var gN1 = "UnitTestEdgeDefExtend1Graph1",
ec1 = "UnitTestEdgeDefExtend1EdgeCol1",
vc1 = "UnitTestEdgeDefExtend1VertexCol1",
vc2 = "UnitTestEdgeDefExtend1VertexCol2",
vc3 = "UnitTestEdgeDefExtend1VertexCol3";
try {
graph._drop(gN1);
@ -492,24 +517,6 @@ function GeneralGraphCreationSuite() {
},
test_extendEdgeDefinitionFromExistingGraph2: function() {
var gN1 = "UnitTestEdgeDefExtend2Graph1",
gN2 = "UnitTestEdgeDefExtend2Graph2",
ec1 = "UnitTestEdgeDefExtend2EdgeCol1",
ec2 = "UnitTestEdgeDefExtend2EdgeCol2",
ec3 = "UnitTestEdgeDefExtend2EdgeCol3",
vc1 = "UnitTestEdgeDefExtend2VertexCol1",
vc2 = "UnitTestEdgeDefExtend2VertexCol2",
vc3 = "UnitTestEdgeDefExtend2VertexCol3",
vc4 = "UnitTestEdgeDefExtend2VertexCol4",
vc5 = "UnitTestEdgeDefExtend2VertexCol5";
try {
graph._drop(gN1);
} catch(ignore) {
}
try {
graph._drop(gN2);
} catch(ignore) {
}
var dr1 = graph._directedRelationDefinition(ec1, [vc1], [vc1, vc2]),
dr2 = graph._directedRelationDefinition(ec2, [vc3], [vc4, vc5]),
@ -538,16 +545,6 @@ function GeneralGraphCreationSuite() {
},
test_extendEdgeDefinitionFromExistingGraph3: function() {
var gN1 = "UnitTestEdgeDefExtend3Graph1",
gN2 = "UnitTestEdgeDefExtend3Graph2",
ec1 = "UnitTestEdgeDefExtend3EdgeCol1",
ec2 = "UnitTestEdgeDefExtend3EdgeCol2",
ec3 = "UnitTestEdgeDefExtend3EdgeCol3",
vc1 = "UnitTestEdgeDefExtend3VertexCol1",
vc2 = "UnitTestEdgeDefExtend3VertexCol2",
vc3 = "UnitTestEdgeDefExtend3VertexCol3",
vc4 = "UnitTestEdgeDefExtend3VertexCol4",
vc5 = "UnitTestEdgeDefExtend3VertexCol5";
try {
graph._drop(gN1);
} catch(ignore) {
@ -572,32 +569,9 @@ function GeneralGraphCreationSuite() {
g1._extendEdgeDefinitions(dr3);
assertEqual([dr1, dr2, dr3], g1.__edgeDefinitions);
try {
graph._drop(gN1);
} catch(ignore) {
}
try {
graph._drop(gN2);
} catch(ignore) {
}
},
test_editEdgeDefinitionFromExistingGraph1: function() {
var gN1 = "UnitTestEdgeDefEdit1Graph1",
ec1 = "UnitTestEdgeDefEdit1EdgeCol1",
ec2 = "UnitTestEdgeDefEdit1EdgeCol2",
vc1 = "UnitTestEdgeDefEdit1VertexCol1",
vc2 = "UnitTestEdgeDefEdit1VertexCol2",
vc3 = "UnitTestEdgeDefEdit1VertexCol3",
vc4 = "UnitTestEdgeDefEdit1VertexCol4",
vc5 = "UnitTestEdgeDefEdit1VertexCol5";
try {
graph._drop(gN1);
} catch(ignore) {
}
var dr1 = graph._directedRelationDefinition(ec1, [vc1], [vc1, vc2]),
dr2 = graph._directedRelationDefinition(ec2, [vc3], [vc4, vc5]),
g1 = graph._create(gN1, [dr1]);
@ -607,77 +581,35 @@ function GeneralGraphCreationSuite() {
} catch (e) {
assertEqual(
e.errorMessage,
arangodb.errors.ERROR_GRAPH_EDGE_COLLECTION_NOT_USED
arangodb.errors.ERROR_GRAPH_EDGE_COLLECTION_NOT_USED.message
);
}
try {
graph._drop(gN1);
} catch(ignore) {
}
},
test_editEdgeDefinitionFromExistingGraph2: function() {
var gN1 = "UnitTestEdgeDefEdit2Graph1",
gN2 = "UnitTestEdgeDefEdit2Graph2",
ec1 = "UnitTestEdgeDefEdit2EdgeCol1",
vc1 = "UnitTestEdgeDefEdit2VertexCol1",
vc2 = "UnitTestEdgeDefEdit2VertexCol2",
vc3 = "UnitTestEdgeDefEdit2VertexCol3",
vc4 = "UnitTestEdgeDefEdit2VertexCol4",
vc5 = "UnitTestEdgeDefEdit2VertexCol5";
try {
graph._drop(gN1);
} catch(ignore) {
}
try {
graph._drop(gN2);
} catch(ignore) {
}
var dr1 = graph._directedRelationDefinition(ec1, [vc1], [vc1, vc2]),
dr2 = graph._directedRelationDefinition(ec1, [vc3], [vc4, vc5]),
g1 = graph._create(gN1, [dr1]),
var dr1 = graph._directedRelationDefinition(ec1, [vc1, vc2], [vc3, vc4]),
dr2 = graph._directedRelationDefinition(ec2, [vc1], [vc4]),
dr3 = graph._directedRelationDefinition(ec1, [vc5], [vc5]),
g1 = graph._create(gN1, [dr1, dr2]),
g2 = graph._create(gN2, [dr1]);
g1._editEdgeDefinitions(dr2, true);
assertEqual([dr2], g1.__edgeDefinitions);
assertEqual([dr2], g2.__edgeDefinitions);
assertTrue(db._collection(vc1) === null);
assertTrue(db._collection(vc2) === null);
try {
graph._drop(gN1);
} catch(ignore) {
}
try {
graph._drop(gN2);
} catch(ignore) {
}
g1._editEdgeDefinitions(dr3);
assertEqual([dr3, dr2], g1.__edgeDefinitions);
assertEqual([dr3], g2.__edgeDefinitions);
g1 = graph._graph(gN1);
g2 = graph._graph(gN2);
assertTrue(g1._getOrphanCollections().indexOf(vc2) !== -1);
assertTrue(g1._getOrphanCollections().indexOf(vc3) !== -1);
assertTrue(g2._getOrphanCollections().indexOf(vc1) !== -1);
assertTrue(g2._getOrphanCollections().indexOf(vc2) !== -1);
assertTrue(g2._getOrphanCollections().indexOf(vc3) !== -1);
assertTrue(g2._getOrphanCollections().indexOf(vc4) !== -1);
},
test_editEdgeDefinitionFromExistingGraph3: function() {
var prefix = "UnitTestEdgeDefEdit3",
gN1 = prefix + "Graph1",
gN2 = prefix + "Graph2",
ec1 = prefix + "EdgeCol1",
ec2 = prefix + "EdgeCol2",
vc1 = prefix + "VertexCol1",
vc2 = prefix + "VertexCol2",
vc3 = prefix + "VertexCol3",
vc4 = prefix + "VertexCol4",
vc5 = prefix + "VertexCol5",
vc6 = prefix + "VertexCol6";
try {
graph._drop(gN1);
} catch(ignore) {
}
try {
graph._drop(gN2);
} catch(ignore) {
}
var dr1 = graph._directedRelationDefinition(ec1, [vc1], [vc1, vc2]),
dr2 = graph._directedRelationDefinition(ec1, [vc3], [vc4, vc5]),
@ -689,13 +621,15 @@ function GeneralGraphCreationSuite() {
g2._addOrphanCollection(vc5);
g2._addOrphanCollection(vc6);
g1._editEdgeDefinitions(dr2, true);
assertEqual([dr2, dr3], g1.__edgeDefinitions);
assertEqual([dr2], g2.__edgeDefinitions);
assertTrue(db._collection(vc1) === null);
assertFalse(db._collection(vc2) === null);
assertEqual([], g1._getOrphanCollections());
g1 = graph._graph(gN1);
g2 = graph._graph(gN2);
assertEqual([vc6], g2._getOrphanCollections());
assertEqual([vc1], g1._getOrphanCollections());
assertTrue(g2._getOrphanCollections().indexOf(vc1) !== -1);
assertTrue(g2._getOrphanCollections().indexOf(vc2) !== -1);
assertTrue(g2._getOrphanCollections().indexOf(vc6) !== -1);
try {
graph._drop(gN1);
@ -2562,8 +2496,8 @@ function OrphanCollectionSuite() {
},
test_addOrphanCollection1: function() {
g1._addOrphanCollection(vC1, false);
assertEqual(g1._getOrphanCollections(), [vC1]);
g1._addOrphanCollection(vC5, true);
assertEqual(g1._getOrphanCollections(), [vC5]);
},
test_addOrphanCollection2: function() {
@ -2588,6 +2522,15 @@ function OrphanCollectionSuite() {
assertEqual(g1._getOrphanCollections(), []);
},
test_addOrphanCollection4: function() {
try {
g1._addOrphanCollection(vC1);
} catch (e) {
assertEqual(e.errorNum, ERRORS.ERROR_GRAPH_COLLECTION_USED_IN_EDGE_DEF.code);
assertEqual(e.errorMessage, ERRORS.ERROR_GRAPH_COLLECTION_USED_IN_EDGE_DEF.message);
}
},
test_removeOrphanCollection1: function() {
var name = "completelyNonsenseNameForACollectionBLUBBBBB"
try {

View File

@ -4437,13 +4437,15 @@ function TRAVERSAL_FUNC (func,
maxIterations: params.maxIterations,
uniqueness: params.uniqueness,
expander: direction,
direction: direction,
strategy: params.strategy,
order: params.order,
itemOrder: params.itemOrder,
startVertex : startVertex,
endVertex : endVertex,
weight : params.weight,
defaultWeight : params.defaultWeight
defaultWeight : params.defaultWeight,
prefill : params.prefill
};
@ -4643,18 +4645,6 @@ function DETERMINE_WEIGHT (edge, weight, defaultWeight) {
return Infinity;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief visitor callback function for traversal
////////////////////////////////////////////////////////////////////////////////
function TRAVERSAL_SHORTEST_PATH_VISITOR (config, result, vertex, path) {
"use strict";
if (config.endVertex && config.endVertex === vertex._id) {
result.push(CLONE({ vertex: vertex, path: path , startVertex : config.startVertex}));
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief visitor callback function for traversal
@ -4664,18 +4654,19 @@ function TRAVERSAL_DISTANCE_VISITOR (config, result, vertex, path) {
"use strict";
if (config.endVertex && config.endVertex === vertex._id) {
var subPaths = [];
var dist = 0;
if (config.weight) {
path.edges.forEach(function (e) {
path.edges.forEach(function (e) {
if (config.weight) {
if (typeof e[config.weight] === "number") {
dist = dist + e[config.weight];
} else if (config.defaultWeight) {
dist = dist + config.defaultWeight;
}
});
} else {
dist = path.edges.length;
}
} else {
dist++;
}
});
result.push(
CLONE({ vertex: vertex, distance: dist , path: path , startVertex : config.startVertex})
);
@ -4683,6 +4674,62 @@ function TRAVERSAL_DISTANCE_VISITOR (config, result, vertex, path) {
}
////////////////////////////////////////////////////////////////////////////////
/// @brief visitor callback function for traversal
////////////////////////////////////////////////////////////////////////////////
function TRAVERSAL_DIJSKTRA_VISITOR (config, result, vertex, path) {
"use strict";
if (config.endVertex && config.endVertex === vertex._id) {
path.vertices.forEach(function (from) {
path.vertices.forEach(function (to) {
if (config.prefill.indexOf(JSON.stringify({ from : TO_ID(from), to : TO_ID(to)})) !== -1) {
return;
}
var positionFrom = path.vertices.indexOf(from);
var positionTo = path.vertices.indexOf(to);
if (positionFrom > positionTo && config.direction !== 'any') {
return;
}
var startVertex = from._id;
var vertex = to;
var distance = 0;
var pathNew = {vertices : [from], edges : []};
while (positionFrom !== positionTo) {
var edgePosition;
if (positionFrom > positionTo) {
edgePosition = positionFrom-1;
} else {
edgePosition = positionFrom;
}
if (positionFrom > positionTo) {
positionFrom = positionFrom -1;
} else {
positionFrom ++;
}
pathNew.vertices.push(path.vertices[positionFrom]);
pathNew.edges.push(path.edges[edgePosition]);
if (config.weight) {
if (path.edges[edgePosition][config.weight] &&
typeof path.edges[edgePosition][config.weight] === "number") {
distance = distance + path.edges[edgePosition][config.weight];
} else if (config.defaultWeight) {
distance = distance + config.defaultWeight;
}
} else {
distance++;
}
}
result.push(
CLONE({ vertex: vertex, distance: distance , path: pathNew , startVertex : startVertex})
);
});
});
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief helper function to determine parameters for SHORTEST_PATH and
@ -4920,6 +4967,8 @@ function MERGE_EXAMPLES_WITH_EDGES (examples, edges) {
return result;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief calculate shortest paths by dijkstra
////////////////////////////////////////////////////////////////////////////////
@ -4931,17 +4980,29 @@ function CALCULATE_SHORTEST_PATHES_WITH_DIJKSTRA (graphName, graphData, options)
params.weight = options.weight;
params.defaultWeight = options.defaultWeight;
params = SHORTEST_PATH_PARAMS(params);
params.visitor = TRAVERSAL_DISTANCE_VISITOR;
params.visitor = TRAVERSAL_DIJSKTRA_VISITOR;
var result = [];
var calculated = {};
graphData.fromVertices.forEach(function (v) {
graphData.toVertices.forEach(function (t) {
if (calculated[JSON.stringify({ from : TO_ID(v), to : TO_ID(t)})]) {
result.push(calculated[JSON.stringify({ from : TO_ID(v), to : TO_ID(t)})]);
return;
}
params.prefill = Object.keys(calculated);
var e = TRAVERSAL_FUNC("GENERAL_GRAPH_SHORTEST_PATH",
factory,
TO_ID(v),
TO_ID(t),
options.direction,
params);
result = result.concat(e);
e.forEach(function (f) {
if (TO_ID(v) === f.startVertex && TO_ID(t) === f.vertex._id) {
result.push(f);
}
calculated[JSON.stringify({ from : f.startVertex, to : f.vertex._id})] = f;
});
});
});
result.forEach(function (r) {

View File

@ -88,6 +88,7 @@ function getStorage () {
////////////////////////////////////////////////////////////////////////////////
/// @brief check a manifest for completeness
///
/// this implements issue #590: Manifest Lint
////////////////////////////////////////////////////////////////////////////////
@ -120,14 +121,15 @@ function checkManifest (filename, mf) {
var expected = {
"assets": [ false, "object" ],
"author": [ false, "string" ],
"configuration": [ false, "object" ],
"contributors": [ false, "array" ],
"controllers": [ false, "object" ],
"defaultDocument": [ false, "string" ],
"description": [ true, "string" ],
"engines": [ false, "object" ],
"files": [ false, "object" ],
"keywords": [ false, "array" ],
"isSystem": [ false, "boolean" ],
"keywords": [ false, "array" ],
"lib": [ false, "string" ],
"license": [ false, "string" ],
"name": [ true, "string" ],
@ -363,9 +365,9 @@ function buildFileAsset (app, path, basePath, asset) {
var content = buildAssetContent(app, asset.files, basePath);
var type;
// -----------------------------------------------------------------------------
// .............................................................................
// content-type detection
// -----------------------------------------------------------------------------
// .............................................................................
// contentType explicitly specified for asset
if (asset.hasOwnProperty("contentType") && asset.contentType !== '') {
@ -388,9 +390,9 @@ function buildFileAsset (app, path, basePath, asset) {
type = arangodb.guessContentType("");
}
// -----------------------------------------------------------------------------
// .............................................................................
// return content
// -----------------------------------------------------------------------------
// .............................................................................
return { contentType: type, body: content };
}
@ -528,6 +530,7 @@ function executeAppScript (app, name, mount, prefix) {
appContext.mount = mount;
appContext.collectionPrefix = prefix;
appContext.options = app._options;
appContext.configuration = app._options.configuration;
appContext.basePath = fs.join(root, app._path);
appContext.isDevelopment = devel;
@ -747,6 +750,7 @@ function routingAalApp (app, mount, options) {
appContextTempl.mount = mount; // global mount
appContextTempl.options = options;
appContextTempl.configuration = app._options.configuration;
appContextTempl.collectionPrefix = prefix; // collection prefix
appContextTempl.basePath = fs.join(root, app._path);
@ -908,6 +912,68 @@ function scanDirectory (path) {
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create configuration
////////////////////////////////////////////////////////////////////////////////
function checkConfiguration (app, options) {
'use strict';
if (options === undefined || options === null) {
options = {};
}
if (! options.hasOwnProperty("configuration")) {
options.configuration = {};
}
if (! app._manifest.hasOwnProperty("configuration")) {
return options;
}
var configuration = options.configuration;
var expected = app._manifest.configuration;
var att;
for (att in expected) {
if (expected.hasOwnProperty(att)) {
if (configuration.hasOwnProperty(att)) {
var value = configuration[att];
var expectedType = expected[att].type;
var actualType = Array.isArray(value) ? "array" : typeof(value);
if (actualType !== expectedType) {
throw new Error(
"configuration for '" + app._manifest.name + "' uses "
+ "an invalid data type (" + actualType + ") "
+ "for " + expectedType + " attribute '" + att + "'");
}
}
else if (expected[att].hasOwnProperty("default")) {
configuration[att] = expected[att]["default"];
}
else {
throw new Error(
"configuration for '" + app._manifest.name + "' is "
+ "missing a value for attribute '" + att + "'");
}
}
}
// additionally check if there are superfluous attributes in the manifest
for (att in configuration) {
if (configuration.hasOwnProperty(att)) {
if (! expected.hasOwnProperty(att)) {
console.warn("configuration for '%s' contains an unknown attribute '%s'",
app._manifest.name,
att);
}
}
}
return options;
}
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// -----------------------------------------------------------------------------
@ -950,6 +1016,7 @@ exports.rescan = function () {
/// * options:
/// collectionPrefix: overwrites the default prefix
/// reload: reload the routing info (default: true)
/// configuration: configuration options
///
/// Output:
/// * appId: the application identifier (must be mounted)
@ -983,7 +1050,7 @@ exports.mount = function (appId, mount, options) {
// install the application
// .............................................................................
options = options || { };
options = checkConfiguration(app, options);
var doc;

View File

@ -1475,6 +1475,16 @@ function ahuacatlQueryGeneralTraversalTestSuite() {
assertEqual(actual[0]["UnitTests_Leipziger/Gerda"], 1);
actual = getQueryResults("RETURN GRAPH_ECCENTRICITY('werKenntWen')");
assertEqual(actual[0]["UnitTests_Berliner/Anton"].toFixed(1), 0.6);
assertEqual(actual[0]["UnitTests_Berliner/Berta"].toFixed(2), 0.75);
assertEqual(actual[0]["UnitTests_Frankfurter/Emil"].toFixed(2), 0.75);
assertEqual(actual[0]["UnitTests_Frankfurter/Fritz"].toFixed(1), 0.6);
assertEqual(actual[0]["UnitTests_Hamburger/Caesar"].toFixed(1), 0.6);
assertEqual(actual[0]["UnitTests_Hamburger/Dieter"], 1);
assertEqual(actual[0]["UnitTests_Leipziger/Gerda"], 1);
actual = getQueryResults("RETURN GRAPH_ECCENTRICITY('werKenntWen', {algorithm : 'dijkstra', direction : 'inbound'})");
assertEqual(actual[0]["UnitTests_Berliner/Anton"], 1);
assertEqual(actual[0]["UnitTests_Berliner/Berta"], 1);

View File

@ -296,6 +296,8 @@ ERROR_GRAPH_DUPLICATE,1925,"graph already exists","a graph with this name alread
ERROR_GRAPH_VERTEX_COL_DOES_NOT_EXIST,1926,"collection does not exist"," does not exist.",
ERROR_GRAPH_WRONG_COLLECTION_TYPE_VERTEX,1927,"not a vertex collection","the collection is not a vertex collection.",
ERROR_GRAPH_NOT_IN_ORPHAN_COLLECTION,1928,"not in orphan collection","Vertex collection not in orphan collection of the graph.",
ERROR_GRAPH_COLLECTION_USED_IN_EDGE_DEF,1929,"collection used in edge def","The collection is already used in an edge definition of the graph.",
ERROR_GRAPH_EDGE_COLLECTION_NOT_USED,1930,"edge collection not used in graph","The edge collection is not used in any edge definition of the graph.",
################################################################################
## Session errors

View File

@ -212,6 +212,8 @@ void TRI_InitialiseErrorMessages (void) {
REG_ERROR(ERROR_GRAPH_VERTEX_COL_DOES_NOT_EXIST, "collection does not exist");
REG_ERROR(ERROR_GRAPH_WRONG_COLLECTION_TYPE_VERTEX, "not a vertex collection");
REG_ERROR(ERROR_GRAPH_NOT_IN_ORPHAN_COLLECTION, "not in orphan collection");
REG_ERROR(ERROR_GRAPH_COLLECTION_USED_IN_EDGE_DEF, "collection used in edge def");
REG_ERROR(ERROR_GRAPH_EDGE_COLLECTION_NOT_USED, "edge collection not used in graph");
REG_ERROR(ERROR_SESSION_UNKNOWN, "unknown session");
REG_ERROR(ERROR_SESSION_EXPIRED, "session expired");
REG_ERROR(SIMPLE_CLIENT_UNKNOWN_ERROR, "unknown client error");

View File

@ -498,6 +498,10 @@ extern "C" {
/// the collection is not a vertex collection.
/// - 1928: @LIT{not in orphan collection}
/// Vertex collection not in orphan collection of the graph.
/// - 1929: @LIT{collection used in edge def}
/// The collection is already used in an edge definition of the graph.
/// - 1930: @LIT{edge collection not used in graph}
/// The edge collection is not used in any edge definition of the graph.
/// - 1950: @LIT{unknown session}
/// Will be raised when an invalid/unknown session id is passed to the server.
/// - 1951: @LIT{session expired}
@ -2638,6 +2642,26 @@ void TRI_InitialiseErrorMessages (void);
#define TRI_ERROR_GRAPH_NOT_IN_ORPHAN_COLLECTION (1928)
////////////////////////////////////////////////////////////////////////////////
/// @brief 1929: ERROR_GRAPH_COLLECTION_USED_IN_EDGE_DEF
///
/// collection used in edge def
///
/// The collection is already used in an edge definition of the graph.
////////////////////////////////////////////////////////////////////////////////
#define TRI_ERROR_GRAPH_COLLECTION_USED_IN_EDGE_DEF (1929)
////////////////////////////////////////////////////////////////////////////////
/// @brief 1930: ERROR_GRAPH_EDGE_COLLECTION_NOT_USED
///
/// edge collection not used in graph
///
/// The edge collection is not used in any edge definition of the graph.
////////////////////////////////////////////////////////////////////////////////
#define TRI_ERROR_GRAPH_EDGE_COLLECTION_NOT_USED (1930)
////////////////////////////////////////////////////////////////////////////////
/// @brief 1950: ERROR_SESSION_UNKNOWN
///