1
0
Fork 0
arangodb/js/actions/api-traversal.js

288 lines
7.4 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_COLLECTION_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",
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);
}
}
});