mirror of https://gitee.com/bigwinds/arangodb
271 lines
7.3 KiB
JavaScript
271 lines
7.3 KiB
JavaScript
/* jshint strict: false */
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / @brief traversal actions
|
|
// /
|
|
// / @file
|
|
// /
|
|
// / DISCLAIMER
|
|
// /
|
|
// / Copyright 2014 ArangoDB GmbH, Cologne, Germany
|
|
// /
|
|
// / Licensed under the Apache License, Version 2.0 (the "License")
|
|
// / you may not use this file except in compliance with the License.
|
|
// / You may obtain a copy of the License at
|
|
// /
|
|
// / http://www.apache.org/licenses/LICENSE-2.0
|
|
// /
|
|
// / Unless required by applicable law or agreed to in writing, software
|
|
// / distributed under the License is distributed on an "AS IS" BASIS,
|
|
// / WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// / See the License for the specific language governing permissions and
|
|
// / limitations under the License.
|
|
// /
|
|
// / Copyright holder is ArangoDB GmbH, Cologne, Germany
|
|
// /
|
|
// / @author Jan Steemann
|
|
// / @author Copyright 2014, ArangoDB GmbH, Cologne, Germany
|
|
// / @author Copyright 2013, triAGENS GmbH, Cologne, Germany
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
|
|
var arangodb = require('@arangodb');
|
|
var actions = require('@arangodb/actions');
|
|
var db = require('internal').db;
|
|
var traversal = require('@arangodb/graph/traversal');
|
|
var Traverser = traversal.Traverser;
|
|
var graph = require('@arangodb/general-graph');
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / @brief create a "bad parameter" error
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
|
|
function badParam (req, res, message) {
|
|
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,
|
|
code,
|
|
message);
|
|
}
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / @brief was docuBlock JSF_HTTP_API_TRAVERSAL
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
|
|
function post_api_traversal (req, res) {
|
|
/* jshint evil: true */
|
|
var json = actions.getJsonBody(req, res);
|
|
|
|
if (json === undefined) {
|
|
return badParam(req, res);
|
|
}
|
|
|
|
// check start vertex
|
|
// -----------------------------------------
|
|
|
|
if (json.startVertex === undefined ||
|
|
typeof json.startVertex !== 'string') {
|
|
return badParam(req, res, 'missing or invalid startVertex');
|
|
}
|
|
|
|
var doc;
|
|
try {
|
|
doc = db._document(json.startVertex);
|
|
} catch (err) {
|
|
return notFound(req, res, arangodb.ERROR_ARANGO_DOCUMENT_NOT_FOUND, 'invalid startVertex');
|
|
}
|
|
|
|
var datasource;
|
|
var edgeCollection;
|
|
|
|
if (json.graphName === undefined) {
|
|
// check edge collection
|
|
// -----------------------------------------
|
|
|
|
if (json.edgeCollection === undefined) {
|
|
return badParam(req, res, 'missing graphname');
|
|
}
|
|
if (typeof json.edgeCollection !== 'string') {
|
|
return notFound(req, res, 'invalid edgecollection');
|
|
}
|
|
|
|
try {
|
|
edgeCollection = db._collection(json.edgeCollection);
|
|
datasource = traversal.collectionDatasourceFactory(edgeCollection);
|
|
} catch (ignore) {}
|
|
|
|
if (edgeCollection === undefined ||
|
|
edgeCollection === null) {
|
|
return notFound(req, res, arangodb.ERROR_ARANGO_DATA_SOURCE_NOT_FOUND,
|
|
'invalid edgeCollection');
|
|
}
|
|
} else {
|
|
if (typeof json.graphName !== 'string' || !graph._exists(json.graphName)) {
|
|
return notFound(req, res, arangodb.ERROR_GRAPH_NOT_FOUND,
|
|
'invalid graphname');
|
|
}
|
|
datasource = traversal.generalGraphDatasourceFactory(json.graphName);
|
|
}
|
|
|
|
// set up filters
|
|
// -----------------------------------------
|
|
|
|
var filters = [];
|
|
if (json.minDepth !== undefined) {
|
|
filters.push(traversal.minDepthFilter);
|
|
}
|
|
if (json.maxDepth !== undefined) {
|
|
filters.push(traversal.maxDepthFilter);
|
|
}
|
|
if (json.filter) {
|
|
try {
|
|
filters.push(new Function('config', 'vertex', 'path', json.filter));
|
|
} catch (err3) {
|
|
return badParam(req, res, 'invalid filter function');
|
|
}
|
|
}
|
|
|
|
// if no filter given, use the default filter (does nothing)
|
|
if (filters.length === 0) {
|
|
filters.push(traversal.visitAllFilter);
|
|
}
|
|
|
|
// set up visitor
|
|
// -----------------------------------------
|
|
|
|
var visitor;
|
|
|
|
if (json.visitor !== undefined) {
|
|
try {
|
|
visitor = new Function('config', 'result', 'vertex', 'path', 'connected', json.visitor);
|
|
} catch (err4) {
|
|
return badParam(req, res, 'invalid visitor function');
|
|
}
|
|
} else {
|
|
visitor = traversal.trackingVisitor;
|
|
}
|
|
|
|
// set up expander
|
|
// -----------------------------------------
|
|
|
|
var expander;
|
|
|
|
if (json.direction !== undefined) {
|
|
expander = json.direction;
|
|
} else if (json.expander !== undefined) {
|
|
try {
|
|
expander = new Function('config', 'vertex', 'path', json.expander);
|
|
} catch (err5) {
|
|
return badParam(req, res, 'invalid expander function');
|
|
}
|
|
}
|
|
|
|
if (expander === undefined) {
|
|
return badParam(req, res, 'missing or invalid expander');
|
|
}
|
|
|
|
// set up sort
|
|
// -----------------------------------------
|
|
|
|
var sort;
|
|
|
|
if (json.sort !== undefined) {
|
|
try {
|
|
sort = new Function('l', 'r', json.sort);
|
|
} catch (err6) {
|
|
return badParam(req, res, 'invalid sort function');
|
|
}
|
|
}
|
|
|
|
// assemble config object
|
|
// -----------------------------------------
|
|
|
|
var config = {
|
|
params: json,
|
|
datasource: datasource,
|
|
strategy: json.strategy,
|
|
order: json.order,
|
|
itemOrder: json.itemOrder,
|
|
expander: expander,
|
|
sort: sort,
|
|
visitor: visitor,
|
|
filter: filters,
|
|
minDepth: json.minDepth,
|
|
maxDepth: json.maxDepth,
|
|
maxIterations: json.maxIterations,
|
|
uniqueness: json.uniqueness
|
|
};
|
|
|
|
if (edgeCollection !== undefined) {
|
|
config.edgeCollection = edgeCollection;
|
|
}
|
|
|
|
// assemble result object
|
|
// -----------------------------------------
|
|
|
|
var result = {
|
|
visited: {
|
|
vertices: [],
|
|
paths: []
|
|
}
|
|
};
|
|
|
|
if (json.init !== undefined) {
|
|
try {
|
|
var init = new Function('result', json.init);
|
|
init(result);
|
|
} catch (err7) {
|
|
return badParam(req, res, 'invalid init function');
|
|
}
|
|
}
|
|
|
|
// run the traversal
|
|
// -----------------------------------------
|
|
|
|
var traverser;
|
|
try {
|
|
traverser = new Traverser(config);
|
|
traverser.traverse(result, doc);
|
|
actions.resultOk(req, res, actions.HTTP_OK, { result: result });
|
|
} catch (err8) {
|
|
if (traverser === undefined) {
|
|
// error during traversal setup
|
|
return badParam(req, res, err8);
|
|
}
|
|
actions.resultException(req, res, err8, undefined, false);
|
|
}
|
|
}
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / @brief gateway
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
|
|
actions.defineHttp({
|
|
url: '_api/traversal',
|
|
isSystem: false,
|
|
|
|
callback: function (req, res) {
|
|
try {
|
|
switch (req.requestType) {
|
|
case actions.POST:
|
|
post_api_traversal(req, res);
|
|
break;
|
|
|
|
default:
|
|
actions.resultUnsupported(req, res);
|
|
}
|
|
} catch (err) {
|
|
actions.resultException(req, res, err);
|
|
}
|
|
}
|
|
});
|