webgme-engine
Version:
WebGME server and Client API without a GUI
729 lines (650 loc) • 26.7 kB
JavaScript
/*eslint-disable*/
/*
* Copyright (C) 2013 Vanderbilt University, All rights reserved.
*
* Author: Tamas Kecskes
*/
//TODO this is an outdated file, will be updated and maintained in the future.
console.error('ERROR: Outdated source file have to be updated');
process.exit(1);
if (typeof define !== "function") {
var requirejs = require("requirejs");
requirejs.config({
nodeRequire: require,
baseUrl: __dirname + "/.."
});
requirejs(["common/util/common", "common/util/assert", "common/core/tasync", "bin/serialize_to_xml"], function (COMMON, ASSERT, TASYNC, serializer) {
"use strict";
TASYNC.trycatch(main, function (error) {
console.log(error.trace || error.stack);
COMMON.setProgress(null);
COMMON.closeProject();
COMMON.closeDatabase();
});
var _commit = null,
_startHash = null,
_branch = null,
_projectName = null,
_outFile = null;
function main() {
var args = COMMON.getParameters(null);
if (args.length < 1 || COMMON.getParameters("help") !== null) {
console.log("Usage: node parse_xme.js <xmlfile> [options]");
console.log("");
console.log("Parses a GME xme file and stores it int a WEBGME database. Possible options:");
console.log("");
console.log(" -mongo [database [host [port]]]\topens a mongo database");
console.log(" -proj <project>\t\t\tselects the given project");
console.log(" -branch <branch>\t\t\tthe branch to serialize");
console.log(" -hash <hash>\t\t\t\tthe root hash to serialize");
console.log(" -commit <hash>\t\t\tthe commit hash to serialize");
console.log(" -help\t\t\t\t\tprints out this help message");
console.log("");
return;
}
console.log('starting serialization', new Date());
_outFile = args[0];
_branch = COMMON.getParameters("branch");
if (_branch) {
_branch = _branch[0] || "parsed";
}
_startHash = COMMON.getParameters("hash");
if (_startHash) {
_startHash = _startHash[0];
}
_projectName = COMMON.getParameters("proj");
if (_projectName) {
_projectName = _projectName[0];
}
_commit = COMMON.getParameters('commit');
if (_commit) {
_commit = _commit[0];
}
var done = TASYNC.call(COMMON.openDatabase);
done = TASYNC.call(COMMON.openProject, done);
var core = TASYNC.call(COMMON.getCore, done);
if (!_startHash) {
if (_branch) {
_startHash = TASYNC.call(getRootHashOfBranch, _branch, done);
TASYNC.call(settingCommitHashOfBranch, _branch, done);
} else if (_commit) {
_startHash = TASYNC.call(getRootHashOfCommit, _commit, done);
} else {
done = TASYNC.call(COMMON.closeProject, done);
done = TASYNC.call(COMMON.closeDatabase, done);
return done;
}
}
done = TASYNC.call(serializer, core, _startHash, _outFile);
done = TASYNC.call(function (object) {
console.log('the root after serializing and normalizing:', object);
console.log('the commit hash what we modified:', _commit);
if (_commit) {
//we should make a commit
var newCommit = makeCommit(_outFile, object, _commit);
if (_branch) {
//we also should update the branch
return TASYNC.call(writeBranch, newCommit);
} else {
return null;
}
} else {
return null;
}
}, done);
done = TASYNC.call(COMMON.closeProject, done);
done = TASYNC.call(COMMON.closeDatabase, done);
done = TASYNC.call(function () {
console.log('finished', new Date());
}, done);
return done;
}
function makeCommit(xmlfile, rootHash, commitHash) {
var project = COMMON.getProject();
return project.makeCommit([commitHash], rootHash, "normalizing during serialization to " + xmlfile);
}
function getRootHashOfBranch(branch) {
var project = COMMON.getProject();
var commitHash = project.getBranchHash(branch, null);
var done = TASYNC.call(project.loadObject, commitHash);
done = TASYNC.call(function (object) {
console.log('getRootHashOfBranch', branch, object.root);
_branch = branch;
return object.root;
}, done);
return done;
}
function settingCommitHashOfBranch(branch) {
var project = COMMON.getProject();
var cHash = project.getBranchHash(branch, null);
return TASYNC.call(function (hash) {
_commit = hash;
return hash;
}, cHash);
}
function getRootHashOfCommit(commit) {
var project = COMMON.getProject();
return TASYNC.call(function (object) {
console.log('getRootHashOfCommit', commit, object.root);
return object.root;
}, TASYNC.call(project.loadObject, commit));
}
function writeBranch(hash) {
var project = COMMON.getProject();
var done = project.setBranchHash(_branch, _commit, hash);
return TASYNC.call(function () {
console.log("Commit " + hash + " written to branch " + _branch);
}, done);
}
});
}
define(["common/util/assert", "common/core/tasync", "common/util/common", 'fs', 'common/storage/commit', 'common/storage/cache', 'common/storage/mongo'], function (ASSERT, TASYNC, COMMON, fs, Commit, Cache, Mongo) {
// attributes reserved for easier JSON to XML conversion
// _type : show the type of the XML tag
// _attr : object which contain all the attributes of the XML node
// _empty : true/false show if the object has inner content or not (if not it will be written in <tag/> form
// _children : [] - ordered list of inner XML objects
// _string : if this tag exists then the inner part of the XML object will be this string
var _nodes = [];
var _prefix = "*&*";
var _idCounter = {
atom: 0,
model: 0,
connection: 0,
folder: 0
};
//XML object attributes
var registry = {
guid: "guid",
created: "cdate",
modified: "mdate",
version: "version",
metaname: "metaname",
metaguid: "metaguid",
metaversion: "metaversion",
id: "id",
relid: "relid",
kind: "kind",
role: "role",
isinstance: "isinstance",
isprimary: "isprimary"
};
var webOnly = ['position', 'isPort', 'isConnection', 'metameta', 'author', 'comment', 'refPortCount', 'decorator', 'lineStyle'];
function stringToXMLString(text) {
text = text.replace(/\&/g, '&');
text = text.replace(/\"/g, '"');
text = text.replace(/\'/g, ''');
text = text.replace(/</g, '<');
text = text.replace(/>/g, '>');
return text;
}
function initJsonObject(gmeNode) {
var initJ = {};
initJ._type = theCore.getRegistry(gmeNode, 'metameta');
initJ._empty = false;
initJ._children = [];
initJ._attr = {};
//TODO properly adding new guid stuff
initJ._attr["guid"] = "{" + theCore.getGuid(gmeNode) + "}";
for (var i in registry) {
var value = theCore.getRegistry(gmeNode, i);
if (value !== undefined && value !== null) {
initJ._attr[registry[i]] = value;
}
}
//now we should add the children to the node
//first come the name
//then the registry nodes
//then the attributes
//name
initJ._children.push({
_type: "name",
_empty: false,
_string: stringToXMLString(theCore.getAttribute(gmeNode, 'name'))
});
//comment and author
if (initJ._type === 'project') {
initJ._children.push({
_type: 'comment',
_empty: false,
_string: stringToXMLString(theCore.getRegistry(gmeNode, 'comment') || "")
});
initJ._children.push({
_type: 'author',
_empty: false,
_string: stringToXMLString(theCore.getRegistry(gmeNode, 'author') || "")
});
}
//regnodes
initJ._children = initJ._children.concat(createRegistryObject(gmeNode));
//attributes
var attrNames = theCore.getAttributeNames(gmeNode);
for (i = 0; i < attrNames.length; i++) {
if (attrNames[i] !== 'name') {
initJ._children.push({
_type: "attribute",
_empty: false,
_attr: {
kind: attrNames[i]
},
_children: [
{
_type: "value",
_empty: false,
_string: stringToXMLString(theCore.getAttribute(gmeNode, attrNames[i]))
}
]
});
}
}
return initJ;
}
function registryToChildrenArray(registryObj) {
ASSERT(typeof registryObj === 'object');
var regJSON = [];
for (var i in registryObj) {
if (i !== '_value') {
var length = regJSON.push({
_type: "regnode",
_empty: false,
_attr: {
name: i
},
_children: []
});
var valueString = "";
if (!(registryObj[i]._value === null || registryObj[i]._value === undefined)) {
if (typeof registryObj[i]._value === "string") {
valueString = registryObj[i]._value;
} else {
valueString = JSON.stringify(registryObj[i]._value);
}
}
regJSON[length - 1]._children = registryToChildrenArray(registryObj[i]);
regJSON[length - 1]._children.unshift({
_type: "value",
_empty: false,
_string: valueString
});
}
}
return regJSON;
}
function createRegistryObject(gmeNode) {
var regNames = theCore.getRegistryNames(gmeNode);
var regObject = {};
for (i = 0; i < regNames.length; i++) {
if ((registry[regNames[i]] === undefined || registry[regNames[i]] === null) && webOnly.indexOf(regNames[i]) === -1) {
var nameArray = regNames[i].split('/');
var tObj = regObject;
for (var j = 0; j < nameArray.length; j++) {
if (tObj[nameArray[j]]) {
tObj = tObj[nameArray[j]];
} else {
tObj[nameArray[j]] = {};
tObj = tObj[nameArray[j]];
}
}
tObj._value = theCore.getRegistry(gmeNode, regNames[i]);
}
}
//no we should convert into the correct JSON form
var regChildren = registryToChildrenArray(regObject);
return regChildren;
}
function fullJsonToString(jsonObject, indent) {
if (jsonObject === null) {
return "";
}
ASSERT(jsonObject._type);
var outString = indent;
//starting with the type of the object
outString += "<" + jsonObject._type;
//adding XML attributes
if (jsonObject._attr) {
for (var i in jsonObject._attr) {
outString += " " + i + "=\"" + jsonObject._attr[i] + "\"";
}
}
//checking _empty
if (jsonObject._empty) {
outString += "/>\n";
return outString;
}
//checking _string
if (jsonObject._string !== undefined && jsonObject._string !== null) {
outString += ">" + jsonObject._string + "</" + jsonObject._type + ">\n";
return outString;
}
outString += ">\n";
//creating children texts
if (jsonObject._children) {
ASSERT(jsonObject._children.length);
for (i = 0; i < jsonObject._children.length; i++) {
outString += fullJsonToString(jsonObject._children[i], indent + " ");
}
}
outString += indent + "</" + jsonObject._type + ">\n";
return outString;
}
function partialJsonToString(jsonObject, indent) {
ASSERT(jsonObject._type);
var outString = indent;
//starting with the type of the object
outString += "<" + jsonObject._type;
//adding XML attributes
if (jsonObject._attr) {
for (var i in jsonObject._attr) {
outString += " " + i + "=\"" + jsonObject._attr[i] + "\"";
}
}
//checking _empty
if (jsonObject._empty) {
outString += "/>\n";
return outString;
}
//checking _string
if (jsonObject._string !== undefined && jsonObject._string !== null) {
outString += ">" + jsonObject._string + "</" + jsonObject._type + ">\n";
return outString;
}
outString += ">\n";
//creating children texts
if (jsonObject._children) {
ASSERT(jsonObject._children.length);
for (i = 0; i < jsonObject._children.length; i++) {
outString += fullJsonToString(jsonObject._children[i], indent + " ");
}
}
//in this version we are not closing the object
//outString += indent+"</"+jsonObject._type+">\n";
return outString;
}
function closeJsonToString(jsonObject, indent) {
return indent + "</" + jsonObject._type + ">\n";
}
function createXMLStart() {
return "xml version=\"1.0\" encoding=\"UTF-8\"?>\n theIds[idArr[1]].max) {
theIds[idArr[1]].max = Number('0x' + idArr[2]);
}
break;
}
}
function relIdScanningSync(objectArray) {
var relIds = {};
var generate = [];
var max = 0;
for (var i = 0; i < objectArray.length; i++) {
var rId = theCore.getRegistry(objectArray[i], 'relid');
var wId = theCore.getRelid(objectArray[i]);
if (rId !== null && rId !== undefined) {
if (Number(rId) > max) {
max = Number(rId);
}
if (Number(rId) === Number(wId)) {
//original node
if (relIds[rId]) {
generate.push(relIds[rId]);
}
relIds[rId] = i;
} else {
if (relIds[rId]) {
generate.push(i);
} else {
relIds[rId] = i;
}
}
}
}
for (var i = 0; i < generate.length; i++) {
theCore.setRegistry(objectArray[generate[i]], 'relid', '0x' + (++max).toString(16));
}
}
function idChecking(object) {
var children = theCore.loadChildren(object);
objectIdScanningSync(object);
return TASYNC.call(function (objectArray) {
relIdScanningSync(objectArray);
var done;
for (var i = 0; i < objectArray.length; i++) {
done = TASYNC.call(idChecking, objectArray[i], done);
}
return done;
}, children);
}
function padding(length) {
var pad = '';
for (var i = 0; i < length; i++) {
pad += '0';
}
return pad;
}
function idReallocationSync(object) {
var needId = false;
var idType = "";
switch (theCore.getRegistry(object, 'metameta')) {
case 'folder':
needId = true;
idType = '006a';
break;
case 'atom':
needId = true;
idType = '0066';
break;
case 'model':
needId = true;
idType = '0065';
break;
case 'connection':
needId = true;
idType = '0068';
break;
case 'reference':
needId = true;
idType = '0067';
break;
case 'set':
needId = true;
idType = '0069';
break;
}
if (needId) {
if (!theIds[idType].paths[theCore.getPath(object)]) {
//we need to allocate a new id for the node
var maxIdEnd = (++theIds[idType].max).toString(16);
var newId = 'id-' + idType + '-' + padding(8 - maxIdEnd.length) + maxIdEnd;
theCore.setRegistry(object, 'id', newId);
//these nodes needs new GUIDs as well, so let's generate them
var newGuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
theCore.setRegistry(object, 'guid', '{' + newGuid + '}');
}
}
}
function persist(root) {
console.log("Waiting for objects to be saved ...");
var done = theCore.persist(root);
var hash = theCore.getHash(root);
return TASYNC.join(hash, done);
}
var theCore;
var theNodes = [];
var thePaths = [];
var theString = "";
var theIds = {
'0065': {max: 0, ids: {}, paths: {}},
'0066': {max: 0, ids: {}, paths: {}},
'0067': {max: 0, ids: {}, paths: {}},
'0068': {max: 0, ids: {}, paths: {}},
'0069': {max: 0, ids: {}, paths: {}},
'006a': {max: 0, ids: {}, paths: {}}
};
function getChildren(object, indent) {
idReallocationSync(object);
var children = theCore.loadChildren(object);
//object tasks pre children loading
switch (theCore.getRegistry(object, 'metameta')) {
case 'connection':
var jsonObject = connectionToJson(object);
var done = TASYNC.call(function (obj) {
theString += fullJsonToString(obj, indent);
return;
}, jsonObject);
return done;
case 'refport':
//we deal these kind of nodes during connection handling
return;
case 'reference':
var pointerNames = theCore.getPointerNames(object);
var ref = null;
if (pointerNames.indexOf('target') !== -1) {
ref = theCore.loadPointer(object, 'target');
}
var jsonObject = initJsonObject(object);
var done = TASYNC.call(function (objectArray, referred) {
if (referred !== null) {
jsonObject._attr['referred'] = theCore.getRegistry(referred, 'id');
}
theString += partialJsonToString(jsonObject, indent);
var mydone;
for (var i = 0; i < objectArray.length; i++) {
theNodes.push(objectArray[i]);
thePaths.push(theCore.getPath(objectArray[i]));
mydone = TASYNC.call(getChildren, objectArray[i], indent + " ", mydone);
}
return mydone;
}, children, ref);
//post-children tasks
done = TASYNC.call(function () {
theString += closeJsonToString(jsonObject, indent);
}, done);
return done;
default:
var jsonObject = initJsonObject(object);
theString += partialJsonToString(jsonObject, indent);
//handling children
var done = TASYNC.call(function (objectArray) {
var mydone;
for (var i = 0; i < objectArray.length; i++) {
theNodes.push(objectArray[i]);
thePaths.push(theCore.getPath(objectArray[i]));
mydone = TASYNC.call(getChildren, objectArray[i], indent + " ", mydone);
}
return mydone;
}, children);
//post-children tasks
done = TASYNC.call(function () {
theString += closeJsonToString(jsonObject, indent);
}, done);
return done;
}
}
function serialize(core, hash, outPath) {
theCore = core;
var root = core.loadRoot(hash);
theString += createXMLStart();
var done = TASYNC.call(idChecking, root);
done = TASYNC.call(getChildren, root, " ", done);
done = TASYNC.call(function () {
//console.log(thePaths);
fs.writeFileSync(outPath, theString);
return;
}, done);
done = TASYNC.call(persist, root, done);
return done;
}
//return TASYNC.wrap(serialize);
return serialize;
});