1
0
Fork 0
arangodb/js/common/modules/org/arangodb-common.js

530 lines
14 KiB
JavaScript

/*jslint indent: 2, maxlen: 100, nomen: true, vars: true, white: true, plusplus: true */
/*global require, module, exports */
////////////////////////////////////////////////////////////////////////////////
/// @brief JavaScript base module
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2004-2013 triAGENS 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 triAGENS GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
var internal = require("internal");
var fs = require("fs");
var mimetypes = require("org/arangodb/mimetypes").mimeTypes;
// -----------------------------------------------------------------------------
// --SECTION-- module "arangodb"
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// --SECTION-- public constants
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief errors
////////////////////////////////////////////////////////////////////////////////
(function () {
'use strict';
var name;
for (name in internal.errors) {
if (internal.errors.hasOwnProperty(name)) {
exports[name] = internal.errors[name].code;
}
}
}());
exports.errors = internal.errors;
// -----------------------------------------------------------------------------
// --SECTION-- public types
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief ArangoError
////////////////////////////////////////////////////////////////////////////////
exports.ArangoError = internal.ArangoError;
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief defines a module
////////////////////////////////////////////////////////////////////////////////
exports.defineModule = function (path, file) {
'use strict';
var content;
var m;
var mc;
content = fs.read(file);
mc = internal.db._collection("_modules");
if (mc === null) {
mc = internal.db._create("_modules", { isSystem: true });
}
path = module.normalize(path);
m = mc.firstExample({ path: path });
if (m === null) {
mc.save({ path: path, content: content });
}
else {
mc.replace(m, { path: path, content: content });
}
};
////////////////////////////////////////////////////////////////////////////////
/// @brief guessContentType
////////////////////////////////////////////////////////////////////////////////
exports.guessContentType = function (filename) {
'use strict';
var re = /\.([a-zA-Z0-9]+)$/;
var match = re.exec(filename);
if (match !== null) {
var extension = match[1];
if (mimetypes.hasOwnProperty(extension)) {
var type = mimetypes[extension];
if (type[1]) {
// append charset
return type[0] + "; charset=utf-8";
}
return type[0];
}
// fall-through intentional
}
// default mimetype
return "text/plain; charset=utf-8";
};
////////////////////////////////////////////////////////////////////////////////
/// @brief normalizeURL
///
/// If @FA{path} starts with "." or "..", then it is a relative path.
/// Otherwise it is an absolute path. Normalizing will remove `//`,
/// `/./`, `/../` from the url - expect in the beginning, where it keeps
/// `../` and or at most one `./`.
///
/// If @FA{path} is empty, the url `./` will be returned.
////////////////////////////////////////////////////////////////////////////////
exports.normalizeURL = function (path) {
'use strict';
var i;
var n;
var p;
var q;
var r;
var x;
if (path === "") {
return "./";
}
p = path.split('/');
// relative path
if (p[0] === "." || p[0] === "..") {
r = p[0] + "/";
p.shift();
q = p;
}
// absolute path
else if (p[0] === "") {
r = "/";
p.shift();
q = p;
}
// assume that the path is relative
else {
r = "./";
q = p;
}
// normalize path
n = [];
for (i = 0; i < q.length; ++i) {
x = q[i];
if (x === "..") {
if (n.length === 0) {
if (r === "../") {
n.push(x);
}
else if (r === "./") {
r = "../";
}
else {
throw "cannot use '..' to escape top-level-directory";
}
}
else if (n[n.length - 1] === "..") {
n.push(x);
}
else {
n.pop();
}
}
else if (x !== "" && x !== ".") {
n.push(x);
}
}
return r + n.join('/');
};
////////////////////////////////////////////////////////////////////////////////
/// @brief inspect
////////////////////////////////////////////////////////////////////////////////
exports.inspect = internal.inspect;
////////////////////////////////////////////////////////////////////////////////
/// @brief output
///
/// In order to allow "capture" output to work, we cannot assigne the
/// function here.
////////////////////////////////////////////////////////////////////////////////
exports.output = function () {
'use strict';
internal.output.apply(internal.output, arguments);
};
////////////////////////////////////////////////////////////////////////////////
/// @brief print
////////////////////////////////////////////////////////////////////////////////
exports.print = internal.print;
////////////////////////////////////////////////////////////////////////////////
/// @brief printf
////////////////////////////////////////////////////////////////////////////////
exports.printf = internal.printf;
////////////////////////////////////////////////////////////////////////////////
/// @brief sprintf
////////////////////////////////////////////////////////////////////////////////
exports.sprintf = internal.sprintf;
////////////////////////////////////////////////////////////////////////////////
/// @brief printObject
////////////////////////////////////////////////////////////////////////////////
exports.printObject = internal.printObject;
////////////////////////////////////////////////////////////////////////////////
/// @brief 2D ASCII table printing
////////////////////////////////////////////////////////////////////////////////
exports.printTable = function (list, columns, options) {
'use strict';
options = options || { };
if (options.totalString === undefined) {
options.totalString = "%s document(s)\n";
}
var pad = '...';
var descriptions, matrix, col, what, j;
if (columns === undefined) {
what = list[0];
}
else if (Array.isArray(columns)) {
what = { };
columns.forEach(function (col) {
what[col] = null;
});
}
else {
what = columns;
}
j = 0;
descriptions = [ ];
matrix = [ [ ] ];
for (col in what) {
if (what.hasOwnProperty(col)) {
var fixedLength = null;
if (columns && columns.hasOwnProperty(col) && columns[col] > 0) {
fixedLength = columns[col] >= pad.length ? columns[col] : pad.length;
}
// header
var name = col;
// rename header?
if (options.hasOwnProperty("rename")) {
if (options.rename.hasOwnProperty(col)) {
name = options.rename[col];
}
}
descriptions.push({
id: col,
fixedLength: fixedLength,
length: fixedLength || name.length
});
matrix[0][j++] = name;
}
}
// determine values & max widths
list.forEach(function (row, i) {
matrix[i + 1] = [ ];
descriptions.forEach(function (col) {
if (row.hasOwnProperty(col.id)) {
var value;
if (options.prettyStrings && typeof row[col.id] === 'string') {
value = row[col.id];
}
else {
value = JSON.stringify(row[col.id]) || "";
}
matrix[i + 1].push(value);
if (value.length > col.length && ! col.fixedLength) {
col.length = Math.min(value.length, 100);
}
}
else {
// undefined
matrix[i + 1].push('');
}
});
});
var divider = function () {
var parts = [ ];
descriptions.forEach(function (desc) {
parts.push(exports.stringPadding('', desc.length, '-', 'r'));
});
if (options.framed) {
return '+-' + parts.join('-+-') + '-+\n';
}
return parts.join(' ') + '\n';
};
var compose = function () {
var result = '';
if (options.framed) {
result += divider();
}
matrix.forEach(function (row, i) {
var parts = [ ];
row.forEach(function (col, j) {
var len = descriptions[j].length, value = row[j];
if (value.length > len) {
value = value.substr(0, len - pad.length) + pad;
}
parts.push(exports.stringPadding(value, len, ' ', 'r'));
});
if (options.framed) {
result += '| ' + parts.join(' | ') + ' |\n';
}
else {
result += parts.join(' ') + '\n';
}
if (i === 0) {
result += divider();
}
});
result += divider();
if (! options.hideTotal) {
result += internal.sprintf(options.totalString, String(list.length));
}
return result;
};
if (! Array.isArray(list)) {
// not an array
return;
}
if (list.length === 0) {
exports.print(options.emptyString || "no document(s)");
}
else {
exports.print(compose());
}
};
////////////////////////////////////////////////////////////////////////////////
/// @brief stringPadding
////////////////////////////////////////////////////////////////////////////////
exports.stringPadding = function (str, len, pad, dir) {
'use strict';
// yes, this is more code than new Array(length).join(chr), but it makes jslint happy
function fill (length, chr) {
var result = '', i;
for (i = 0; i < length; ++i) {
result += chr;
}
return result;
}
if (typeof(len) === "undefined") {
len = 0;
}
if (typeof(pad) === "undefined") {
pad = ' ';
}
if (len + 1 >= str.length) {
switch (dir || "r"){
// LEFT
case 'l':
str = fill(len + 1 - str.length, pad) + str;
break;
// BOTH
case 'b':
var padlen = len - str.length;
var right = Math.ceil(padlen / 2);
var left = padlen - right;
str = fill(left + 1, pad) + str + fill(right + 1, pad);
break;
default:
str = str + fill(len + 1 - str.length, pad);
break;
}
}
return str;
};
////////////////////////////////////////////////////////////////////////////////
/// @brief throws an error in case a download failed
////////////////////////////////////////////////////////////////////////////////
exports.throwDownloadError = function (msg) {
'use strict';
throw new exports.ArangoError({
errorNum: exports.errors.ERROR_APPLICATION_DOWNLOAD_FAILED.code,
errorMessage: exports.errors.ERROR_APPLICATION_DOWNLOAD_FAILED.message + ': ' + String(msg)
});
};
////////////////////////////////////////////////////////////////////////////////
/// @brief throws an error in case of missing file
////////////////////////////////////////////////////////////////////////////////
exports.throwFileNotFound = function (msg) {
'use strict';
throw new exports.ArangoError({
errorNum: exports.errors.ERROR_FILE_NOT_FOUND.code,
errorMessage: exports.errors.ERROR_FILE_NOT_FOUND.message + ': ' + String(msg)
});
};
////////////////////////////////////////////////////////////////////////////////
/// @brief throws an error in case of a bad parameter
////////////////////////////////////////////////////////////////////////////////
exports.throwBadParameter = function (msg) {
'use strict';
throw new exports.ArangoError({
errorNum: exports.errors.ERROR_BAD_PARAMETER.code,
errorMessage: exports.errors.ERROR_BAD_PARAMETER.message + ': ' + String(msg)
});
};
////////////////////////////////////////////////////////////////////////////////
/// @brief checks parameter, throws an error if missing
////////////////////////////////////////////////////////////////////////////////
exports.checkParameter = function (usage, descs, vars) {
'use strict';
var i;
for (i = 0; i < descs.length; ++i) {
var desc = descs[i];
if (typeof vars[i] === "undefined") {
exports.throwBadParameter(desc[0] + " missing, usage: " + usage);
}
if (typeof vars[i] !== desc[1]) {
exports.throwBadParameter(desc[0] + " should be a '" + desc[1] + "', "
+ "not '" + (typeof vars[i]) + "'");
}
}
};
// -----------------------------------------------------------------------------
// --SECTION-- END-OF-FILE
// -----------------------------------------------------------------------------
// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @}\\|/\\*jslint"
// End: