initial commit
This commit is contained in:
commit
4b60ece582
327 changed files with 28286 additions and 0 deletions
0
libjs/CMakeLists.txt
Normal file
0
libjs/CMakeLists.txt
Normal file
0
libjs/polymorph/CMakeLists.txt
Normal file
0
libjs/polymorph/CMakeLists.txt
Normal file
76
libjs/polymorph/dependency.js
Normal file
76
libjs/polymorph/dependency.js
Normal file
|
@ -0,0 +1,76 @@
|
|||
"use strict";
|
||||
|
||||
var Dependency = function(options) {
|
||||
if (!Dependency.configured) {
|
||||
throw new Error("Unable to create a dependency without static variables configuration, use Dependency.configure first");
|
||||
}
|
||||
this._string = options.string;
|
||||
this._text = options.text;
|
||||
|
||||
this._parse();
|
||||
}
|
||||
|
||||
Dependency.configured = false;
|
||||
Dependency.configure = function(libDir, target) {
|
||||
this.libDir = libDir;
|
||||
this.target = target;
|
||||
var tPath = target.replace(libDir, "lib");
|
||||
tPath = tPath.replace(".js", "");
|
||||
tPath = tPath.split("/");
|
||||
tPath.pop();
|
||||
this.path = tPath;
|
||||
this.configured = true;
|
||||
};
|
||||
|
||||
Dependency.prototype.log = function() {
|
||||
console.log("---------------------------------");
|
||||
console.log("Found string: " + this._string);
|
||||
console.log("Captured dependency: " + this._text);
|
||||
console.log("Output dependency: " + this._name);
|
||||
console.log("Lib is: " + Dependency.libDir);
|
||||
console.log("Target is: " + Dependency.target);
|
||||
console.log("---------------------------------");
|
||||
}
|
||||
|
||||
Dependency.prototype._parse = function() {
|
||||
var fl = this._text[0];
|
||||
var dArr = this._text.split("/");
|
||||
|
||||
if (fl !== ".") {
|
||||
this._name = "lib/" + this._text + "/index";
|
||||
} else {
|
||||
var summ = Dependency.path.slice();
|
||||
this._name = "";
|
||||
|
||||
for (var i = 0; i < dArr.length; ++i) {
|
||||
var hop = dArr[i];
|
||||
switch (hop) {
|
||||
case ".":
|
||||
case "":
|
||||
break;
|
||||
case "..":
|
||||
summ.pop();
|
||||
break
|
||||
default:
|
||||
summ.push(hop);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (var j = 0; j < summ.length; ++j) {
|
||||
if (j !== 0) {
|
||||
this._name += "/"
|
||||
}
|
||||
this._name += summ[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Dependency.prototype.modify = function(line) {
|
||||
return line.replace(this._text, this._name);
|
||||
}
|
||||
Dependency.prototype.toString = function() {
|
||||
return this._name;
|
||||
}
|
||||
|
||||
module.exports = Dependency;
|
51
libjs/polymorph/depresolver.js
Normal file
51
libjs/polymorph/depresolver.js
Normal file
|
@ -0,0 +1,51 @@
|
|||
"use strict";
|
||||
var Dependency = require("./dependency");
|
||||
|
||||
var DepResolver = function(options) {
|
||||
Dependency.configure(options.libDir, options.target)
|
||||
|
||||
this._reg1 = /(?:require\s*\((?:\"(.*)\"|\'(.*)\')\)[^;,]*(?:[;,]|$))(?!\s*\/\/not\sa\sd)/g;
|
||||
this._reg2 = /(?:\"(.+)\"|\'(.+)\'),{0,1}(?=\s*\/\/resolve as d)/g;
|
||||
}
|
||||
|
||||
DepResolver.prototype.resolve = function(lines) {
|
||||
var regres;
|
||||
var dep;
|
||||
var header = [];
|
||||
var dependencies = [];
|
||||
dependencies.push("var defineArray = [];\n");
|
||||
|
||||
for (var i = 0; i < lines.length; ++i) {
|
||||
var line = lines[i];
|
||||
var found = false;
|
||||
while((regres = this._reg1.exec(line)) !== null) {
|
||||
dep = new Dependency({
|
||||
string: regres[0],
|
||||
text: regres[1]
|
||||
});
|
||||
lines[i] = dep.modify(line);
|
||||
dependencies.push("defineArray.push(\"" + dep.toString() + "\");");
|
||||
found = true;
|
||||
}
|
||||
if (!found) {
|
||||
while((regres = this._reg2.exec(line)) !== null) {
|
||||
dep = new Dependency({
|
||||
string: regres[0],
|
||||
text: regres[1]
|
||||
});
|
||||
|
||||
lines[i] = dep.modify(line);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
header.push("define(moduleName, defineArray, function() {");
|
||||
|
||||
return {
|
||||
header: header,
|
||||
dependencies: dependencies,
|
||||
bottom: "});"
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = DepResolver;
|
75
libjs/polymorph/index.js
Normal file
75
libjs/polymorph/index.js
Normal file
|
@ -0,0 +1,75 @@
|
|||
"use strict";
|
||||
var fs = require("fs");
|
||||
var DepResolver = require("./depresolver");
|
||||
var pathCheck = require("./pathCheck");
|
||||
|
||||
var path = process.argv[2];
|
||||
var target = process.argv[3];
|
||||
var moduleName = process.argv[4];
|
||||
var env = process.argv[5];
|
||||
var libDir = process.argv[6];
|
||||
|
||||
var isNode = true;
|
||||
if (env === "browser") {
|
||||
isNode = false;
|
||||
}
|
||||
|
||||
var dr = new DepResolver({
|
||||
target: target,
|
||||
libDir: libDir
|
||||
});
|
||||
|
||||
fs.readFile(path, function(err, buffer) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
console._stdout.write(String.fromCharCode(27) + "[1;32m");
|
||||
console._stdout.write("polymorph: ");
|
||||
console._stdout.write(String.fromCharCode(27) + "[0m");
|
||||
console._stdout.write("parsing " + moduleName + " for " + env);
|
||||
console._stdout.write("\n");
|
||||
|
||||
var file = buffer.toString();
|
||||
var output = "";
|
||||
if (!isNode) {
|
||||
file = file.replace(/module.exports[\s]*=/g, "return");
|
||||
file = file.replace(/\"use\sstrict\";/g, "");
|
||||
var lines = file.split("\n");
|
||||
|
||||
output = "\"use strict\";\n" +
|
||||
"(function(global) {\n" +
|
||||
" var moduleName = \""+moduleName+"\"\n";
|
||||
|
||||
var add = dr.resolve(lines);
|
||||
|
||||
for (var i = 0; i < add.dependencies.length; ++i) {
|
||||
output += " " + add.dependencies[i] + "\n";
|
||||
}
|
||||
|
||||
output += "\n";
|
||||
|
||||
for (var i = 0; i < add.header.length; ++i) {
|
||||
output += " " + add.header[i] + "\n";
|
||||
}
|
||||
|
||||
for (var i = 0; i < lines.length; ++i) {
|
||||
var line = lines[i];
|
||||
output += " " + line + "\n";
|
||||
}
|
||||
|
||||
output += " " + add.bottom + "\n";
|
||||
output += "})(window);";
|
||||
} else {
|
||||
output = file;
|
||||
}
|
||||
var p = target.split("/");
|
||||
p[1] = "/" + p[1]
|
||||
pathCheck(p.slice(1, -1), function(err) {
|
||||
if (err) throw err;
|
||||
fs.writeFile(target, output, function(err) {
|
||||
if (err) throw err;
|
||||
process.exit(0);
|
||||
});
|
||||
})
|
||||
})
|
||||
|
34
libjs/polymorph/pathCheck.js
Normal file
34
libjs/polymorph/pathCheck.js
Normal file
|
@ -0,0 +1,34 @@
|
|||
"use strict";
|
||||
const fs = require("fs");
|
||||
|
||||
function pathCheck(/*Array*/path, cb) {
|
||||
fs.access(path[0], function(err) {
|
||||
if (err) {
|
||||
if (err.code === 'ENOENT') {
|
||||
fs.mkdir(path[0], function() {
|
||||
if (path.length === 1) {
|
||||
cb();
|
||||
} else {
|
||||
let nPath = path.slice();
|
||||
let out = nPath.splice(1, 1);
|
||||
nPath[0] += "/" + out[0];
|
||||
pathCheck(nPath, cb);
|
||||
}
|
||||
})
|
||||
} else {
|
||||
cb(err);
|
||||
}
|
||||
} else {
|
||||
if (path.length === 1) {
|
||||
cb();
|
||||
} else {
|
||||
let nPath = path.slice();
|
||||
let out = nPath.splice(1, 1);
|
||||
nPath[0] += "/" + out[0];
|
||||
pathCheck(nPath, cb);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = pathCheck;
|
5
libjs/utils/CMakeLists.txt
Normal file
5
libjs/utils/CMakeLists.txt
Normal file
|
@ -0,0 +1,5 @@
|
|||
cmake_minimum_required(VERSION 2.8.12)
|
||||
|
||||
configure_file(class.js class.js)
|
||||
configure_file(subscribable.js subscribable.js)
|
||||
configure_file(globalMethods.js globalMethods.js)
|
52
libjs/utils/class.js
Normal file
52
libjs/utils/class.js
Normal file
|
@ -0,0 +1,52 @@
|
|||
"use strict";
|
||||
|
||||
var Class = function() {};
|
||||
|
||||
Class.inherit = function(proto) {
|
||||
var superClass = this;
|
||||
var Base = function() {};
|
||||
var subclass = proto && (proto.constructor !== Object) ? proto.constructor : function() {
|
||||
superClass.apply(this, arguments)
|
||||
};
|
||||
|
||||
Base.prototype = this.prototype;
|
||||
var fn = new Base();
|
||||
|
||||
for (var key in proto) {
|
||||
if (proto.hasOwnProperty(key)) {
|
||||
fn[key] = proto[key];
|
||||
}
|
||||
}
|
||||
for (var method in this) {
|
||||
if (this.hasOwnProperty(method)) {
|
||||
subclass[method] = this[method];
|
||||
}
|
||||
}
|
||||
|
||||
fn.constructor = subclass;
|
||||
subclass.prototype = subclass.fn = fn;
|
||||
|
||||
return subclass;
|
||||
}
|
||||
|
||||
module.exports = Class.inherit({
|
||||
className: "Class",
|
||||
constructor: function() {
|
||||
if (!(this instanceof Class)) {
|
||||
throw new SyntaxError("You didn't call \"new\" operator");
|
||||
}
|
||||
|
||||
Class.call(this);
|
||||
this._uncyclic = [];
|
||||
},
|
||||
destructor: function() {
|
||||
for (var i = 0; i < this._uncyclic.length; ++i) {
|
||||
this._uncyclic[i].call(this);
|
||||
}
|
||||
|
||||
for (var key in this) {
|
||||
this[key] = undefined;
|
||||
delete this[key];
|
||||
}
|
||||
}
|
||||
});
|
69
libjs/utils/globalMethods.js
Normal file
69
libjs/utils/globalMethods.js
Normal file
|
@ -0,0 +1,69 @@
|
|||
"use strict";
|
||||
|
||||
global.W = {
|
||||
extend: function () {
|
||||
var lTarget = arguments[0] || {};
|
||||
var lIndex = 1;
|
||||
var lLength = arguments.length;
|
||||
var lDeep = false;
|
||||
var lOptions, lName, lSrc, lCopy, lCopyIsArray, lClone;
|
||||
|
||||
// Handle a deep copy situation
|
||||
if (typeof lTarget === "boolean") {
|
||||
lDeep = lTarget;
|
||||
lTarget = arguments[1] || {};
|
||||
// skip the boolean and the target
|
||||
lIndex = 2;
|
||||
}
|
||||
|
||||
// Handle case when target is a string or something (possible in deep
|
||||
// copy)
|
||||
if (typeof lTarget !== "object" && typeof lTarget != "function") {
|
||||
lTarget = {};
|
||||
}
|
||||
|
||||
if (lLength === lIndex) {
|
||||
lTarget = this;
|
||||
--lIndex;
|
||||
}
|
||||
|
||||
for (; lIndex < lLength; lIndex++) {
|
||||
// Only deal with non-null/undefined values
|
||||
if ((lOptions = arguments[lIndex]) != undefined) {
|
||||
// Extend the base object
|
||||
for (lName in lOptions) {
|
||||
lSrc = lTarget[lName];
|
||||
lCopy = lOptions[lName];
|
||||
|
||||
// Prevent never-ending loop
|
||||
if (lTarget === lCopy) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Recurse if we're merging plain objects or arrays
|
||||
if (lDeep && lCopy && (Object.isObject(lCopy) || (lCopyIsArray = Array.isArray(lCopy)))) {
|
||||
if (lCopyIsArray) {
|
||||
lCopyIsArray = false;
|
||||
lClone = lSrc && Array.isArray(lSrc) ? lSrc : [];
|
||||
|
||||
} else {
|
||||
lClone = lSrc && Object.isObject(lSrc) ? lSrc : {};
|
||||
}
|
||||
|
||||
// Never move original objects, clone them
|
||||
lTarget[lName] = Object.extend(lDeep, lClone, lCopy);
|
||||
|
||||
// Don't bring in undefined values
|
||||
} else {
|
||||
if (lCopy !== undefined) {
|
||||
lTarget[lName] = lCopy;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return the modified object
|
||||
return lTarget;
|
||||
}
|
||||
};
|
94
libjs/utils/subscribable.js
Normal file
94
libjs/utils/subscribable.js
Normal file
|
@ -0,0 +1,94 @@
|
|||
"use strict";
|
||||
|
||||
var Class = require("./class");
|
||||
|
||||
var Subscribable = Class.inherit({
|
||||
"className": "Subscribable",
|
||||
"constructor": function() {
|
||||
Class.fn.constructor.call(this);
|
||||
|
||||
this._events = Object.create(null);
|
||||
},
|
||||
"destructor": function() {
|
||||
this.off();
|
||||
Class.fn.destructor.call(this);
|
||||
},
|
||||
|
||||
"on": function(name, handler, context) {
|
||||
var handlers = this._events[name];
|
||||
|
||||
if (typeof name !== "string") {
|
||||
throw new Error("Name of event is mandatory");
|
||||
}
|
||||
|
||||
if (!(handler instanceof Function)) {
|
||||
throw new Error("Handler of event is mandatory");
|
||||
}
|
||||
|
||||
if (!handlers) {
|
||||
handlers = [];
|
||||
this._events[name] = handlers;
|
||||
}
|
||||
|
||||
handlers.push({
|
||||
handler: handler,
|
||||
context: context || this,
|
||||
once: false
|
||||
});
|
||||
},
|
||||
"one": function(name) {
|
||||
Subscribable.fn.on.apply(this, arguments);
|
||||
this._events[name][this._events[name].length - 1].once = true;
|
||||
},
|
||||
"off": function(name, handler, context) {
|
||||
|
||||
if (typeof name === "string") {
|
||||
if (this._events[name]) {
|
||||
if (handler instanceof Function) {
|
||||
var handlers = this._events[name];
|
||||
for (var i = handlers.length - 1; i >= 0 ; --i) {
|
||||
if (handlers[i].handler === handler) {
|
||||
if (context) {
|
||||
if (handlers[i].context === context) {
|
||||
handlers.splice(i, 1);
|
||||
}
|
||||
} else {
|
||||
handlers.splice(i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
delete this._events[name];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this._events = Object.create(null);
|
||||
}
|
||||
},
|
||||
"trigger": function() {
|
||||
var args = [].slice.call(arguments);
|
||||
if (args.length === 0) {
|
||||
throw new Error("Name of event is mandatory");
|
||||
}
|
||||
var answer = false;
|
||||
var name = args.shift();
|
||||
var handlers = this._events[name];
|
||||
if (handlers) {
|
||||
for (var i = 0; i < handlers.length; ++i) {
|
||||
var handle = handlers[i];
|
||||
answer = handle.handler.apply(handle.context, args);
|
||||
if (handle.once) {
|
||||
handlers.splice(i, 1);
|
||||
--i;
|
||||
}
|
||||
|
||||
if (answer === false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Subscribable;
|
7
libjs/wContainer/CMakeLists.txt
Normal file
7
libjs/wContainer/CMakeLists.txt
Normal file
|
@ -0,0 +1,7 @@
|
|||
cmake_minimum_required(VERSION 2.8.12)
|
||||
|
||||
configure_file(abstractpair.js abstractpair.js)
|
||||
configure_file(abstractmap.js abstractmap.js)
|
||||
configure_file(abstractlist.js abstractlist.js)
|
||||
configure_file(abstractorder.js abstractorder.js)
|
||||
configure_file(abstractset.js abstractset.js)
|
204
libjs/wContainer/abstractlist.js
Normal file
204
libjs/wContainer/abstractlist.js
Normal file
|
@ -0,0 +1,204 @@
|
|||
"use strict";
|
||||
var Class = require("../utils/class");
|
||||
|
||||
var AbstractList = Class.inherit({
|
||||
"className": "AbstractList",
|
||||
"constructor": function(owning) {
|
||||
Class.fn.constructor.call(this);
|
||||
|
||||
if (!this.constructor.dataType) {
|
||||
throw new Error("An attempt to instantiate a list without declared member type");
|
||||
}
|
||||
|
||||
this._owning = owning !== false;
|
||||
this._begin = new ListNode(this);
|
||||
this._end = this._begin;
|
||||
this._size = 0;
|
||||
},
|
||||
"destructor": function() {
|
||||
this.clear();
|
||||
|
||||
Class.fn.destructor.call(this);
|
||||
},
|
||||
"begin": function() {
|
||||
return new ListIterator(this._begin);
|
||||
},
|
||||
"clear": function() {
|
||||
var node = this._begin;
|
||||
while (node !== this._end) {
|
||||
node = node._next;
|
||||
node._prev.destructor();
|
||||
}
|
||||
node._prev = null;
|
||||
|
||||
this._begin = node;
|
||||
this._size = 0;
|
||||
},
|
||||
"end": function() {
|
||||
return new ListIterator(this._end);
|
||||
},
|
||||
"erase": function(begin, end) {
|
||||
if (end === undefined) {
|
||||
end = begin.clone();
|
||||
end["++"]();
|
||||
}
|
||||
|
||||
if (begin._node === this._begin) {
|
||||
this._begin = end._node;
|
||||
end._node._prev = null;
|
||||
} else {
|
||||
begin._node._prev._next = end._node;
|
||||
end._node._prev = begin._node._prev;
|
||||
}
|
||||
|
||||
while(!begin["=="](end)) {
|
||||
|
||||
var node = begin._node;
|
||||
begin["++"]();
|
||||
--this._size;
|
||||
node.destructor();
|
||||
}
|
||||
},
|
||||
"insert": function(data, target) {
|
||||
if (target._node._list !== this) {
|
||||
throw new Error("An attempt to insert to list using iterator from another container");
|
||||
}
|
||||
if (!(data instanceof this.constructor.dataType)) {
|
||||
throw new Error("An attempt to insert wrong data type into list");
|
||||
}
|
||||
var node = new ListNode(this);
|
||||
node._data = data;
|
||||
|
||||
if (target._node === this._begin) {
|
||||
this._begin = node;
|
||||
} else {
|
||||
var bItr = target.clone();
|
||||
bItr["--"]();
|
||||
var before = bItr._node;
|
||||
before._next = node;
|
||||
node._prev = before;
|
||||
bItr.destructor();
|
||||
}
|
||||
|
||||
node._next = target._node;
|
||||
target._node._prev = node;
|
||||
|
||||
++this._size;
|
||||
},
|
||||
"pop_back": function() {
|
||||
if (this._begin === this._end) {
|
||||
throw new Error("An attempt to pop from empty list");
|
||||
}
|
||||
var node = this._end._prev;
|
||||
|
||||
if (node === this._begin) {
|
||||
this._begin = this._end;
|
||||
this._end._prev = null;
|
||||
} else {
|
||||
node._prev._next = this._end;
|
||||
this._end._prev = node._prev;
|
||||
}
|
||||
node.destructor();
|
||||
|
||||
--this._size;
|
||||
},
|
||||
"push_back": function(data) {
|
||||
if (!(data instanceof this.constructor.dataType)) {
|
||||
throw new Error("An attempt to insert wrong data type into list");
|
||||
}
|
||||
|
||||
var node = new ListNode(this);
|
||||
node._data = data;
|
||||
if (this._size === 0) {
|
||||
this._begin = node;
|
||||
} else {
|
||||
this._end._prev._next = node;
|
||||
node._prev = this._end._prev;
|
||||
}
|
||||
|
||||
node._next = this._end;
|
||||
this._end._prev = node;
|
||||
|
||||
this._size++;
|
||||
},
|
||||
"size": function() {
|
||||
return this._size;
|
||||
}
|
||||
});
|
||||
|
||||
var ListNode = Class.inherit({
|
||||
"className": "ListNode",
|
||||
"constructor": function(list) {
|
||||
Class.fn.constructor.call(this);
|
||||
|
||||
this._list = list
|
||||
this._data = null;
|
||||
this._next = null;
|
||||
this._prev = null;
|
||||
this._owning = list._owning !== false;
|
||||
},
|
||||
"destructor": function() {
|
||||
if (this._owning && (this._data instanceof Class)) {
|
||||
this._data.destructor();
|
||||
}
|
||||
delete this._list;
|
||||
|
||||
Class.fn.destructor.call(this);
|
||||
}
|
||||
});
|
||||
|
||||
var ListIterator = Class.inherit({
|
||||
"className": "ListIterator",
|
||||
"constructor": function(node) {
|
||||
Class.fn.constructor.call(this);
|
||||
|
||||
this._node = node;
|
||||
},
|
||||
"++": function() {
|
||||
if (this._node._next === null) {
|
||||
throw new Error("An attempt to increment iterator, pointing at the end of container");
|
||||
}
|
||||
this._node = this._node._next;
|
||||
},
|
||||
"--": function() {
|
||||
if (this._node._prev === null) {
|
||||
throw new Error("An attempt to decrement iterator, pointing at the beginning of container");
|
||||
}
|
||||
this._node = this._node._prev;
|
||||
},
|
||||
"*": function() {
|
||||
if (this._node._data === null) {
|
||||
throw new Error("An attempt to dereference iterator, pointing at the end of container");
|
||||
}
|
||||
return this._node._data;
|
||||
},
|
||||
"==": function(other) {
|
||||
return this._node === other._node;
|
||||
},
|
||||
"clone": function() {
|
||||
return new ListIterator(this._node);
|
||||
}
|
||||
});
|
||||
|
||||
AbstractList.dataType = undefined;
|
||||
AbstractList.iterator = ListIterator;
|
||||
|
||||
AbstractList.template = function(data) {
|
||||
|
||||
if (!(data instanceof Function)) {
|
||||
throw new Error("Wrong argument to template a list");
|
||||
}
|
||||
|
||||
var List = AbstractList.inherit({
|
||||
"className": "List",
|
||||
"constructor": function(owning) {
|
||||
AbstractList.fn.constructor.call(this, owning);
|
||||
}
|
||||
});
|
||||
|
||||
List.dataType = data;
|
||||
|
||||
return List;
|
||||
};
|
||||
|
||||
module.exports = AbstractList;
|
142
libjs/wContainer/abstractmap.js
Normal file
142
libjs/wContainer/abstractmap.js
Normal file
|
@ -0,0 +1,142 @@
|
|||
"use strict";
|
||||
var Class = require("../utils/class");
|
||||
var RBTree = require("bintrees").RBTree;
|
||||
var AbstractPair = require("./abstractpair");
|
||||
|
||||
var AbstractMap = Class.inherit({
|
||||
"className": "AbstractMap",
|
||||
"constructor": function(owning) {
|
||||
Class.fn.constructor.call(this);
|
||||
|
||||
this._owning = owning !== false;
|
||||
this._data = new RBTree(function (a, b) {
|
||||
if (a[">"](b)) {
|
||||
return 1;
|
||||
}
|
||||
if (a["<"](b)) {
|
||||
return -1
|
||||
}
|
||||
if (a["=="](b)) {
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
},
|
||||
"destructor": function() {
|
||||
this.clear();
|
||||
|
||||
Class.fn.destructor.call(this);
|
||||
},
|
||||
"begin": function() {
|
||||
var itr = this._data.iterator();
|
||||
if (itr.next() !== null) {
|
||||
return new Iterator(itr);
|
||||
}
|
||||
return this.end();
|
||||
},
|
||||
"clear": function() {
|
||||
if (this._owning) {
|
||||
this._data.each(function(data) {
|
||||
data.destructor();
|
||||
});
|
||||
}
|
||||
|
||||
this._data.clear();
|
||||
},
|
||||
"each": function(funct) {
|
||||
this._data.each(funct);
|
||||
},
|
||||
"end": function() {
|
||||
return new Iterator(this._data.iterator());
|
||||
},
|
||||
"erase": function(itr) {
|
||||
var pair = itr["*"]();
|
||||
if (!this._data.remove(pair)) {
|
||||
throw new Error("An attempt to remove non-existing map element");
|
||||
}
|
||||
if (this._owning) {
|
||||
pair.destructor();
|
||||
}
|
||||
},
|
||||
"find": function(key) {
|
||||
var pair = new this.constructor.dataType(key);
|
||||
|
||||
var iter = this._data.findIter(pair);
|
||||
if (iter === null) {
|
||||
return this.end();
|
||||
}
|
||||
return new Iterator(iter);
|
||||
},
|
||||
"insert": function(key, value) {
|
||||
var pair = new this.constructor.dataType(key, value);
|
||||
|
||||
if (!this._data.insert(pair)) {
|
||||
throw new Error("An attempt to insert already existing element into a map");
|
||||
}
|
||||
},
|
||||
"r_each": function(funct) {
|
||||
this._data.reach(funct);
|
||||
},
|
||||
"size": function() {
|
||||
return this._data.size;
|
||||
},
|
||||
"lowerBound": function(key) {
|
||||
var pair = new this.constructor.dataType(key);
|
||||
|
||||
return new Iterator(this._data.lowerBound(pair));
|
||||
},
|
||||
"upperBound": function(key) {
|
||||
var pair = new this.constructor.dataType(key);
|
||||
|
||||
return new Iterator(this._data.upperBound(pair));
|
||||
}
|
||||
});
|
||||
|
||||
var Iterator = Class.inherit({
|
||||
"className": "MapIterator",
|
||||
"constructor": function(rbtree_iterator) {
|
||||
Class.fn.constructor.call(this);
|
||||
|
||||
this._itr = rbtree_iterator;
|
||||
},
|
||||
"++": function() {
|
||||
if ((this._itr._cursor === null)) {
|
||||
throw new Error("An attempt to increment an iterator pointing to the end of the map");
|
||||
}
|
||||
this._itr.next();
|
||||
},
|
||||
"--": function() {
|
||||
this._itr.prev();
|
||||
if ((this._itr._cursor === null)) {
|
||||
throw new Error("An attempt to decrement an iterator pointing to the beginning of the map");
|
||||
}
|
||||
},
|
||||
"==": function(other) {
|
||||
return this._itr.data() === other._itr.data();
|
||||
},
|
||||
"*": function() {
|
||||
if ((this._itr._cursor === null)) {
|
||||
throw new Error("An attempt to dereference an iterator pointing to the end of the map");
|
||||
}
|
||||
return this._itr.data();
|
||||
}
|
||||
});
|
||||
|
||||
AbstractMap.dataType = undefined;
|
||||
AbstractMap.iterator = Iterator;
|
||||
|
||||
AbstractMap.template = function(first, second) {
|
||||
var dt = AbstractPair.template(first, second);
|
||||
|
||||
var Map = AbstractMap.inherit({
|
||||
"className": "Map",
|
||||
"constructor": function(owning) {
|
||||
AbstractMap.fn.constructor.call(this, owning);
|
||||
}
|
||||
});
|
||||
|
||||
Map.dataType = dt;
|
||||
|
||||
return Map;
|
||||
};
|
||||
|
||||
module.exports = AbstractMap;
|
104
libjs/wContainer/abstractorder.js
Normal file
104
libjs/wContainer/abstractorder.js
Normal file
|
@ -0,0 +1,104 @@
|
|||
"use strict";
|
||||
var Class = require("../utils/class");
|
||||
var AbstractMap = require("./abstractmap");
|
||||
var AbstractList = require("./abstractlist");
|
||||
|
||||
var AbstractOrder = Class.inherit({
|
||||
"className": "AbstractOrder",
|
||||
"constructor": function(owning) {
|
||||
Class.fn.constructor.call(this);
|
||||
|
||||
if (!this.constructor.dataType) {
|
||||
throw new Error("An attempt to instantiate an order without declared member type");
|
||||
}
|
||||
|
||||
var Map = AbstractMap.template(this.constructor.dataType, this.constructor.iterator);
|
||||
var List = AbstractList.template(this.constructor.dataType);
|
||||
|
||||
this._owning = owning !== false;
|
||||
|
||||
this._rmap = new Map(this._owning);
|
||||
this._order = new List(false);
|
||||
},
|
||||
"destructor": function() {
|
||||
this._rmap.destructor();
|
||||
this._order.destructor();
|
||||
|
||||
Class.fn.destructor.call(this);
|
||||
},
|
||||
"begin": function() {
|
||||
return this._order.begin();
|
||||
},
|
||||
"clear": function() {
|
||||
this._rmap.clear();
|
||||
this._order.clear();
|
||||
},
|
||||
"end": function() {
|
||||
return this._order.end();
|
||||
},
|
||||
"erase": function(element) {
|
||||
var itr = this._rmap.find(element);
|
||||
|
||||
if (itr["=="](this._rmap.end())) {
|
||||
throw new Error("An attempt to erase non existing element from an order");
|
||||
}
|
||||
|
||||
var pair = itr["*"]();
|
||||
|
||||
this._order.erase(pair.second);
|
||||
this._rmap.erase(itr);
|
||||
},
|
||||
"find": function(data) {
|
||||
var itr = this._rmap.find(data);
|
||||
|
||||
if (itr["=="](this._rmap.end())) {
|
||||
return this.end();
|
||||
}
|
||||
return itr["*"]().second;
|
||||
},
|
||||
"insert": function(data, target) {
|
||||
var itr = this._rmap.find(target);
|
||||
|
||||
if (itr["=="](this._rmap.end())) {
|
||||
throw new Error("An attempt to insert element before the non existing one");
|
||||
}
|
||||
|
||||
var pair = itr["*"]();
|
||||
this._order.insert(data, pair.second);
|
||||
|
||||
var pointer = pair.second.clone()["--"]();
|
||||
this._rmap.insert(data, pointer);
|
||||
},
|
||||
"push_back": function(data) {
|
||||
this._order.push_back(data);
|
||||
var itr = this._order.end();
|
||||
itr["--"]();
|
||||
|
||||
this._rmap.insert(data, itr);
|
||||
},
|
||||
"size": function() {
|
||||
return this._order.size();
|
||||
}
|
||||
});
|
||||
|
||||
AbstractOrder.dataType = undefined;
|
||||
AbstractOrder.iterator = AbstractList.iterator;
|
||||
|
||||
AbstractOrder.template = function(data) {
|
||||
if (!(data instanceof Function)) {
|
||||
throw new Error("Wrong argument to template an order");
|
||||
}
|
||||
|
||||
var Order = AbstractOrder.inherit({
|
||||
"className": "Order",
|
||||
"constructor": function(owning) {
|
||||
AbstractOrder.fn.constructor.call(this, owning);
|
||||
}
|
||||
});
|
||||
|
||||
Order.dataType = data;
|
||||
|
||||
return Order;
|
||||
}
|
||||
|
||||
module.exports = AbstractOrder
|
111
libjs/wContainer/abstractpair.js
Normal file
111
libjs/wContainer/abstractpair.js
Normal file
|
@ -0,0 +1,111 @@
|
|||
"use strict";
|
||||
var Class = require("../utils/class");
|
||||
|
||||
var AbstractPair = Class.inherit({
|
||||
"className": "AbstractPair",
|
||||
"constructor": function(first, second) {
|
||||
Class.fn.constructor.call(this);
|
||||
|
||||
if (!this.constructor.firstType || !this.constructor.secondType) {
|
||||
throw new Error("An attempt to instantiate a pair without declared member types");
|
||||
}
|
||||
if (!(first instanceof this.constructor.firstType)) {
|
||||
throw new Error("An attempt to construct a pair from wrong arguments");
|
||||
}
|
||||
|
||||
this.first = first;
|
||||
this.second = second;
|
||||
},
|
||||
"destructor": function() {
|
||||
this.first.destructor();
|
||||
if (this.second) {
|
||||
this.second.destructor();
|
||||
}
|
||||
|
||||
Class.fn.destructor.call(this);
|
||||
},
|
||||
"<": function(other) {
|
||||
if (!(other instanceof this.constructor)) {
|
||||
throw new Error("Can't compare pairs with different content types");
|
||||
}
|
||||
if (this.constructor.complete) {
|
||||
if (this.first["<"](other.first)) {
|
||||
return true;
|
||||
} else if(this.first["=="](other.first)) {
|
||||
this.second["<"](other.second);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return this.first["<"](other.first);
|
||||
}
|
||||
},
|
||||
">": function(other) {
|
||||
if (!(other instanceof this.constructor)) {
|
||||
throw new Error("Can't compare pairs with different content types");
|
||||
}
|
||||
if (this.constructor.complete) {
|
||||
if (this.first[">"](other.first)) {
|
||||
return true;
|
||||
} else if(this.first["=="](other.first)) {
|
||||
this.second[">"](other.second);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return this.first[">"](other.first);
|
||||
}
|
||||
},
|
||||
"==": function(other) {
|
||||
if (!(other instanceof this.constructor)) {
|
||||
throw new Error("Can't compare pairs with different content types");
|
||||
}
|
||||
if (this.constructor.complete) {
|
||||
return this.first["=="](other.first) && this.second["=="](other.second);
|
||||
} else {
|
||||
return this.first["=="](other.first);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
AbstractPair.firstType = undefined;
|
||||
AbstractPair.secondType = undefined;
|
||||
AbstractPair.complete = false;
|
||||
|
||||
AbstractPair.template = function(first, second, complete) {
|
||||
if (!(first instanceof Function) || !(second instanceof Function)) {
|
||||
throw new Error("An attempt to create template pair from wrong arguments");
|
||||
}
|
||||
if (
|
||||
!(first.prototype["<"] instanceof Function) ||
|
||||
!(first.prototype[">"] instanceof Function) ||
|
||||
!(first.prototype["=="] instanceof Function)
|
||||
)
|
||||
{
|
||||
throw new Error("Not acceptable first type");
|
||||
}
|
||||
if (
|
||||
complete &&
|
||||
(
|
||||
!(second.prototype["<"] instanceof Function) ||
|
||||
!(second.prototype[">"] instanceof Function) ||
|
||||
!(second.prototype["=="] instanceof Function)
|
||||
)
|
||||
)
|
||||
{
|
||||
throw new Error("Not acceptable second type");
|
||||
}
|
||||
var Pair = AbstractPair.inherit({
|
||||
"className": "Pair",
|
||||
"constructor": function(first, second) {
|
||||
AbstractPair.fn.constructor.call(this, first, second);
|
||||
}
|
||||
});
|
||||
Pair.firstType = first;
|
||||
Pair.secondType = second;
|
||||
Pair.complete = complete === true;
|
||||
|
||||
return Pair;
|
||||
};
|
||||
|
||||
module.exports = AbstractPair;
|
143
libjs/wContainer/abstractset.js
Normal file
143
libjs/wContainer/abstractset.js
Normal file
|
@ -0,0 +1,143 @@
|
|||
"use strict";
|
||||
var Class = require("../utils/class");
|
||||
var RBTree = require("bintrees").RBTree;
|
||||
|
||||
var AbstractSet = Class.inherit({
|
||||
"className": "AbstractSet",
|
||||
"constructor": function(owning) {
|
||||
Class.fn.constructor.call(this);
|
||||
|
||||
this._owning = owning !== false;
|
||||
this._data = new RBTree(function (a, b) {
|
||||
if (a[">"](b)) {
|
||||
return 1;
|
||||
}
|
||||
if (a["<"](b)) {
|
||||
return -1
|
||||
}
|
||||
if (a["=="](b)) {
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
},
|
||||
"destructor": function() {
|
||||
this.clear();
|
||||
|
||||
Class.fn.destructor.call(this);
|
||||
},
|
||||
"begin": function() {
|
||||
var itr = this._data.iterator();
|
||||
if (itr.next() !== null) {
|
||||
return new Iterator(itr);
|
||||
}
|
||||
return this.end();
|
||||
},
|
||||
"clear": function() {
|
||||
if (this._owning) {
|
||||
this._data.each(function(data) {
|
||||
data.destructor();
|
||||
});
|
||||
}
|
||||
|
||||
this._data.clear();
|
||||
},
|
||||
"each": function(funct) {
|
||||
this._data.each(funct);
|
||||
},
|
||||
"end": function() {
|
||||
return new Iterator(this._data.iterator());
|
||||
},
|
||||
"erase": function(itr) {
|
||||
var value = itr["*"]();
|
||||
if (!this._data.remove(value)) {
|
||||
throw new Error("An attempt to remove non-existing set element");
|
||||
}
|
||||
if (this._owning) {
|
||||
value.destructor();
|
||||
}
|
||||
},
|
||||
"find": function(key) {
|
||||
if (!(key instanceof this.constructor.dataType)) {
|
||||
throw new Error("An attempt to find wrong value type in the set");
|
||||
}
|
||||
var iter = this._data.findIter(key);
|
||||
if (iter === null) {
|
||||
return this.end();
|
||||
}
|
||||
return new Iterator(iter);
|
||||
},
|
||||
"insert": function(value) {
|
||||
if (!(value instanceof this.constructor.dataType)) {
|
||||
throw new Error("An attempt to insert wrong value type to set");
|
||||
}
|
||||
if (!this._data.insert(value)) {
|
||||
throw new Error("An attempt to insert already existing element into a set");
|
||||
}
|
||||
},
|
||||
"r_each": function(funct) {
|
||||
this._data.reach(funct);
|
||||
},
|
||||
"size": function() {
|
||||
return this._data.size;
|
||||
},
|
||||
"lowerBound": function(key) {
|
||||
if (!(key instanceof this.constructor.dataType)) {
|
||||
throw new Error("An attempt to find wrong value type in the set");
|
||||
}
|
||||
return new Iterator(this._data.lowerBound(key));
|
||||
},
|
||||
"upperBound": function(key) {
|
||||
if (!(key instanceof this.constructor.dataType)) {
|
||||
throw new Error("An attempt to find wrong value type in the set");
|
||||
}
|
||||
return new Iterator(this._data.upperBound(key));
|
||||
}
|
||||
});
|
||||
|
||||
var Iterator = Class.inherit({
|
||||
"className": "SetIterator",
|
||||
"constructor": function(rbtree_iterator) {
|
||||
Class.fn.constructor.call(this);
|
||||
|
||||
this._itr = rbtree_iterator;
|
||||
},
|
||||
"++": function() {
|
||||
if ((this._itr._cursor === null)) {
|
||||
throw new Error("An attempt to increment an iterator pointing to the end of the set");
|
||||
}
|
||||
this._itr.next();
|
||||
},
|
||||
"--": function() {
|
||||
this._itr.prev();
|
||||
if ((this._itr._cursor === null)) {
|
||||
throw new Error("An attempt to decrement an iterator pointing to the beginning of the set");
|
||||
}
|
||||
},
|
||||
"==": function(other) {
|
||||
return this._itr.data() === other._itr.data();
|
||||
},
|
||||
"*": function() {
|
||||
if ((this._itr._cursor === null)) {
|
||||
throw new Error("An attempt to dereference an iterator pointing to the end of the set");
|
||||
}
|
||||
return this._itr.data();
|
||||
}
|
||||
});
|
||||
|
||||
AbstractSet.dataType = undefined;
|
||||
AbstractSet.iterator = Iterator;
|
||||
|
||||
AbstractSet.template = function(type) {
|
||||
var Set = AbstractSet.inherit({
|
||||
"className": "Set",
|
||||
"constructor": function(owning) {
|
||||
AbstractSet.fn.constructor.call(this, owning);
|
||||
}
|
||||
});
|
||||
|
||||
Set.dataType = type;
|
||||
|
||||
return Set;
|
||||
};
|
||||
|
||||
module.exports = AbstractSet;
|
19
libjs/wController/CMakeLists.txt
Normal file
19
libjs/wController/CMakeLists.txt
Normal file
|
@ -0,0 +1,19 @@
|
|||
cmake_minimum_required(VERSION 2.8.12)
|
||||
|
||||
configure_file(controller.js controller.js)
|
||||
configure_file(globalControls.js globalControls.js)
|
||||
configure_file(link.js link.js)
|
||||
configure_file(list.js list.js)
|
||||
configure_file(navigationPanel.js navigationPanel.js)
|
||||
configure_file(page.js page.js)
|
||||
configure_file(pageStorage.js pageStorage.js)
|
||||
configure_file(panesList.js panesList.js)
|
||||
configure_file(string.js string.js)
|
||||
configure_file(theme.js theme.js)
|
||||
configure_file(themeSelecter.js themeSelecter.js)
|
||||
configure_file(vocabulary.js vocabulary.js)
|
||||
configure_file(attributes.js attributes.js)
|
||||
configure_file(localModel.js localModel.js)
|
||||
configure_file(catalogue.js catalogue.js)
|
||||
configure_file(imagePane.js imagePane.js)
|
||||
configure_file(file/file.js file/file.js)
|
1
libjs/wController/attributes.js
Normal file
1
libjs/wController/attributes.js
Normal file
|
@ -0,0 +1 @@
|
|||
"use strict";
|
141
libjs/wController/catalogue.js
Normal file
141
libjs/wController/catalogue.js
Normal file
|
@ -0,0 +1,141 @@
|
|||
"use strict";
|
||||
|
||||
var Controller = require("./controller");
|
||||
var AbstractOrder = require("../wContainer/abstractorder");
|
||||
|
||||
var Uint64 = require("../wType/uint64");
|
||||
var Vocabulary = require("../wType/vocabulary");
|
||||
var Boolean = require("../wType/boolean");
|
||||
var String = require("../wType/string");
|
||||
|
||||
var IdOrder = AbstractOrder.template(Uint64);
|
||||
|
||||
var Catalogue = Controller.inherit({
|
||||
"className": "Catalogue",
|
||||
"constructor": function(addr, options) {
|
||||
Controller.fn.constructor.call(this, addr);
|
||||
|
||||
this._hasSorting = false;
|
||||
this._hasFilter = false;
|
||||
this._filter = undefined;
|
||||
this.data = new IdOrder(true);
|
||||
|
||||
if (options.sorting) {
|
||||
this._hasSorting = true;
|
||||
this._sorting = new Vocabulary();
|
||||
this._sorting.insert("ascending", new Boolean(options.sorting.ascending));
|
||||
this._sorting.insert("field", new String(options.sorting.field));
|
||||
}
|
||||
if (options.filter) {
|
||||
var filter = new Vocabulary();
|
||||
for (var key in options.filter) {
|
||||
if (options.filter.hasOwnProperty(key)) {
|
||||
filter.insert(key, options.filter[key]);
|
||||
}
|
||||
}
|
||||
if (filter.length()) {
|
||||
this._filter = filter;
|
||||
this._hasFilter = true;
|
||||
} else {
|
||||
filter.destructor();
|
||||
}
|
||||
}
|
||||
|
||||
this.addHandler("get");
|
||||
this.addHandler("addElement");
|
||||
this.addHandler("removeElement");
|
||||
this.addHandler("moveElement");
|
||||
this.addHandler("clear");
|
||||
},
|
||||
"destructor": function() {
|
||||
this.data.destructor();
|
||||
|
||||
if (this._hasSorting) {
|
||||
this._sorting.destructor();
|
||||
}
|
||||
if (this._hasFilter) {
|
||||
this._filter.destructor();
|
||||
}
|
||||
|
||||
Controller.fn.destructor.call(this);
|
||||
},
|
||||
"addElement": function(element, before) {
|
||||
if (before === undefined) {
|
||||
this.data.push_back(element);
|
||||
} else {
|
||||
this.data.insert(element, before);
|
||||
}
|
||||
|
||||
this.trigger("addElement", element, before);
|
||||
},
|
||||
"clear": function() {
|
||||
this.data.clear();
|
||||
this.trigger("clear");
|
||||
},
|
||||
"_createSubscriptionVC": function() {
|
||||
var vc = Controller.fn._createSubscriptionVC.call(this);
|
||||
var p = new Vocabulary();
|
||||
|
||||
if (this._hasSorting) {
|
||||
p.insert("sorting", this._sorting.clone());
|
||||
}
|
||||
if (this._hasFilter) {
|
||||
p.insert("filter", this._filter.clone());
|
||||
}
|
||||
|
||||
vc.insert("params", p);
|
||||
return vc;
|
||||
},
|
||||
"_h_addElement": function(ev) {
|
||||
var data = ev.getData();
|
||||
var id = data.at("id").clone();
|
||||
var before = undefined;
|
||||
if (data.has("before")) {
|
||||
before = data.at("before").clone();
|
||||
}
|
||||
|
||||
this.addElement(id, before);
|
||||
},
|
||||
"_h_get": function(ev) {
|
||||
this.clear();
|
||||
|
||||
var data = ev.getData().at("data");
|
||||
var size = data.length();
|
||||
for (var i = 0; i < size; ++i) {
|
||||
this.addElement(data.at(i).clone());
|
||||
}
|
||||
this.initialized = true;
|
||||
this.trigger("data");
|
||||
},
|
||||
"_h_moveElement": function(ev) {
|
||||
var data = ev.getData();
|
||||
var id = data.at("id").clone();
|
||||
var before = undefined;
|
||||
if (data.has("before")) {
|
||||
before = data.at("before").clone();
|
||||
}
|
||||
|
||||
this.data.erase(id);
|
||||
if (before === undefined) {
|
||||
this.data.push_back(element);
|
||||
} else {
|
||||
this.data.insert(element, before);
|
||||
}
|
||||
|
||||
this.trigger("moveElement", id, before);
|
||||
},
|
||||
"_h_removeElement": function(ev) {
|
||||
var data = ev.getData();
|
||||
|
||||
this.removeElement(data.at("id").clone());
|
||||
},
|
||||
"_h_clear": function(ev) {
|
||||
this.clear();
|
||||
},
|
||||
"removeElement": function(id) {
|
||||
this.data.erase(id);
|
||||
this.trigger("removeElement", id);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Catalogue;
|
382
libjs/wController/controller.js
Normal file
382
libjs/wController/controller.js
Normal file
|
@ -0,0 +1,382 @@
|
|||
"use strict";
|
||||
var counter = 0;
|
||||
var Subscribable = require("../utils/subscribable");
|
||||
var Handler = require("../wDispatcher/handler");
|
||||
var Address = require("../wType/address");
|
||||
var String = require("../wType/string");
|
||||
var Vocabulary = require("../wType/vocabulary");
|
||||
var Event = require("../wType/event");
|
||||
var counter = 0;
|
||||
|
||||
var Controller = Subscribable.inherit({
|
||||
"className": "Controller",
|
||||
"constructor": function(addr) {
|
||||
Subscribable.fn.constructor.call(this);
|
||||
|
||||
this.id = ++counter;
|
||||
this.initialized = false;
|
||||
|
||||
this._subscribed = false;
|
||||
this._registered = false;
|
||||
this._pairAddress = addr;
|
||||
this._address = new Address([this.className.toString() + counter++]);
|
||||
|
||||
this._handlers = [];
|
||||
this._controllers = [];
|
||||
this.properties = [];
|
||||
this._foreignControllers = [];
|
||||
|
||||
this.addHandler("properties");
|
||||
},
|
||||
"destructor": function() {
|
||||
var i;
|
||||
|
||||
if (this._subscribed) {
|
||||
this.unsubscribe();
|
||||
}
|
||||
if (this._registered) {
|
||||
this.unregister();
|
||||
}
|
||||
|
||||
for (i = 0; i < this._foreignControllers.length; ++i) {
|
||||
this._foreignControllers[i].c.destructor();
|
||||
}
|
||||
|
||||
for (i = 0; i < this._controllers.length; ++i) {
|
||||
this._controllers[i].destructor();
|
||||
}
|
||||
|
||||
for (i = 0; i < this._handlers.length; ++i) {
|
||||
this._handlers[i].destructor();
|
||||
}
|
||||
this._pairAddress.destructor();
|
||||
this._address.destructor();
|
||||
|
||||
Subscribable.fn.destructor.call(this);
|
||||
},
|
||||
"addController": function(controller, before) {
|
||||
if (!(controller instanceof Controller)) {
|
||||
throw new Error("An attempt to add not a controller into " + this.className);
|
||||
}
|
||||
controller.on("serviceMessage", this._onControllerServiceMessage, this);
|
||||
var index = this._controllers.length;
|
||||
if (before === undefined) {
|
||||
this._controllers.push(controller);
|
||||
} else {
|
||||
index = before;
|
||||
this._controllers.splice(before, 0, controller);
|
||||
}
|
||||
if (this._registered) {
|
||||
controller.register(this._dp, this._socket);
|
||||
}
|
||||
if (this._subscribed && !controller._subscribed) {
|
||||
this._subscribeChildController(index);
|
||||
}
|
||||
this.trigger("newController", controller, index);
|
||||
},
|
||||
"addForeignController": function(nodeName, ctrl) {
|
||||
if (!(ctrl instanceof Controller)) {
|
||||
throw new Error("An attempt to add not a controller into " + this.className);
|
||||
}
|
||||
|
||||
this._foreignControllers.push({n: nodeName, c: ctrl});
|
||||
ctrl.on("serviceMessage", this._onControllerServiceMessage, this);
|
||||
|
||||
if (this._registered) {
|
||||
global.registerForeignController(nodeName, ctrl);
|
||||
}
|
||||
|
||||
if (this._subscribed) {
|
||||
global.subscribeForeignController(nodeName, ctrl);
|
||||
}
|
||||
},
|
||||
"addHandler": function(name) {
|
||||
if (!(this["_h_" + name] instanceof Function)) {
|
||||
throw new Error("An attempt to create handler without a handling method");
|
||||
}
|
||||
|
||||
var handler = new Handler(this._address["+"](new Address([name])), this, this["_h_" + name]);
|
||||
|
||||
this._handlers.push(handler);
|
||||
if (this._registered) {
|
||||
this._dp.registerHandler(handler);
|
||||
}
|
||||
},
|
||||
"clearChildren": function() {
|
||||
while (this._controllers.length) {
|
||||
var controller = this._controllers[this._controllers.length - 1]
|
||||
this._removeController(controller);
|
||||
controller.destructor();
|
||||
}
|
||||
},
|
||||
"_createSubscriptionVC": function() {
|
||||
return new Vocabulary();
|
||||
},
|
||||
"getPairAddress": function() {
|
||||
return this._pairAddress.clone();
|
||||
},
|
||||
"_h_properties": function(ev) {
|
||||
this.trigger("clearProperties");
|
||||
this.properties = [];
|
||||
var data = ev.getData();
|
||||
var list = data.at("properties");
|
||||
var size = list.length();
|
||||
for (var i = 0; i < size; ++i) {
|
||||
var vc = list.at(i);
|
||||
var pair = {p: vc.at("property").toString(), k: vc.at("key").toString()};
|
||||
this.properties.push(pair);
|
||||
this.trigger("addProperty", pair.k, pair.p);
|
||||
}
|
||||
},
|
||||
"_onControllerServiceMessage": function(msg, severity) {
|
||||
this.trigger("serviceMessage", msg, severity);
|
||||
},
|
||||
"_onSocketDisconnected": function() {
|
||||
this._subscribed = false;
|
||||
},
|
||||
"register": function(dp, socket) {
|
||||
var i;
|
||||
if (this._registered) {
|
||||
throw new Error("Controller " + this._address.toString() + " is already registered");
|
||||
}
|
||||
this._dp = dp;
|
||||
this._socket = socket;
|
||||
socket.on("disconnected", this._onSocketDisconnected, this);
|
||||
|
||||
for (i = 0; i < this._controllers.length; ++i) {
|
||||
this._controllers[i].register(this._dp, this._socket);
|
||||
}
|
||||
|
||||
for (i = 0; i < this._handlers.length; ++i) {
|
||||
dp.registerHandler(this._handlers[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < this._foreignControllers.length; ++i) {
|
||||
var pair = this._foreignControllers[i]
|
||||
global.registerForeignController(pair.n, pair.c);
|
||||
}
|
||||
|
||||
this._registered = true;
|
||||
},
|
||||
"removeController": function(ctrl) {
|
||||
if (!(ctrl instanceof Controller)) {
|
||||
throw new Error("An attempt to remove not a controller from " + this.className);
|
||||
}
|
||||
var index = this._controllers.indexOf(ctrl);
|
||||
if (index !== -1) {
|
||||
this._removeControllerByIndex(index);
|
||||
} else {
|
||||
throw new Error("An attempt to remove not not existing controller from " + this.className);
|
||||
}
|
||||
},
|
||||
"removeForeignController": function(ctrl) {
|
||||
if (!(ctrl instanceof Controller)) {
|
||||
throw new Error("An attempt to remove not a controller from " + this.className);
|
||||
}
|
||||
for (var i = 0; i < this._foreignControllers.length; ++i) {
|
||||
if (this._foreignControllers[i].c === ctrl) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i === this._foreignControllers.length) {
|
||||
throw new Error("An attempt to remove not not existing controller from " + this.className);
|
||||
} else {
|
||||
var pair = this._foreignControllers[i];
|
||||
if (this._subscribed) {
|
||||
global.unsubscribeForeignController(pair.n, pair.c);
|
||||
}
|
||||
|
||||
if (this._registered) {
|
||||
global.registerForeignController(pair.n, pair.c);
|
||||
}
|
||||
|
||||
pair.c.off("serviceMessage", this._onControllerServiceMessage, this);
|
||||
|
||||
this._foreignControllers.splice(i, 1);
|
||||
}
|
||||
},
|
||||
"_removeControllerByIndex": function(index) {
|
||||
var ctrl = this._controllers[index];
|
||||
if (this._subscribed) {
|
||||
this._unsubscribeChildController(index);
|
||||
}
|
||||
if (this._dp) {
|
||||
ctrl.unregister();
|
||||
}
|
||||
this._controllers.splice(index, 1);
|
||||
|
||||
this.trigger("removedController", ctrl, index);
|
||||
},
|
||||
"send": function(vc, handler) {
|
||||
if (!this._registered) {
|
||||
throw new Error("An attempt to send event from model " + this._address.toString() + " which is not registered");
|
||||
}
|
||||
var addr = this._pairAddress["+"](new Address([handler]));
|
||||
var id = this._socket.getId().clone();
|
||||
|
||||
vc.insert("source", this._address.clone());
|
||||
|
||||
var ev = new Event(addr, vc);
|
||||
ev.setSenderId(id);
|
||||
this._socket.send(ev);
|
||||
ev.destructor();
|
||||
},
|
||||
"subscribe": function() {
|
||||
if (this._subscribed) {
|
||||
throw new Error("An attempt to subscribe model " + this._address.toString() + " which is already subscribed");
|
||||
}
|
||||
this._subscribed = true;
|
||||
|
||||
var vc = this._createSubscriptionVC();
|
||||
this.send(vc, "subscribe");
|
||||
|
||||
for (var i = 0; i < this._controllers.length; ++i) {
|
||||
this._subscribeChildController(i)
|
||||
}
|
||||
|
||||
for (var i = 0; i < this._foreignControllers.length; ++i) {
|
||||
var pair = this._foreignControllers[i]
|
||||
global.subscribeForeignController(pair.n, pair.c);
|
||||
}
|
||||
},
|
||||
"_subscribeChildController": function(index) {
|
||||
var ctrl = this._controllers[index];
|
||||
ctrl.subscribe();
|
||||
},
|
||||
"unregister": function() {
|
||||
if (!this._registered) {
|
||||
throw new Error("Controller " + this._address.toString() + " is not registered");
|
||||
}
|
||||
var i;
|
||||
|
||||
for (i = 0; i < this._foreignControllers.length; ++i) {
|
||||
var pair = this._foreignControllers[i]
|
||||
global.unregisterForeignController(pair.n, pair.c);
|
||||
}
|
||||
|
||||
for (i = 0; i < this._controllers.length; ++i) {
|
||||
this._controllers[i].unregister();
|
||||
}
|
||||
for (i = 0; i < this._handlers.length; ++i) {
|
||||
this._dp.unregisterHandler(this._handlers[i]);
|
||||
}
|
||||
this._socket.off("disconnected", this._onSocketDisconnected, this);
|
||||
delete this._dp;
|
||||
delete this._socket;
|
||||
|
||||
this._registered = false;
|
||||
},
|
||||
"unsubscribe": function() {
|
||||
if (!this._subscribed) {
|
||||
throw new Error("An attempt to unsubscribe model " + this._address.toString() + " which is not subscribed");
|
||||
}
|
||||
this._subscribed = false;
|
||||
|
||||
if (this._socket.isOpened()) {
|
||||
var vc = new Vocabulary();
|
||||
this.send(vc, "unsubscribe");
|
||||
}
|
||||
|
||||
for (var i = 0; i < this._foreignControllers.length; ++i) {
|
||||
var pair = this._foreignControllers[i]
|
||||
global.unsubscribeForeignController(pair.n, pair.c);
|
||||
}
|
||||
|
||||
for (var i = 0; i < this._controllers.length; ++i) {
|
||||
this._unsubscribeChildController(i);
|
||||
}
|
||||
},
|
||||
"_unsubscribeChildController": function(index) {
|
||||
var ctrl = this._controllers[index];
|
||||
ctrl.unsubscribe();
|
||||
}
|
||||
});
|
||||
|
||||
Controller.createByType = function(type, address) {
|
||||
var typeName = this.ReversedModelType[type];
|
||||
if (typeName === undefined) {
|
||||
throw new Error("Unknown ModelType: " + type);
|
||||
}
|
||||
var Type = this.constructors[typeName];
|
||||
if (Type === undefined) {
|
||||
throw new Error("Constructor is not loaded yet, something is wrong");
|
||||
}
|
||||
return new Type(address);
|
||||
}
|
||||
|
||||
Controller.initialize = function(rc, cb) {
|
||||
var deps = [];
|
||||
var types = [];
|
||||
for (var key in this.ModelTypesPaths) {
|
||||
if (this.ModelTypesPaths.hasOwnProperty(key)) {
|
||||
if (!rc || rc.indexOf(key) !== -1) {
|
||||
deps.push(this.ModelTypesPaths[key]);
|
||||
types.push(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
require(deps, function() {
|
||||
for (var i = 0; i < types.length; ++i) {
|
||||
Controller.constructors[types[i]] = arguments[i];
|
||||
}
|
||||
cb();
|
||||
});
|
||||
}
|
||||
|
||||
Controller.ModelType = {
|
||||
String: 0,
|
||||
List: 1,
|
||||
Vocabulary: 2,
|
||||
Image: 3,
|
||||
Controller: 4,
|
||||
|
||||
Attributes: 50,
|
||||
|
||||
GlobalControls: 100,
|
||||
Link: 101,
|
||||
Page: 102,
|
||||
PageStorage: 103,
|
||||
PanesList: 104,
|
||||
Theme: 105,
|
||||
ThemeStorage: 106
|
||||
};
|
||||
|
||||
Controller.ReversedModelType = {
|
||||
"0": "String",
|
||||
"1": "List",
|
||||
"2": "Vocabulary",
|
||||
"3": "Image",
|
||||
"4": "Controller",
|
||||
|
||||
"50": "Attributes",
|
||||
|
||||
"100": "GlobalControls",
|
||||
"101": "Link",
|
||||
"102": "Page",
|
||||
"103": "PageStorage",
|
||||
"104": "PanesList",
|
||||
"105": "Theme",
|
||||
"106": "ThemeStorage"
|
||||
};
|
||||
|
||||
Controller.ModelTypesPaths = {
|
||||
String: "./string", //resolve as dependency
|
||||
List: "./list", //resolve as dependency
|
||||
Vocabulary: "./vocabulary", //resolve as dependency
|
||||
Attributes: "./attributes", //resolve as dependency
|
||||
GlobalControls: "./globalControls", //resolve as dependency
|
||||
Link: "./link", //resolve as dependency
|
||||
Page: "./page", //resolve as dependency
|
||||
PageStorage: "./pageStorage", //resolve as dependency
|
||||
PanesList: "./panesList", //resolve as dependency
|
||||
Theme: "./theme", //resolve as dependency
|
||||
ThemeStorage: "./themeStorage", //resolve as dependency
|
||||
Image: "./image" //resolve as dependency
|
||||
};
|
||||
|
||||
Controller.constructors = {
|
||||
Controller: Controller
|
||||
};
|
||||
|
||||
module.exports = Controller;
|
86
libjs/wController/file/file.js
Normal file
86
libjs/wController/file/file.js
Normal file
|
@ -0,0 +1,86 @@
|
|||
"use strict";
|
||||
|
||||
var Controller = require("../controller");
|
||||
var WVocabulary = require("../../wType/vocabulary");
|
||||
|
||||
var File = Controller.inherit({
|
||||
"className": "File",
|
||||
"constructor": function(addr) {
|
||||
Controller.fn.constructor.call(this, addr);
|
||||
|
||||
this._hasData = false;
|
||||
this._hasAdditional = false;
|
||||
this.data = null;
|
||||
this._additional = null;
|
||||
this._need = 0;
|
||||
|
||||
this.addHandler("get");
|
||||
this.addHandler("getAdditional");
|
||||
},
|
||||
"destructor": function() {
|
||||
if (this._hasData) {
|
||||
this.data.destructor();
|
||||
}
|
||||
if (this._hasAdditional) {
|
||||
this._additional.destructor();
|
||||
}
|
||||
Controller.fn.destructor.call(this);
|
||||
},
|
||||
"dontNeedData": function() {
|
||||
--this._need;
|
||||
},
|
||||
"hasData": function() {
|
||||
return this._hasData
|
||||
},
|
||||
"_getAdditional": function(add) {
|
||||
var ac = !this._hasAdditional || !this._additional["=="](add);
|
||||
if (ac) {
|
||||
if (this._hasAdditional) {
|
||||
this._additional.destructor();
|
||||
}
|
||||
this._additional = add.clone();
|
||||
}
|
||||
this._hasAdditional = true;
|
||||
return ac;
|
||||
},
|
||||
"getMimeType": function() {
|
||||
return this._additional.at("mimeType").toString();
|
||||
},
|
||||
"_h_get": function(ev) {
|
||||
var dt = ev.getData();
|
||||
|
||||
var ac = this._getAdditional(dt.at("additional"));
|
||||
if (ac) {
|
||||
this.trigger("additionalChange")
|
||||
}
|
||||
|
||||
this._hasData = true;
|
||||
this.data = dt.at("data").clone();
|
||||
this.trigger("data");
|
||||
},
|
||||
"_h_getAdditional": function(ev) {
|
||||
var ac = this._getAdditional(ev.getData());
|
||||
if (ac) {
|
||||
this.trigger("additionalChange");
|
||||
}
|
||||
},
|
||||
"needData": function() {
|
||||
if (this._need === 0) {
|
||||
var vc = new WVocabulary();
|
||||
|
||||
this.send(vc, "get");
|
||||
}
|
||||
++this._need;
|
||||
},
|
||||
"subscribe": function() {
|
||||
Controller.fn.subscribe.call(this);
|
||||
|
||||
if (this._need > 0) {
|
||||
var vc = new WVocabulary();
|
||||
|
||||
this.send(vc, "get");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = File;
|
60
libjs/wController/globalControls.js
Normal file
60
libjs/wController/globalControls.js
Normal file
|
@ -0,0 +1,60 @@
|
|||
"use strict";
|
||||
|
||||
var List = require("./list");
|
||||
var String = require("./string");
|
||||
var NavigationPanel = require("./navigationPanel");
|
||||
var ThemeSelecter = require("./themeSelecter");
|
||||
var Theme = require("./theme");
|
||||
|
||||
var GlobalControls = List.inherit({
|
||||
"className": "GlobalControls",
|
||||
"constructor": function(address) {
|
||||
List.fn.constructor.call(this, address);
|
||||
},
|
||||
"addElement": function(vc) {
|
||||
List.fn.addElement.call(this, vc);
|
||||
|
||||
var name = vc.at("name").toString();
|
||||
var type = vc.at("type").toString();
|
||||
var addr = vc.at("address");
|
||||
var ctrl;
|
||||
var supported = true;
|
||||
|
||||
switch (name) {
|
||||
case "version":
|
||||
ctrl = new String(addr.clone());
|
||||
break;
|
||||
case "navigationPanel":
|
||||
ctrl = new NavigationPanel(addr.clone());
|
||||
break;
|
||||
case "themes":
|
||||
ctrl = new ThemeSelecter(addr.clone());
|
||||
ctrl.on("selected", this._onThemeSelected, this);
|
||||
break;
|
||||
default:
|
||||
supported = false;
|
||||
this.trigger("serviceMessage", "Unsupported global control: " + name + " (" + type + ")", 1);
|
||||
break;
|
||||
}
|
||||
if (supported) {
|
||||
ctrl.name = name;
|
||||
this.addController(ctrl);
|
||||
}
|
||||
},
|
||||
"clear": function() {
|
||||
List.fn.clear.call(this);
|
||||
this.clearChildren();
|
||||
},
|
||||
"_onThemeReady": function(theme) {
|
||||
this.trigger("themeSelected", theme._data);
|
||||
this.removeController(theme);
|
||||
theme.destructor();
|
||||
},
|
||||
"_onThemeSelected": function(obj) {
|
||||
var theme = new Theme(obj.value.clone());
|
||||
this.addController(theme);
|
||||
theme.on("ready", this._onThemeReady.bind(this, theme));
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = GlobalControls;
|
69
libjs/wController/image.js
Normal file
69
libjs/wController/image.js
Normal file
|
@ -0,0 +1,69 @@
|
|||
"use strict";
|
||||
|
||||
var Address = require("../wType/address");
|
||||
|
||||
var Controller = require("./controller");
|
||||
var File = require("./file/file");
|
||||
|
||||
var Image = Controller.inherit({
|
||||
"className": "Image",
|
||||
"constructor": function(addr) {
|
||||
Controller.fn.constructor.call(this, addr);
|
||||
|
||||
this.data = undefined;
|
||||
this._hasCtrl = false;
|
||||
this._fileCtrl = undefined;
|
||||
this._need = 0;
|
||||
|
||||
this.addHandler("get");
|
||||
},
|
||||
"dontNeedData": function() {
|
||||
--this._need;
|
||||
},
|
||||
"getMimeType": function () {
|
||||
return this._fileCtrl.getMimeType();
|
||||
},
|
||||
"hasData": function() {
|
||||
if (this._hasCtrl) {
|
||||
return this._fileCtrl.hasData();
|
||||
}
|
||||
return false;
|
||||
},
|
||||
"_h_get": function(ev) {
|
||||
var data = ev.getData();
|
||||
|
||||
if (this._hasCtrl) {
|
||||
this.removeForeignController(this._fileCtrl);
|
||||
this._fileCtrl.destructor();
|
||||
delete this._fileCtrl;
|
||||
this._hasCtrl = false;
|
||||
}
|
||||
var strId = data.at("data").toString();
|
||||
if (strId !== "0") {
|
||||
this._fileCtrl = new File(new Address(["images", strId]));
|
||||
this.addForeignController("Corax", this._fileCtrl);
|
||||
|
||||
this._fileCtrl.on("data", this._onControllerData, this);
|
||||
|
||||
this._hasCtrl = true;
|
||||
if (this._need > 0) {
|
||||
this._fileCtrl.needData();
|
||||
}
|
||||
} else {
|
||||
this.trigger("clear");
|
||||
}
|
||||
},
|
||||
"needData": function() {
|
||||
if (this._need === 0 && this._hasCtrl) {
|
||||
this._fileCtrl.needData();
|
||||
}
|
||||
++this._need;
|
||||
},
|
||||
"_onControllerData": function() {
|
||||
this.data = this._fileCtrl.data;
|
||||
|
||||
this.trigger("data");
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Image;
|
40
libjs/wController/imagePane.js
Normal file
40
libjs/wController/imagePane.js
Normal file
|
@ -0,0 +1,40 @@
|
|||
"use strict";
|
||||
|
||||
var Address = require("../wType/address");
|
||||
|
||||
var Vocabulary = require("./vocabulary");
|
||||
var File = require("./file/file");
|
||||
|
||||
var ImagePane = Vocabulary.inherit({
|
||||
"className": "ImagePane",
|
||||
"constructor": function(addr) {
|
||||
Vocabulary.fn.constructor.call(this, addr);
|
||||
|
||||
this._hasImage = false;
|
||||
this.image = null;
|
||||
},
|
||||
"addElement": function(key, element) {
|
||||
if (key === "image" && !this._hasImage) {
|
||||
this._hasImage = true;
|
||||
this.image = new File(new Address(["images", element.toString()]));
|
||||
this.addForeignController("Corax", this.image);
|
||||
}
|
||||
Vocabulary.fn.addElement.call(this, key, element);
|
||||
},
|
||||
"hasImage": function() {
|
||||
return this._hasImage;
|
||||
},
|
||||
"removeElement": function(key) {
|
||||
Vocabulary.fn.removeElement.call(this, key);
|
||||
|
||||
if (key === "image" && this._hasImage) {
|
||||
this.removeForeignController(this.image);
|
||||
|
||||
this._hasImage = false;
|
||||
this.image.destructor();
|
||||
this.image = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = ImagePane;
|
38
libjs/wController/link.js
Normal file
38
libjs/wController/link.js
Normal file
|
@ -0,0 +1,38 @@
|
|||
"use strict";
|
||||
|
||||
var Controller = require("./controller");
|
||||
var String = require("./string");
|
||||
|
||||
var Address = require("../wType/address");
|
||||
|
||||
var Link = Controller.inherit({
|
||||
"className": "Link",
|
||||
"constructor": function(addr) {
|
||||
Controller.fn.constructor.call(this, addr);
|
||||
|
||||
var hop = new Address(["label"]);
|
||||
|
||||
this.targetAddress = new Address([]);
|
||||
this.label = new String(addr['+'](hop));
|
||||
|
||||
this.addController(this.label);
|
||||
|
||||
this.addHandler("get");
|
||||
|
||||
hop.destructor();
|
||||
},
|
||||
"destructor": function() {
|
||||
this.targetAddress.destructor();
|
||||
|
||||
Controller.fn.destructor.call(this);
|
||||
},
|
||||
"_h_get": function(ev) {
|
||||
var data = ev.getData();
|
||||
|
||||
this.targetAddress = data.at("targetAddress").clone();
|
||||
|
||||
this.trigger("data", this.targetAddress);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Link;
|
51
libjs/wController/list.js
Normal file
51
libjs/wController/list.js
Normal file
|
@ -0,0 +1,51 @@
|
|||
"use strict";
|
||||
var Controller = require("./controller");
|
||||
var Vector = require("../wType/vector");
|
||||
|
||||
var List = Controller.inherit({
|
||||
"className": "List",
|
||||
"constructor": function(addr) {
|
||||
Controller.fn.constructor.call(this, addr);
|
||||
|
||||
this.data = new Vector();
|
||||
|
||||
this.addHandler("get");
|
||||
this.addHandler("push");
|
||||
this.addHandler("clear");
|
||||
},
|
||||
"destructor": function() {
|
||||
this.data.destructor();
|
||||
|
||||
Controller.fn.destructor.call(this);
|
||||
},
|
||||
"addElement": function(element) {
|
||||
this.data.push(element);
|
||||
this.trigger("newElement", element);
|
||||
},
|
||||
"clear": function() {
|
||||
this.data.clear();
|
||||
this.trigger("clear");
|
||||
},
|
||||
"_h_clear": function(ev) {
|
||||
this.clear();
|
||||
},
|
||||
"_h_get": function(ev) {
|
||||
this.clear();
|
||||
|
||||
var data = ev.getData().at("data");
|
||||
var size = data.length();
|
||||
for (var i = 0; i < size; ++i) {
|
||||
this.addElement(data.at(i).clone());
|
||||
}
|
||||
this.initialized = true;
|
||||
this.trigger("data");
|
||||
},
|
||||
"_h_push": function(ev) {
|
||||
var data = ev.getData();
|
||||
|
||||
var element = data.at("data").clone();
|
||||
this.addElement(element);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = List;
|
28
libjs/wController/localModel.js
Normal file
28
libjs/wController/localModel.js
Normal file
|
@ -0,0 +1,28 @@
|
|||
"use strict";
|
||||
var counter = 0;
|
||||
var Subscribable = require("../utils/subscribable");
|
||||
|
||||
var LocalModel = Subscribable.inherit({
|
||||
"className": "LocalModel",
|
||||
"constructor": function(properties) {
|
||||
Subscribable.fn.constructor.call(this);
|
||||
|
||||
this.properties = [];
|
||||
this._controllers = [];
|
||||
|
||||
if (properties) {
|
||||
for (var key in properties) {
|
||||
if (properties.hasOwnProperty(key)) {
|
||||
var pair = {p: key, k: properties[key]};
|
||||
this.properties.push(pair);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"setData": function(data) {
|
||||
this.data = data;
|
||||
this.trigger("data");
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = LocalModel;
|
24
libjs/wController/navigationPanel.js
Normal file
24
libjs/wController/navigationPanel.js
Normal file
|
@ -0,0 +1,24 @@
|
|||
"use strict";
|
||||
var List = require("./list");
|
||||
var Link = require("./link");
|
||||
|
||||
var NavigationPanel = List.inherit({
|
||||
"className": "NavigationPanel",
|
||||
"constructor": function(addr) {
|
||||
List.fn.constructor.call(this, addr);
|
||||
},
|
||||
"addElement": function(element) {
|
||||
var address = element.at("address").clone();
|
||||
|
||||
var ctrl = new Link(address);
|
||||
this.addController(ctrl);
|
||||
|
||||
List.fn.addElement.call(this, element);
|
||||
},
|
||||
"clear": function() {
|
||||
List.fn.clear.call(this);
|
||||
this.clearChildren();
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = NavigationPanel;
|
120
libjs/wController/page.js
Normal file
120
libjs/wController/page.js
Normal file
|
@ -0,0 +1,120 @@
|
|||
"use strict";
|
||||
|
||||
var Controller = require("./controller");
|
||||
var String = require("./string");
|
||||
|
||||
var Vocabulary = require("../wType/vocabulary");
|
||||
var Address = require("../wType/address");
|
||||
|
||||
var AbstractMap = require("../wContainer/abstractmap");
|
||||
var ContentMap = AbstractMap.template(Address, Object);
|
||||
|
||||
var Page = Controller.inherit({
|
||||
"className": "Page",
|
||||
"constructor": function(addr) {
|
||||
Controller.fn.constructor.call(this, addr);
|
||||
|
||||
this.data = new ContentMap(false);
|
||||
|
||||
this.addHandler("get");
|
||||
this.addHandler("addItem");
|
||||
this.addHandler("removeItem");
|
||||
this.addHandler("clear");
|
||||
|
||||
this.elements = [];
|
||||
},
|
||||
"destructor": function() {
|
||||
this.data.destructor();
|
||||
|
||||
Controller.fn.destructor.call(this);
|
||||
},
|
||||
"addItem": function(element) {
|
||||
var type = element.at("type").valueOf();
|
||||
var address = element.at("address").clone();
|
||||
var col = element.at("col").valueOf();
|
||||
var row = element.at("row").valueOf();
|
||||
var colspan = element.at("colspan").valueOf();
|
||||
var rowspan = element.at("rowspan").valueOf();
|
||||
var aligment = element.at("aligment").valueOf();
|
||||
var viewType = element.at("viewType").valueOf();
|
||||
var opts = Page.deserializeOptions(element.at("viewOptions"));
|
||||
|
||||
var controller = Page.createByType(type, address);
|
||||
this.addController(controller);
|
||||
|
||||
var el = {
|
||||
type: type,
|
||||
col: col,
|
||||
row: row,
|
||||
colspan: colspan,
|
||||
rowspan: rowspan,
|
||||
aligment: aligment,
|
||||
viewType: viewType,
|
||||
viewOptions: opts,
|
||||
controller: controller
|
||||
}
|
||||
this.data.insert(address, el);
|
||||
this.trigger("addItem", address, el);
|
||||
},
|
||||
"clear": function() {
|
||||
this.data.clear();
|
||||
this.trigger("clear");
|
||||
this.clearChildren();
|
||||
},
|
||||
"_h_clear": function(ev) {
|
||||
this.clear();
|
||||
},
|
||||
"_h_get": function(ev) {
|
||||
this.clear();
|
||||
|
||||
var data = ev.getData().at("data");
|
||||
var size = data.length();
|
||||
for (var i = 0; i < size; ++i) {
|
||||
this.addItem(data.at(i).clone());
|
||||
}
|
||||
},
|
||||
"_h_addItem": function(ev) {
|
||||
var data = ev.getData().clone();
|
||||
|
||||
this.addItem(data);
|
||||
},
|
||||
"_h_removeItem": function(ev) {
|
||||
var data = ev.getData();
|
||||
|
||||
var address = data.at("address").clone();
|
||||
this.removeItem(address);
|
||||
},
|
||||
"removeItem": function(address) {
|
||||
var itr = this.data.find(address);
|
||||
var pair = itr["*"]();
|
||||
this.data.erase(itr);
|
||||
|
||||
this.trigger("removeItem", pair.first);
|
||||
|
||||
this.removeController(pair.second.controller);
|
||||
pair.second.controller.destructor();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Page.deserializeOptions = function(vc) {
|
||||
var opts = Object.create(null);
|
||||
var keys = vc.getKeys();
|
||||
|
||||
for (var i = 0; i < keys.length; ++i) {
|
||||
var value = vc.at(keys[i]);
|
||||
|
||||
if (value instanceof Vocabulary) {
|
||||
value = this.deserializeOptions(value);
|
||||
} else if(value instanceof Address) { //todo vector!
|
||||
value = value.clone();
|
||||
} else {
|
||||
value = value.valueOf();
|
||||
}
|
||||
opts[keys[i]] = value;
|
||||
}
|
||||
|
||||
return opts;
|
||||
}
|
||||
|
||||
module.exports = Page;
|
38
libjs/wController/pageStorage.js
Normal file
38
libjs/wController/pageStorage.js
Normal file
|
@ -0,0 +1,38 @@
|
|||
"use strict";
|
||||
var Controller = require("./controller");
|
||||
var Vocabulary = require("../wType/vocabulary");
|
||||
var String = require("../wType/string");
|
||||
|
||||
var PageStorage = Controller.inherit({
|
||||
"className": "PageStorage",
|
||||
"constructor": function(addr) {
|
||||
Controller.fn.constructor.call(this, addr);
|
||||
|
||||
this.addHandler("pageAddress");
|
||||
this.addHandler("pageName");
|
||||
},
|
||||
"getPageAddress": function(url) {
|
||||
var vc = new Vocabulary();
|
||||
|
||||
vc.insert("url", new String(url));
|
||||
this.send(vc, "getPageAddress");
|
||||
},
|
||||
"getPageName": function(address) {
|
||||
var vc = new Vocabulary();
|
||||
|
||||
vc.insert("address", address.clone());
|
||||
this.send(vc, "getPageName");
|
||||
},
|
||||
"_h_pageAddress": function(ev) {
|
||||
var data = ev.getData();
|
||||
|
||||
this.trigger("pageAddress", data.at("address").clone());
|
||||
},
|
||||
"_h_pageName": function(ev) {
|
||||
var data = ev.getData();
|
||||
|
||||
this.trigger("pageName", data.at("name").toString());
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = PageStorage;
|
80
libjs/wController/panesList.js
Normal file
80
libjs/wController/panesList.js
Normal file
|
@ -0,0 +1,80 @@
|
|||
"use strict";
|
||||
var List = require("./list");
|
||||
var ImagePane = require("./imagePane");
|
||||
|
||||
var Address = require("../wType/address");
|
||||
|
||||
var PanesList = List.inherit({
|
||||
"className": "PanesList",
|
||||
"constructor": function PanesListModel(addr) {
|
||||
List.fn.constructor.call(this, addr);
|
||||
|
||||
this._subscriptionStart = 0;
|
||||
this._subscriptionEnd = Infinity;
|
||||
},
|
||||
"addElement": function(element) {
|
||||
var size = this.data.length();
|
||||
List.fn.addElement.call(this, element);
|
||||
|
||||
if (size >= this._subscriptionStart && size < this._subscriptionEnd) {
|
||||
var controller = new ImagePane(this._pairAddress["+"](new Address([element.toString()])));
|
||||
this.addController(controller);
|
||||
}
|
||||
},
|
||||
"clear": function() {
|
||||
List.fn.clear.call(this);
|
||||
this.clearChildren();
|
||||
},
|
||||
"setSubscriptionRange": function(s, e) {
|
||||
var needStart = s !== this._subscriptionStart;
|
||||
var needEnd = e !== this._subscriptionEnd;
|
||||
if (needStart || needEnd) {
|
||||
var os = this._subscriptionStart;
|
||||
var oe = this._subscriptionEnd;
|
||||
this._subscriptionStart = s;
|
||||
this._subscriptionEnd = e;
|
||||
if (this._subscribed) {
|
||||
this.trigger("rangeStart");
|
||||
if (needStart) {
|
||||
if (s > os) {
|
||||
var limit = Math.min(s - os, this._controllers.length);
|
||||
for (var i = 0; i < limit; ++i) {
|
||||
var ctrl = this._controllers[0];
|
||||
this._removeControllerByIndex(0);
|
||||
ctrl.destructor();
|
||||
}
|
||||
} else {
|
||||
var limit = Math.min(os, e) - s;
|
||||
for (var i = 0; i < limit; ++i) {
|
||||
var ctrl = new ImagePane(this._pairAddress["+"](new Address([this.data.at(i + s).toString()])));
|
||||
this.addController(ctrl, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (needEnd) {
|
||||
var ce = Math.min(this.data.length(), e);
|
||||
var coe = Math.min(this.data.length(), oe);
|
||||
if (ce > coe) {
|
||||
var start = Math.max(s, oe);
|
||||
var amount = ce - start; //it can be negative, it's fine
|
||||
for (var i = 0; i < amount; ++i) {
|
||||
var ctrl = new ImagePane(this._pairAddress["+"](new Address([this.data.at(start + i).toString()])));
|
||||
this.addController(ctrl);
|
||||
}
|
||||
} else if (ce < coe) {
|
||||
var amount = Math.min(coe - ce, coe - os);
|
||||
for (var i = 0; i < amount; ++i) {
|
||||
var index = this._controllers.length - 1;
|
||||
var ctrl = this._controllers[index];
|
||||
this._removeControllerByIndex(index);
|
||||
ctrl.destructor();
|
||||
}
|
||||
}
|
||||
}
|
||||
this.trigger("rangeEnd");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = PanesList;
|
22
libjs/wController/string.js
Normal file
22
libjs/wController/string.js
Normal file
|
@ -0,0 +1,22 @@
|
|||
"use strict";
|
||||
var Controller = require("./controller");
|
||||
|
||||
var String = Controller.inherit({
|
||||
"className": "String",
|
||||
"constructor": function(addr) {
|
||||
Controller.fn.constructor.call(this, addr);
|
||||
|
||||
this.data = "";
|
||||
|
||||
this.addHandler("get");
|
||||
},
|
||||
"_h_get": function(ev) {
|
||||
var data = ev.getData();
|
||||
|
||||
this.data = data.at("data").toString();
|
||||
|
||||
this.trigger("data");
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = String;
|
31
libjs/wController/theme.js
Normal file
31
libjs/wController/theme.js
Normal file
|
@ -0,0 +1,31 @@
|
|||
"use strict";
|
||||
var Controller = require("./controller");
|
||||
|
||||
var Theme = Controller.inherit({
|
||||
"className": "Theme",
|
||||
"constructor": function(addr) {
|
||||
Controller.fn.constructor.call(this, addr);
|
||||
|
||||
this._data = {};
|
||||
this._deferredReady = this._onReady.bind(this);
|
||||
|
||||
this.addHandler("get");
|
||||
},
|
||||
"_h_get": function(ev) {
|
||||
var pairs = ev.getData();
|
||||
this.trigger("clear");
|
||||
|
||||
var data = pairs.at("data");
|
||||
var keys = data.getKeys();
|
||||
for (var i = 0; i < keys.length; ++i) {
|
||||
this._data[keys[i]] = data.at(keys[i]).valueOf()
|
||||
}
|
||||
|
||||
setTimeout(this._deferredReady, 1);
|
||||
},
|
||||
"_onReady": function() {
|
||||
this.trigger("ready", this._data);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Theme;
|
56
libjs/wController/themeSelecter.js
Normal file
56
libjs/wController/themeSelecter.js
Normal file
|
@ -0,0 +1,56 @@
|
|||
"use strict";
|
||||
var Controller = require("./controller");
|
||||
|
||||
var ThemeSelecter = Controller.inherit({
|
||||
"className": "ThemeSelecter",
|
||||
"constructor": function(addr) {
|
||||
Controller.fn.constructor.call(this, addr);
|
||||
|
||||
this._data = {};
|
||||
this._selected = undefined;
|
||||
|
||||
this.addHandler("get");
|
||||
this.addHandler("insert");
|
||||
},
|
||||
"destructor": function() {
|
||||
for (var i = 0; i < this._views.length; ++i) {
|
||||
this._views[i].off("select", this.select, this);
|
||||
}
|
||||
|
||||
Controller.fn.destructor.call(this);
|
||||
},
|
||||
"addView": function(view) {
|
||||
Controller.fn.addView.call(this, view);
|
||||
|
||||
view.on("select", this.select, this);
|
||||
},
|
||||
"_h_get": function(ev) {
|
||||
var pairs = ev.getData();
|
||||
this.trigger("clear");
|
||||
|
||||
var data = pairs.at("data");
|
||||
var keys = data.getKeys();
|
||||
for (var i = 0; i < keys.length; ++i) {
|
||||
this._data[keys[i]] = data.at(keys[i]).clone()
|
||||
this.trigger("newElement", {key: keys[i], value: this._data[keys[i]] });
|
||||
}
|
||||
this.select(pairs.at("default").toString());
|
||||
},
|
||||
"_h_insert": function(ev) {
|
||||
var data = ev.getData();
|
||||
|
||||
var key = data.at().toString();
|
||||
var value = data.at().clone()
|
||||
this._data[key] = value;
|
||||
this.trigger("newElement", {key: key, value: value});
|
||||
},
|
||||
"select": function(key) {
|
||||
if (!this._data[key]) {
|
||||
throw new Error("No such key");
|
||||
}
|
||||
this._selected = key;
|
||||
this.trigger("selected", {key: key, value: this._data[key]});
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = ThemeSelecter;
|
69
libjs/wController/vocabulary.js
Normal file
69
libjs/wController/vocabulary.js
Normal file
|
@ -0,0 +1,69 @@
|
|||
"use strict";
|
||||
var Controller = require("./controller");
|
||||
var WVocabulary = require("../wType/vocabulary");
|
||||
|
||||
var Vocabulary = Controller.inherit({
|
||||
"className": "Vocabulary",
|
||||
"constructor": function(addr) {
|
||||
Controller.fn.constructor.call(this, addr);
|
||||
|
||||
this.data = new WVocabulary();
|
||||
|
||||
this.addHandler("get");
|
||||
this.addHandler("change");
|
||||
this.addHandler("clear");
|
||||
},
|
||||
"destructor": function() {
|
||||
this.data.destructor();
|
||||
|
||||
Controller.fn.destructor.call(this);
|
||||
},
|
||||
"addElement": function(key, element) {
|
||||
this.data.insert(key, element);
|
||||
this.trigger("newElement", key, element);
|
||||
},
|
||||
"removeElement": function(key) {
|
||||
this.data.erase(key);
|
||||
this.trigger("removeElement", key);
|
||||
},
|
||||
"clear": function() {
|
||||
this.data.clear();
|
||||
this.trigger("clear");
|
||||
},
|
||||
"_h_change": function(ev) {
|
||||
var key;
|
||||
var data = ev.getData();
|
||||
|
||||
var erase = data.at("erase");
|
||||
var insert = data.at("insert");
|
||||
|
||||
var eSize = erase.length();
|
||||
for (var i = 0; i < eSize; ++i) {
|
||||
key = erase.at(i).toString();;
|
||||
this.removeElement(key);
|
||||
}
|
||||
|
||||
var keys = insert.getKeys();
|
||||
for (var j = 0; j < keys.length; ++j) {
|
||||
key = keys[i];
|
||||
this.addElement(key, insert.at(key).clone());
|
||||
}
|
||||
this.trigger("change", data.clone());
|
||||
},
|
||||
"_h_clear": function(ev) {
|
||||
this.clear();
|
||||
},
|
||||
"_h_get": function(ev) {
|
||||
this.clear();
|
||||
|
||||
var data = ev.getData().at("data");
|
||||
var keys = data.getKeys();
|
||||
for (var i = 0; i < keys.length; ++i) {
|
||||
var key = keys[i];
|
||||
this.addElement(key, data.at(key).clone());
|
||||
}
|
||||
this.trigger("data");
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Vocabulary;
|
7
libjs/wDispatcher/CMakeLists.txt
Normal file
7
libjs/wDispatcher/CMakeLists.txt
Normal file
|
@ -0,0 +1,7 @@
|
|||
cmake_minimum_required(VERSION 2.8.12)
|
||||
|
||||
configure_file(dispatcher.js dispatcher.js)
|
||||
configure_file(defaulthandler.js defaulthandler.js)
|
||||
configure_file(handler.js handler.js)
|
||||
configure_file(logger.js logger.js)
|
||||
configure_file(parentreporter.js parentreporter.js)
|
35
libjs/wDispatcher/defaulthandler.js
Normal file
35
libjs/wDispatcher/defaulthandler.js
Normal file
|
@ -0,0 +1,35 @@
|
|||
"use strict";
|
||||
var Class = require("../utils/class");
|
||||
var id = 0;
|
||||
|
||||
var DefaultHandler = Class.inherit({
|
||||
"className": "DefaultHandler",
|
||||
"constructor": function() {
|
||||
Class.fn.constructor.call(this);
|
||||
|
||||
this._id = id++;
|
||||
},
|
||||
"==": function(other) {
|
||||
if (!(other instanceof DefaultHandler)) {
|
||||
throw new Error("Can compare only DefaultHandler with DefaultHandler");
|
||||
}
|
||||
return this._id === other._id;
|
||||
},
|
||||
">": function(other) {
|
||||
if (!(other instanceof DefaultHandler)) {
|
||||
throw new Error("Can compare only DefaultHandler with DefaultHandler");
|
||||
}
|
||||
return this._id > other._id;
|
||||
},
|
||||
"<": function(other) {
|
||||
if (!(other instanceof DefaultHandler)) {
|
||||
throw new Error("Can compare only DefaultHandler with DefaultHandler");
|
||||
}
|
||||
return this._id < other._id;
|
||||
},
|
||||
"call": function(event) {
|
||||
throw new Error("Attempt to call pure abstract default handler");
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = DefaultHandler;
|
91
libjs/wDispatcher/dispatcher.js
Normal file
91
libjs/wDispatcher/dispatcher.js
Normal file
|
@ -0,0 +1,91 @@
|
|||
"use strict";
|
||||
var Class = require("../utils/class");
|
||||
var Handler = require("./handler");
|
||||
var DefaultHandler = require("./defaulthandler");
|
||||
var Address = require("../wType/address");
|
||||
var AbstractMap = require("../wContainer/abstractmap");
|
||||
var AbstractOrder = require("../wContainer/abstractorder");
|
||||
|
||||
var HandlerOrder = AbstractOrder.template(Handler);
|
||||
var DefaultHandlerOrder = AbstractOrder.template(DefaultHandler);
|
||||
var HandlerMap = AbstractMap.template(Address, HandlerOrder);
|
||||
|
||||
var Dispatcher = Class.inherit({
|
||||
"className": "Dispatcher",
|
||||
"constructor": function() {
|
||||
Class.fn.constructor.call(this);
|
||||
|
||||
this._handlers = new HandlerMap();
|
||||
this._defautHandlers = new DefaultHandlerOrder(false);
|
||||
},
|
||||
"destructor": function() {
|
||||
this._handlers.destructor();
|
||||
|
||||
Class.fn.destructor.call(this);
|
||||
},
|
||||
"registerHandler": function(handler) {
|
||||
var itr = this._handlers.find(handler.address);
|
||||
var order;
|
||||
|
||||
|
||||
if (itr["=="](this._handlers.end())) {
|
||||
order = new HandlerOrder(false);
|
||||
this._handlers.insert(handler.address.clone(), order);
|
||||
} else {
|
||||
order = itr["*"]();
|
||||
}
|
||||
|
||||
order.push_back(handler);
|
||||
},
|
||||
"unregisterHandler": function(handler) {
|
||||
var itr = this._handlers.find(handler.address);
|
||||
|
||||
if (!itr["=="](this._handlers.end())) {
|
||||
|
||||
var ord = itr["*"]().second;
|
||||
ord.erase(handler);
|
||||
|
||||
if (ord.size() === 0) {
|
||||
this._handlers.erase(itr);
|
||||
}
|
||||
|
||||
} else {
|
||||
throw new Error("Can't unregister hander");
|
||||
}
|
||||
},
|
||||
"registerDefaultHandler": function(dh) {
|
||||
this._defautHandlers.push_back(dh);
|
||||
},
|
||||
"unregisterDefaultHandler": function(dh) {
|
||||
this._defautHandlers.erase(dh);
|
||||
},
|
||||
"pass": function(event) {
|
||||
var itr = this._handlers.find(event.getDestination());
|
||||
|
||||
if (!itr["=="](this._handlers.end())) {
|
||||
var ord = itr["*"]().second;
|
||||
|
||||
var o_beg = ord.begin();
|
||||
var o_end = ord.end();
|
||||
var hands = [];
|
||||
|
||||
for (; !o_beg["=="](o_end); o_beg["++"]()) {
|
||||
hands.push(o_beg["*"]());
|
||||
}
|
||||
|
||||
for (var i = 0; i < hands.length; ++i) {
|
||||
hands[i].pass(event)
|
||||
}
|
||||
} else {
|
||||
var dhitr = this._defautHandlers.begin();
|
||||
var dhend = this._defautHandlers.end();
|
||||
for (; !dhitr["=="](dhend); dhitr["++"]()) {
|
||||
if (dhitr["*"]().call(event)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Dispatcher;
|
44
libjs/wDispatcher/handler.js
Normal file
44
libjs/wDispatcher/handler.js
Normal file
|
@ -0,0 +1,44 @@
|
|||
"use strict";
|
||||
var Class = require("../utils/class");
|
||||
var id = 0;
|
||||
|
||||
var Handler = Class.inherit({
|
||||
"className": "Handler",
|
||||
"constructor": function(address, instance, method) {
|
||||
Class.fn.constructor.call(this);
|
||||
|
||||
this._id = id++;
|
||||
|
||||
this.address = address;
|
||||
this._ctx = instance;
|
||||
this._mth = method;
|
||||
},
|
||||
"destructor": function() {
|
||||
this.address.destructor();
|
||||
|
||||
Class.fn.destructor.call(this);
|
||||
},
|
||||
"pass": function(event) {
|
||||
this._mth.call(this._ctx, event);
|
||||
},
|
||||
"==": function(other) {
|
||||
if (!(other instanceof Handler)) {
|
||||
throw new Error("Can compare only Handler with Handler");
|
||||
}
|
||||
return this._id === other._id;
|
||||
},
|
||||
">": function(other) {
|
||||
if (!(other instanceof Handler)) {
|
||||
throw new Error("Can compare only Handler with Handler");
|
||||
}
|
||||
return this._id > other._id;
|
||||
},
|
||||
"<": function(other) {
|
||||
if (!(other instanceof Handler)) {
|
||||
throw new Error("Can compare only Handler with Handler");
|
||||
}
|
||||
return this._id < other._id;
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Handler;
|
18
libjs/wDispatcher/logger.js
Normal file
18
libjs/wDispatcher/logger.js
Normal file
|
@ -0,0 +1,18 @@
|
|||
"use strict";
|
||||
var DefaultHandler = require("./defaulthandler");
|
||||
|
||||
var Logger = DefaultHandler.inherit({
|
||||
"className": "Logger",
|
||||
"constructor": function() {
|
||||
DefaultHandler.fn.constructor.call(this);
|
||||
},
|
||||
"call": function(event) {
|
||||
console.log("Event went to default handler");
|
||||
console.log("Destination: " + event.getDestination().toString());
|
||||
console.log("Data: " + event.getData().toString());
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Logger;
|
55
libjs/wDispatcher/parentreporter.js
Normal file
55
libjs/wDispatcher/parentreporter.js
Normal file
|
@ -0,0 +1,55 @@
|
|||
"use strict";
|
||||
|
||||
var DefaultHandler = require("./defaulthandler");
|
||||
var Handler = require("./handler");
|
||||
|
||||
var Address = require("../wType/address");
|
||||
var AbstractMap = require("../wContainer/abstractmap");
|
||||
|
||||
var HandlersMap = AbstractMap.template(Address, Handler);
|
||||
|
||||
var ParentReporter = DefaultHandler.inherit({
|
||||
"className": "ParentReporter",
|
||||
"constructor": function() {
|
||||
DefaultHandler.fn.constructor.call(this);
|
||||
|
||||
this._handlers = new HandlersMap(false);
|
||||
},
|
||||
"destructor": function() {
|
||||
this._handlers.destructor();
|
||||
|
||||
DefaultHandler.fn.destructor.call(this);
|
||||
},
|
||||
"call": function(ev) {
|
||||
var addr = ev.getDestination();
|
||||
var result = [];
|
||||
|
||||
var itr = this._handlers.begin();
|
||||
var end = this._handlers.end();
|
||||
for (; !itr["=="](end); itr["++"]()) {
|
||||
var pair = itr["*"]();
|
||||
if (addr.begins(pair.first)) {
|
||||
result[pair.first.size()] = pair.second; //it's a dirty javascript trick
|
||||
} //I need the longest of matching, and that's how I'm gonna get it
|
||||
}
|
||||
if (result.length) {
|
||||
result[result.length - 1].pass(ev);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
"registerParent": function(parentAddr, handler) {
|
||||
this._handlers.insert(parentAddr, handler);
|
||||
},
|
||||
"unregisterParent": function(parentAddr) {
|
||||
var itr = this._handlers.find(parentAddr);
|
||||
if (!itr["=="](this._handlers.end())) {
|
||||
this._handlers.erase(itr);
|
||||
} else {
|
||||
throw new Error("An attempt to unregister unregistered parent in ParentReporter");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = ParentReporter;
|
17
libjs/wModel/CMakeLists.txt
Normal file
17
libjs/wModel/CMakeLists.txt
Normal file
|
@ -0,0 +1,17 @@
|
|||
cmake_minimum_required(VERSION 2.8.12)
|
||||
|
||||
configure_file(model.js model.js)
|
||||
configure_file(globalControls.js globalControls.js)
|
||||
configure_file(link.js link.js)
|
||||
configure_file(list.js list.js)
|
||||
configure_file(page.js page.js)
|
||||
configure_file(pageStorage.js pageStorage.js)
|
||||
configure_file(panesList.js panesList.js)
|
||||
configure_file(string.js string.js)
|
||||
configure_file(theme.js theme.js)
|
||||
configure_file(themeStorage.js themeStorage.js)
|
||||
configure_file(vocabulary.js vocabulary.js)
|
||||
configure_file(attributes.js attributes.js)
|
||||
configure_file(image.js image.js)
|
||||
|
||||
add_subdirectory(proxy)
|
44
libjs/wModel/attributes.js
Normal file
44
libjs/wModel/attributes.js
Normal file
|
@ -0,0 +1,44 @@
|
|||
"use strict";
|
||||
|
||||
var ModelVocabulary = require("./vocabulary");
|
||||
var Vocabulary = require("../wType/vocabulary");
|
||||
var String = require("../wType/string");
|
||||
var Uint64 = require("../wType/uint64");
|
||||
|
||||
var Attributes = ModelVocabulary.inherit({
|
||||
"className": "Attributes",
|
||||
"constructor": function(addr) {
|
||||
ModelVocabulary.fn.constructor.call(this, addr);
|
||||
|
||||
this._attributes = global.Object.create(null);
|
||||
},
|
||||
"addAttribute": function(key, model) {
|
||||
var old = this._attributes[key];
|
||||
if (old) {
|
||||
throw new Error("Attribute with key " + key + " already exists");
|
||||
}
|
||||
this._attributes[key] = model;
|
||||
this.addModel(model);
|
||||
|
||||
var vc = new Vocabulary();
|
||||
vc.insert("name", new String(key));
|
||||
vc.insert("address", model.getAddress());
|
||||
vc.insert("type", new Uint64(model.getType()));
|
||||
this.insert(key, vc);
|
||||
},
|
||||
"removeAttribute": function(key) {
|
||||
var model = this._attributes[key];
|
||||
if (!model) {
|
||||
throw new Error("An attempt to access non existing Attribute");
|
||||
}
|
||||
delete this._attributes[key];
|
||||
this.erase(key);
|
||||
this.removeModel(model);
|
||||
model.destructor();
|
||||
},
|
||||
"setAttribute": function(key, value) {
|
||||
this._attributes[key].set(value);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Attributes;
|
60
libjs/wModel/globalControls.js
Normal file
60
libjs/wModel/globalControls.js
Normal file
|
@ -0,0 +1,60 @@
|
|||
"use strict";
|
||||
|
||||
var List = require("./list");
|
||||
var Model = require("./model");
|
||||
var ModelString = require("./string");
|
||||
var ModelLink = require("./link");
|
||||
var ThemeStorage = require("./themeStorage");
|
||||
var Vocabulary = require("../wType/vocabulary");
|
||||
var Address = require("../wType/address");
|
||||
var String = require("../wType/string");
|
||||
|
||||
var GlobalControls = List.inherit({
|
||||
"className": "GlobalControls",
|
||||
"constructor": function(address) {
|
||||
List.fn.constructor.call(this, address);
|
||||
|
||||
this._initModels()
|
||||
},
|
||||
"addModel": function(name, model) {
|
||||
List.fn.addModel.call(this, model);
|
||||
|
||||
var vc = new Vocabulary();
|
||||
vc.insert("type", new String(model.className));
|
||||
vc.insert("address", model.getAddress());
|
||||
vc.insert("name", new String(name));
|
||||
|
||||
this.push(vc);
|
||||
},
|
||||
"addModelAsLink": function(name, model) {
|
||||
var vc = new Vocabulary();
|
||||
vc.insert("type", new String(model.className));
|
||||
vc.insert("address", model.getAddress());
|
||||
vc.insert("name", new String(name));
|
||||
|
||||
this.push(vc);
|
||||
},
|
||||
"_initModels": function() {
|
||||
var navigationPanel = this._np = new List(this._address["+"](new Address(["navigationPanel"])));
|
||||
|
||||
navigationPanel.addProperty("backgroundColor", "primaryColor");
|
||||
this.addModel("navigationPanel", navigationPanel);
|
||||
|
||||
var ts = new ThemeStorage(this._address["+"](new Address(["themes"])));
|
||||
this.addModel("themes", ts);
|
||||
},
|
||||
"addNav": function(name, address) {
|
||||
var vc = new Vocabulary();
|
||||
|
||||
var model = new ModelLink(this._np._address["+"](new Address(["" + this._np._data.length()])), name, address);
|
||||
model.label.addProperty("fontSize", "largeFontSize");
|
||||
model.label.addProperty("fontFamily", "largeFont");
|
||||
model.label.addProperty("color", "primaryFontColor");
|
||||
this._np.addModel(model);
|
||||
|
||||
vc.insert("address", model.getAddress());
|
||||
this._np.push(vc);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = GlobalControls;
|
47
libjs/wModel/image.js
Normal file
47
libjs/wModel/image.js
Normal file
|
@ -0,0 +1,47 @@
|
|||
"use strict";
|
||||
|
||||
var Model = require("./model");
|
||||
var Uint64 = require("../wType/uint64");
|
||||
var Address = require("../wType/address");
|
||||
var Vocabulary = require("../wType/vocabulary");
|
||||
|
||||
var ModelImage = Model.inherit({
|
||||
"className": "Image",
|
||||
"constructor": function(address, uint64) {
|
||||
Model.fn.constructor.call(this, address);
|
||||
|
||||
this._data = uint64;
|
||||
|
||||
this.addHandler("get");
|
||||
},
|
||||
"destructor": function() {
|
||||
this._data.destructor();
|
||||
|
||||
Model.fn.destructor.call(this);
|
||||
},
|
||||
"_h_subscribe": function(ev) {
|
||||
Model.fn._h_subscribe.call(this, ev);
|
||||
|
||||
this._h_get(ev);
|
||||
},
|
||||
"_h_get": function(ev) {
|
||||
var vc = new Vocabulary();
|
||||
|
||||
vc.insert("data", this._data.clone());
|
||||
this.response(vc, "get", ev);
|
||||
},
|
||||
"set": function(uint64) {
|
||||
this._data.destructor();
|
||||
|
||||
this._data = uint64;
|
||||
|
||||
if (this._registered) {
|
||||
var vc = new Vocabulary();
|
||||
|
||||
vc.insert("data", this._data.clone());
|
||||
this.broadcast(vc, "get");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = ModelImage;
|
44
libjs/wModel/link.js
Normal file
44
libjs/wModel/link.js
Normal file
|
@ -0,0 +1,44 @@
|
|||
"use strict";
|
||||
|
||||
var Model = require("./model");
|
||||
var ModelString = require("./string")
|
||||
|
||||
var String = require("../wType/string");
|
||||
|
||||
var Vocabulary = require("../wType/vocabulary");
|
||||
var Address = require("../wType/address");
|
||||
|
||||
var Link = Model.inherit({
|
||||
"className": "Link",
|
||||
"constructor": function(addr, text, tAddress) {
|
||||
Model.fn.constructor.call(this, addr);
|
||||
|
||||
this.addHandler("get");
|
||||
|
||||
this._targetAddress = tAddress;
|
||||
|
||||
var hop = new Address(["label"]);
|
||||
this.label = new ModelString(addr["+"](hop), text);
|
||||
this.addModel(this.label);
|
||||
|
||||
hop.destructor();
|
||||
},
|
||||
"destructor": function() {
|
||||
this._targetAddress.destructor();
|
||||
|
||||
Model.fn.destructor.call(this);
|
||||
},
|
||||
"_h_get": function(ev) {
|
||||
var vc = new Vocabulary();
|
||||
|
||||
vc.insert("targetAddress", this._targetAddress.clone());
|
||||
this.response(vc, "get", ev);
|
||||
},
|
||||
"_h_subscribe": function(ev) {
|
||||
Model.fn._h_subscribe.call(this, ev);
|
||||
|
||||
this._h_get(ev);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Link;
|
51
libjs/wModel/list.js
Normal file
51
libjs/wModel/list.js
Normal file
|
@ -0,0 +1,51 @@
|
|||
"use strict";
|
||||
|
||||
var Model = require("./model");
|
||||
var Vector = require("../wType/vector");
|
||||
var Vocabulary = require("../wType/vocabulary");
|
||||
var Object = require("../wType/object")
|
||||
|
||||
var List = Model.inherit({
|
||||
"className": "List",
|
||||
"constructor": function(address) {
|
||||
Model.fn.constructor.call(this, address);
|
||||
|
||||
this._data = new Vector();
|
||||
|
||||
this.addHandler("get");
|
||||
},
|
||||
"destructor": function() {
|
||||
this._data.destructor();
|
||||
|
||||
Model.fn.destructor.call(this);
|
||||
},
|
||||
"clear": function() {
|
||||
this._data.clear();
|
||||
|
||||
this.broadcast(new Vocabulary(), "clear");
|
||||
},
|
||||
"_h_subscribe": function(ev) {
|
||||
Model.fn._h_subscribe.call(this, ev);
|
||||
|
||||
this._h_get(ev);
|
||||
},
|
||||
"_h_get": function(ev) {
|
||||
var vc = new Vocabulary();
|
||||
|
||||
vc.insert("data", this._data.clone());
|
||||
this.response(vc, "get", ev);
|
||||
},
|
||||
"push": function(obj) {
|
||||
if (!(obj instanceof Object)) {
|
||||
throw new Error("An attempt to push into list unserializable value");
|
||||
}
|
||||
this._data.push(obj);
|
||||
|
||||
var vc = new Vocabulary();
|
||||
vc.insert("data", obj.clone());
|
||||
|
||||
this.broadcast(vc, "push");
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = List;
|
316
libjs/wModel/model.js
Normal file
316
libjs/wModel/model.js
Normal file
|
@ -0,0 +1,316 @@
|
|||
"use strict";
|
||||
var Subscribable = require("../utils/subscribable");
|
||||
var AbstcractMap = require("../wContainer/abstractmap");
|
||||
var AbstractOrder = require("../wContainer/abstractorder");
|
||||
var Address = require("../wType/address");
|
||||
var Uint64 = require("../wType/uint64");
|
||||
var Event = require("../wType/event");
|
||||
var Vector = require("../wType/vector");
|
||||
var Vocabulary = require("../wType/vocabulary");
|
||||
var String = require("../wType/string");
|
||||
var Handler = require("../wDispatcher/handler");
|
||||
|
||||
var Model = Subscribable.inherit({
|
||||
"className": "Model",
|
||||
"constructor": function(address) {
|
||||
Subscribable.fn.constructor.call(this);
|
||||
|
||||
var SMap = AbstcractMap.template(Uint64, Model.addressOrder);
|
||||
|
||||
this._registered = false;
|
||||
this._subscribers = new SMap(false);
|
||||
this._handlers = [];
|
||||
this._models = [];
|
||||
this._props = new Vector();
|
||||
this._address = address;
|
||||
this._subscribersCount = 0;
|
||||
|
||||
this.addHandler("subscribe");
|
||||
this.addHandler("unsubscribe");
|
||||
},
|
||||
"destructor": function() {
|
||||
var i;
|
||||
if (this._registered) {
|
||||
this.unregister();
|
||||
}
|
||||
|
||||
this._subscribers.destructor();
|
||||
|
||||
for (i = 0; i < this._models.length; ++i) {
|
||||
this._models[i].destructor();
|
||||
}
|
||||
|
||||
for (i = 0; i < this._handlers.length; ++i) {
|
||||
this._handlers[i].destructor();
|
||||
}
|
||||
this._props.destructor();
|
||||
|
||||
Subscribable.fn.destructor.call(this);
|
||||
},
|
||||
"addHandler": function(name) {
|
||||
if (!(this["_h_" + name] instanceof Function)) {
|
||||
throw new Error("An attempt to create handler without a handling method");
|
||||
}
|
||||
|
||||
var handler = new Handler(this._address["+"](new Address([name])), this, this["_h_" + name]);
|
||||
|
||||
this._addHandler(handler);
|
||||
},
|
||||
"_addHandler": function(handler) {
|
||||
this._handlers.push(handler);
|
||||
if (this._registered) {
|
||||
this._dp.registerHandler(handler);
|
||||
}
|
||||
},
|
||||
"addModel": function(model) {
|
||||
if (!(model instanceof Model)) {
|
||||
throw new Error("An attempt to add not a model into " + this.className);
|
||||
}
|
||||
this._models.push(model);
|
||||
model.on("serviceMessage", this._onModelServiceMessage, this);
|
||||
if (this._registered) {
|
||||
model.register(this._dp, this._server);
|
||||
}
|
||||
},
|
||||
"addProperty": function(property, key) {
|
||||
var vc = new Vocabulary();
|
||||
vc.insert("property", new String(property));
|
||||
vc.insert("key", new String(key));
|
||||
|
||||
this._props.push(vc);
|
||||
|
||||
if (this._registered) {
|
||||
var nvc = new Vocabulary();
|
||||
nvc.insert("properties", this._props.clone());
|
||||
this.broadcast(nvc, "properties");
|
||||
}
|
||||
},
|
||||
"broadcast": function(vc, handler) {
|
||||
var itr = this._subscribers.begin();
|
||||
var end = this._subscribers.end();
|
||||
vc.insert("source", this._address.clone());
|
||||
|
||||
for (;!itr["=="](end); itr["++"]()) {
|
||||
var obj = itr["*"]();
|
||||
var order = obj.second;
|
||||
var socket = this._server.getConnection(obj.first);
|
||||
var oItr = order.begin();
|
||||
var oEnd = order.end();
|
||||
for (;!oItr["=="](oEnd); oItr["++"]()) {
|
||||
var addr = oItr["*"]()["+"](new Address([handler]));
|
||||
var ev = new Event(addr, vc.clone());
|
||||
ev.setSenderId(socket.getId().clone());
|
||||
socket.send(ev);
|
||||
ev.destructor();
|
||||
}
|
||||
}
|
||||
vc.destructor();
|
||||
},
|
||||
"getAddress": function() {
|
||||
return this._address.clone();
|
||||
},
|
||||
"getType": function() {
|
||||
var type = Model.ModelType[this.className];
|
||||
if (type === undefined) {
|
||||
throw new Error("Undefined ModelType");
|
||||
}
|
||||
return type;
|
||||
},
|
||||
"_h_subscribe": function(ev) {
|
||||
var id = ev.getSenderId();
|
||||
var source = ev.getData().at("source");
|
||||
|
||||
var itr = this._subscribers.find(id);
|
||||
var ord;
|
||||
if (itr["=="](this._subscribers.end())) {
|
||||
ord = new Model.addressOrder(true);
|
||||
var socket = this._server.getConnection(id);
|
||||
socket.one("disconnected", this._onSocketDisconnected, this);
|
||||
this._subscribers.insert(id.clone(), ord);
|
||||
} else {
|
||||
ord = itr["*"]().second;
|
||||
var oItr = ord.find(source);
|
||||
if (!oItr["=="](ord.end())) {
|
||||
this.trigger("serviceMessage", "id: " + id.toString() + ", " +
|
||||
"source: " + source.toString() + " " +
|
||||
"is trying to subscribe on model " + this._address.toString() + " " +
|
||||
"but it's already subscribed", 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ord.push_back(source.clone());
|
||||
++this._subscribersCount;
|
||||
this.trigger("serviceMessage", this._address.toString() + " has now " + this._subscribersCount + " subscribers", 0);
|
||||
|
||||
var nvc = new Vocabulary();
|
||||
nvc.insert("properties", this._props.clone());
|
||||
|
||||
this.response(nvc, "properties", ev);
|
||||
},
|
||||
"_h_unsubscribe": function(ev) {
|
||||
var id = ev.getSenderId();
|
||||
var source = ev.getData().at("source");
|
||||
|
||||
var itr = this._subscribers.find(id);
|
||||
|
||||
if (itr["=="](this._subscribers.end())) {
|
||||
this.trigger("serviceMessage", "id: " + id.toString() + ", " +
|
||||
"source: " + source.toString() + " " +
|
||||
"is trying to unsubscribe from model " + this._address.toString() + " " +
|
||||
"but even this id is not registered in subscribers map", 1
|
||||
);
|
||||
return
|
||||
}
|
||||
var ord = itr["*"]().second;
|
||||
var oItr = ord.find(source);
|
||||
if (oItr["=="](ord.end())) {
|
||||
this.trigger("serviceMessage", "id: " + id.toString() + ", " +
|
||||
"source: " + source.toString() + " " +
|
||||
"is trying to unsubscribe from model " + this._address.toString() + " " +
|
||||
"but such address is not subscribed to this model", 1
|
||||
);
|
||||
return
|
||||
}
|
||||
ord.erase(oItr["*"]());
|
||||
if (ord.size() === 0) {
|
||||
var socket = this._server.getConnection(itr["*"]().first);
|
||||
socket.off("disconnected", this._onSocketDisconnected, this);
|
||||
this._subscribers.erase(itr);
|
||||
ord.destructor();
|
||||
}
|
||||
|
||||
--this._subscribersCount;
|
||||
this.trigger("serviceMessage", this._address.toString() + " has now " + this._subscribersCount + " subscribers", 0);
|
||||
},
|
||||
"_onModelServiceMessage": function(msg, severity) {
|
||||
this.trigger("serviceMessage", msg, severity);
|
||||
},
|
||||
"_onSocketDisconnected": function(ev, socket) {
|
||||
var id = socket.getId();
|
||||
var itr = this._subscribers.find(id);
|
||||
|
||||
if (itr["=="](this._subscribers.end())) {
|
||||
this.trigger("serviceMessage", "id: " + id.toString() + ", " +
|
||||
"after socket disconnected trying to remove subscriptions from model " +
|
||||
"but id haven't been found in subscribers map", 1);
|
||||
return
|
||||
}
|
||||
var ord = itr["*"]().second;
|
||||
this._subscribersCount -= ord.size();
|
||||
this._subscribers.erase(itr);
|
||||
ord.destructor();
|
||||
this.trigger("serviceMessage", this._address.toString() + " has now " + this._subscribersCount + " subscribers", 0);
|
||||
},
|
||||
"register": function(dp, server) {
|
||||
if (this._registered) {
|
||||
throw new Error("Model " + this._address.toString() + " is already registered");
|
||||
}
|
||||
this._dp = dp;
|
||||
this._server = server;
|
||||
var i;
|
||||
|
||||
for (i = 0; i < this._models.length; ++i) {
|
||||
this._models[i].register(dp, server);
|
||||
}
|
||||
|
||||
for (i = 0; i < this._handlers.length; ++i) {
|
||||
dp.registerHandler(this._handlers[i]);
|
||||
}
|
||||
this._registered = true;
|
||||
},
|
||||
"_removeHandler": function(handler) {
|
||||
var index = this._handlers.indexOf(handler);
|
||||
if (index === -1) {
|
||||
throw new Error("An attempt to remove non existing handler");
|
||||
}
|
||||
this._handlers.splice(index, 1);
|
||||
if (this._registered) {
|
||||
this._dp.unregisterHandler(handler);
|
||||
}
|
||||
},
|
||||
"removeModel": function(model) {
|
||||
if (!(model instanceof Model)) {
|
||||
throw new Error("An attempt to remove not a model from " + this.className);
|
||||
}
|
||||
var index = this._models.indexOf(model);
|
||||
if (index === -1) {
|
||||
throw new Error("An attempt to remove non existing model from " + this.className);
|
||||
}
|
||||
this._models.splice(index, 1);
|
||||
if (this._registered) {
|
||||
model.unregister(this._dp, this._server);
|
||||
}
|
||||
},
|
||||
"response": function(vc, handler, src) {
|
||||
if (!this._registered) {
|
||||
throw new Error("An attempt to send a message from unregistered model " + this._address.toString());
|
||||
}
|
||||
var source = src.getData().at("source").clone();
|
||||
var id = src.getSenderId().clone();
|
||||
var addr = source["+"](new Address([handler]));
|
||||
vc.insert("source", this._address.clone());
|
||||
|
||||
var ev = new Event(addr, vc);
|
||||
ev.setSenderId(id);
|
||||
var socket = this._server.getConnection(id);
|
||||
socket.send(ev);
|
||||
ev.destructor();
|
||||
},
|
||||
"unregister": function() {
|
||||
if (!this._registered) {
|
||||
throw new Error("Model " + this._address.toString() + " is not registered");
|
||||
}
|
||||
var i;
|
||||
|
||||
for (i = 0; i < this._models.length; ++i) {
|
||||
this._models[i].unregister();
|
||||
}
|
||||
|
||||
for (i = 0; i < this._handlers.length; ++i) {
|
||||
this._dp.unregisterHandler(this._handlers[i]);
|
||||
}
|
||||
|
||||
var itr = this._subscribers.begin();
|
||||
var end = this._subscribers.end();
|
||||
|
||||
for (;!itr["=="](end); itr["++"]()) {
|
||||
var socket = this._server.getConnection(itr["*"]().first);
|
||||
var ord = itr["*"]().second;
|
||||
ord.destructor();
|
||||
socket.off("disconnected", this._onSocketDisconnected, this);
|
||||
}
|
||||
this._subscribers.clear();
|
||||
this._subscribersCount = 0;
|
||||
|
||||
delete this._dp;
|
||||
delete this._server;
|
||||
|
||||
this._registered = false;
|
||||
}
|
||||
});
|
||||
|
||||
Model.getModelTypeId = function(model) {
|
||||
return this.ModelType[model.className];
|
||||
}
|
||||
|
||||
Model.addressOrder = AbstractOrder.template(Address);
|
||||
Model.ModelType = {
|
||||
String: 0,
|
||||
List: 1,
|
||||
Vocabulary: 2,
|
||||
Image: 3,
|
||||
Model: 4,
|
||||
|
||||
Attributes: 50,
|
||||
|
||||
GlobalControls: 100,
|
||||
Link: 101,
|
||||
Page: 102,
|
||||
PageStorage: 103,
|
||||
PanesList: 104,
|
||||
Theme: 105,
|
||||
ThemeStorage: 106
|
||||
};
|
||||
|
||||
module.exports = Model;
|
163
libjs/wModel/page.js
Normal file
163
libjs/wModel/page.js
Normal file
|
@ -0,0 +1,163 @@
|
|||
"use strict";
|
||||
|
||||
var Model = require("./model");
|
||||
var AbstractMap = require("../wContainer/abstractmap");
|
||||
var Vocabulary = require("../wType/vocabulary");
|
||||
var Vector = require("../wType/vector");
|
||||
var Address = require("../wType/address");
|
||||
var String = require("../wType/string");
|
||||
var UInt64 = require("../wType/uint64");
|
||||
|
||||
var ContentMap = AbstractMap.template(Address, Vocabulary);
|
||||
|
||||
var Page = Model.inherit({
|
||||
"className": "Page",
|
||||
"constructor": function(address, name) {
|
||||
Model.fn.constructor.call(this, address);
|
||||
|
||||
this._data = new ContentMap(true);
|
||||
this.name = name.toLowerCase();
|
||||
this.urlAddress = [this.name];
|
||||
this._hasParentReporter = false;
|
||||
this._pr = undefined;
|
||||
this._childPages = {};
|
||||
|
||||
this.addHandler("get");
|
||||
this.addHandler("ping");
|
||||
|
||||
this.addProperty("backgroundColor", "mainColor");
|
||||
this.addProperty("color", "mainFontColor");
|
||||
},
|
||||
"destructor": function() {
|
||||
this._data.destructor();
|
||||
|
||||
Model.fn.destructor.call(this);
|
||||
},
|
||||
"addItem": function(model, row, col, rowspan, colspan, aligment, viewType, viewOptions) {
|
||||
Model.fn.addModel.call(this, model);
|
||||
|
||||
var vc = new Vocabulary();
|
||||
viewOptions = viewOptions || new Vocabulary();
|
||||
viewType = viewType || new UInt64(Page.getModelTypeId(model))
|
||||
|
||||
vc.insert("type", new UInt64(Page.getModelTypeId(model)));
|
||||
vc.insert("row", new UInt64(row || 0));
|
||||
vc.insert("col", new UInt64(col || 0));
|
||||
vc.insert("rowspan", new UInt64(rowspan || 1));
|
||||
vc.insert("colspan", new UInt64(colspan || 1));
|
||||
vc.insert("aligment", new UInt64(aligment || Page.Aligment.LeftTop));
|
||||
vc.insert("viewOptions", viewOptions);
|
||||
vc.insert("viewType", viewType);
|
||||
|
||||
this._data.insert(model.getAddress(), vc);
|
||||
|
||||
var evc = vc.clone();
|
||||
evc.insert("address", model.getAddress());
|
||||
|
||||
this.broadcast(evc, "addItem");
|
||||
},
|
||||
"addPage": function(page) {
|
||||
this.addModel(page);
|
||||
var addr = this.urlAddress.slice();
|
||||
addr.push(page.name);
|
||||
page.setUrlAddress(addr)
|
||||
page.on("newPage", this._onNewPage, this);
|
||||
page.on("removePage", this._onRemovePage, this);
|
||||
this._childPages[page.name] = page;
|
||||
|
||||
this.trigger("newPage", page);
|
||||
},
|
||||
"clear": function() {
|
||||
this._data.clear();
|
||||
|
||||
this.broadcast(new Vocabulary(), "clear");
|
||||
},
|
||||
"getChildPage": function(name) {
|
||||
return this._childPages[name];
|
||||
},
|
||||
"_h_get": function(ev) {
|
||||
var data = new Vocabulary();
|
||||
|
||||
var vector = new Vector();
|
||||
var itr = this._data.begin();
|
||||
var end = this._data.end();
|
||||
|
||||
for (; !itr["=="](end); itr["++"]()) {
|
||||
var pair = itr["*"]();
|
||||
var vc = pair.second.clone();
|
||||
|
||||
vc.insert("address", pair.first.clone());
|
||||
vector.push(vc);
|
||||
}
|
||||
|
||||
data.insert("name", new String(this.name));
|
||||
data.insert("data", vector);
|
||||
this.response(data, "get", ev);
|
||||
},
|
||||
"_h_ping": function(ev) {
|
||||
this.trigger("serviceMessage", "page " + this._address.toString() + " got pinged", 0);
|
||||
},
|
||||
"_h_subscribe": function(ev) {
|
||||
Model.fn._h_subscribe.call(this, ev);
|
||||
|
||||
this._h_get(ev);
|
||||
},
|
||||
"_onNewPage": function(page) {
|
||||
this.trigger("newPage", page);
|
||||
},
|
||||
"_onRemovePage": function(page) {
|
||||
this.trigger("removePage", page);
|
||||
},
|
||||
"removeItem": function(model) {
|
||||
Model.fn.removeModel.call(this, model);
|
||||
var addr = model.getAddress();
|
||||
|
||||
var itr = this._data.find(addr);
|
||||
this._data.erase(itr);
|
||||
|
||||
var vc = new Vocabulary();
|
||||
vc.insert("address", addr);
|
||||
|
||||
this.broadcast(vc, "removeItem");
|
||||
},
|
||||
"removePage": function(page) {
|
||||
Model.fn.removeModel.call(this, page);
|
||||
|
||||
delete this._childPages[page.name];
|
||||
page.off("newPage", this._onNewPage, this);
|
||||
page.off("removePage", this._onRemovePage, this);
|
||||
|
||||
this.trigger("removePage", page);
|
||||
},
|
||||
"setParentReporter": function(pr) {
|
||||
if (this._hasParentReporter) {
|
||||
throw new Error("An attempt to set parent reporter to page while another one already exists");
|
||||
}
|
||||
this._pr = pr;
|
||||
this._hasParentReporter = true;
|
||||
},
|
||||
"setUrlAddress": function(address) {
|
||||
this.urlAddress = address;
|
||||
},
|
||||
"unsetParentReporter": function() {
|
||||
if (!this._hasParentReporter) {
|
||||
throw new Error("An attempt to unset parent reporter from page which doesn't have one");
|
||||
}
|
||||
delete this._pr;
|
||||
this._hasParentReporter = false;
|
||||
}
|
||||
});
|
||||
|
||||
Page.Aligment = {
|
||||
"LeftTop": 1,
|
||||
"LeftCenter": 4,
|
||||
"LeftBottom": 7,
|
||||
"CenterTop": 2,
|
||||
"CenterCenter": 5,
|
||||
"CenterBottom": 8,
|
||||
"RightTop": 3,
|
||||
"RightCenter": 6,
|
||||
"RightBottom": 9
|
||||
};
|
||||
|
||||
module.exports = Page;
|
124
libjs/wModel/pageStorage.js
Normal file
124
libjs/wModel/pageStorage.js
Normal file
|
@ -0,0 +1,124 @@
|
|||
"use strict";
|
||||
|
||||
var Model = require("./model");
|
||||
var Page = require("./page");
|
||||
var ModelString = require("./string");
|
||||
var Vocabulary = require("../wType/vocabulary");
|
||||
var Address = require("../wType/address");
|
||||
var String = require("../wType/string");
|
||||
var Event = require("../wType/event");
|
||||
var AbstractMap = require("../wContainer/abstractmap");
|
||||
|
||||
var AddressMap = AbstractMap.template(Address, String);
|
||||
|
||||
var PageStorage = Model.inherit({
|
||||
"className": "PageStorage",
|
||||
"constructor": function(addr, rootPage, pr) {
|
||||
Model.fn.constructor.call(this, addr);
|
||||
|
||||
this._urls = {};
|
||||
this._specialPages = {};
|
||||
this._rMap = new AddressMap(true);
|
||||
this._root = rootPage;
|
||||
this._pr = pr;
|
||||
|
||||
this._initRootPage();
|
||||
this._initNotFoundPage();
|
||||
|
||||
this.addHandler("getPageAddress");
|
||||
this.addHandler("getPageName");
|
||||
},
|
||||
"destructor": function() {
|
||||
this._rMap.destructor();
|
||||
|
||||
Model.fn.destructor.call(this);
|
||||
},
|
||||
"getPageByUrl": function(url) {
|
||||
var addr = url.split("/");
|
||||
var page = this._root;
|
||||
for (var i = 0; i < addr.length; ++i) {
|
||||
if (addr[i] !== "") {
|
||||
page = page.getChildPage(addr[i]);
|
||||
if (page === undefined) {
|
||||
return this._specialPages.notFound;
|
||||
}
|
||||
}
|
||||
}
|
||||
return page;
|
||||
},
|
||||
"hasPage": function(name) {
|
||||
return this.getPageByUrl(name) !== this._specialPages.notFound
|
||||
},
|
||||
"_h_getPageAddress": function(ev) {
|
||||
var data = ev.getData();
|
||||
|
||||
var page = this.getPageByUrl(data.at("url").valueOf());
|
||||
|
||||
var vc = new Vocabulary();
|
||||
if (page) {
|
||||
vc.insert("address", page.getAddress());
|
||||
} else {
|
||||
vc.insert("address", this._specialPages.notFound.getAddress());
|
||||
}
|
||||
|
||||
this.response(vc, "pageAddress", ev);
|
||||
},
|
||||
"_h_getPageName": function(ev) {
|
||||
var data = ev.getData();
|
||||
var address = data.at("address");
|
||||
|
||||
var evp = new Event(address["+"](new Address(["ping"])));
|
||||
this._dp.pass(evp);
|
||||
evp.destructor();
|
||||
|
||||
var itr = this._rMap.find(address);
|
||||
var vc = new Vocabulary();
|
||||
if (itr["=="](this._rMap.end())) {
|
||||
vc.insert("name", new String("notFound"));
|
||||
} else {
|
||||
vc.insert("name", itr["*"]().second.clone());
|
||||
}
|
||||
this.response(vc, "pageName", ev);
|
||||
},
|
||||
"_initNotFoundPage": function() {
|
||||
var nf = new Page(this._address["+"](new Address(["special", "notFound"])), "Not found");
|
||||
this._specialPages["notFound"] = nf;
|
||||
this.addModel(nf);
|
||||
var msg = new ModelString(nf._address["+"](new Address(["errorMessage"])), "Error: page not found");
|
||||
nf.addItem(msg, 0, 0, 1, 1);
|
||||
},
|
||||
"_initRootPage": function() {
|
||||
this.addModel(this._root);
|
||||
|
||||
this._rMap.insert(this._root.getAddress(), new String("/"));
|
||||
this._root.on("newPage", this._onNewPage, this);
|
||||
this._root.on("removePage", this._onRemovePage, this);
|
||||
},
|
||||
"_onNewPage": function(page) {
|
||||
var addr = page.urlAddress.join("/").slice(this._root.name.length);
|
||||
this.trigger("serviceMessage", "Adding new page: " + addr);
|
||||
this.trigger("serviceMessage", "Page address: " + page.getAddress().toString());
|
||||
|
||||
if (this._urls[addr]) {
|
||||
throw new Error("An attempt to add page with an existing url");
|
||||
}
|
||||
this._urls[addr] = page;
|
||||
this._rMap.insert(page.getAddress(), new String(addr));
|
||||
page.setParentReporter(this._pr);
|
||||
},
|
||||
"_onRemovePage": function(page) {
|
||||
var addr = page.urlAddress.join("/").slice(this._root.name.length);
|
||||
this.trigger("serviceMessage", "Removing page: " + addr);
|
||||
this.trigger("serviceMessage", "Page address: " + page.getAddress().toString());
|
||||
|
||||
if (!this._urls[addr]) {
|
||||
throw new Error("An attempt to remove a non existing page");
|
||||
}
|
||||
delete this._urls[addr];
|
||||
var itr = this._rMap.find(page.getAddress());
|
||||
this._rMap.erase(itr);
|
||||
page.unsetParentReporter();
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = PageStorage;
|
21
libjs/wModel/panesList.js
Normal file
21
libjs/wModel/panesList.js
Normal file
|
@ -0,0 +1,21 @@
|
|||
"use strict";
|
||||
|
||||
var List = require("./list");
|
||||
var Vocabulary = require("../wType/vocabulary");
|
||||
|
||||
var PanesList = List.inherit({
|
||||
"className": "PanesList",
|
||||
"constructor": function(address) {
|
||||
List.fn.constructor.call(this, address);
|
||||
},
|
||||
"addItem": function(model) {
|
||||
List.fn.addModel.call(this, model);
|
||||
|
||||
var vc = new Vocabulary();
|
||||
vc.insert("address", model.getAddress());
|
||||
|
||||
this.push(vc);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = PanesList;
|
6
libjs/wModel/proxy/CMakeLists.txt
Normal file
6
libjs/wModel/proxy/CMakeLists.txt
Normal file
|
@ -0,0 +1,6 @@
|
|||
cmake_minimum_required(VERSION 2.8.12)
|
||||
|
||||
configure_file(proxy.js proxy.js)
|
||||
configure_file(list.js list.js)
|
||||
configure_file(vocabulary.js vocabulary.js)
|
||||
configure_file(catalogue.js catalogue.js)
|
54
libjs/wModel/proxy/catalogue.js
Normal file
54
libjs/wModel/proxy/catalogue.js
Normal file
|
@ -0,0 +1,54 @@
|
|||
"use strict";
|
||||
|
||||
var Proxy = require("./proxy");
|
||||
var Vocabulary = require("../../wType/vocabulary");
|
||||
var Vector = require("../../wType/vector");
|
||||
var Ctrl = require("../../wController/catalogue");
|
||||
|
||||
var Catalogue = Proxy.inherit({
|
||||
"className": "List", //no, it is not a typo, this is the way data structure here suppose to look like
|
||||
"constructor": function(address, ctrlAddr, ctrlOpts, socket) {
|
||||
var controller = new Ctrl(ctrlAddr, ctrlOpts);
|
||||
Proxy.fn.constructor.call(this, address, controller, socket);
|
||||
|
||||
this.controller.on("data", this._onRemoteData, this);
|
||||
this.controller.on("addElement", this._onRemoteAddElement, this);
|
||||
//this.controller.on("removeElement", this._onRemoteRemoveElement, this); //not supported yet
|
||||
},
|
||||
"_getAllData": function() {
|
||||
var vec = new Vector();
|
||||
|
||||
var itr = this.controller.data.begin();
|
||||
var end = this.controller.data.end();
|
||||
|
||||
for (; !itr["=="](end); itr["++"]()) {
|
||||
vec.push(itr["*"]().clone());
|
||||
}
|
||||
|
||||
return vec;
|
||||
},
|
||||
"_h_subscribe": function(ev) {
|
||||
Proxy.fn._h_subscribe.call(this, ev);
|
||||
|
||||
if (this.ready) {
|
||||
this._h_get(ev);
|
||||
}
|
||||
},
|
||||
"_onRemoteData": function() {
|
||||
this.setReady(true);
|
||||
|
||||
var vc = new Vocabulary();
|
||||
vc.insert("data", this._getAllData());
|
||||
this.broadcast(vc, "get")
|
||||
},
|
||||
"_onRemoteAddElement": function(obj, before) {
|
||||
if (this.ready) { //only end appends are supported now
|
||||
var vc = new Vocabulary();
|
||||
vc.insert("data", obj.clone());
|
||||
|
||||
this.broadcast(vc, "push");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Catalogue;
|
46
libjs/wModel/proxy/list.js
Normal file
46
libjs/wModel/proxy/list.js
Normal file
|
@ -0,0 +1,46 @@
|
|||
"use strict";
|
||||
|
||||
var Proxy = require("./proxy");
|
||||
var Vocabulary = require("../../wType/vocabulary");
|
||||
var Ctrl = require("../../wController/list");
|
||||
|
||||
var List = Proxy.inherit({
|
||||
"className": "List",
|
||||
"constructor": function(address, controllerAddress, socket) {
|
||||
var controller = new Ctrl(controllerAddress);
|
||||
Proxy.fn.constructor.call(this, address, controller, socket);
|
||||
|
||||
this.controller.on("data", this._onRemoteData, this);
|
||||
this.controller.on("clear", this._onRemoteClear, this);
|
||||
this.controller.on("newElement", this._onRemoteNewElement, this);
|
||||
},
|
||||
"_h_subscribe": function(ev) {
|
||||
Proxy.fn._h_subscribe.call(this, ev);
|
||||
|
||||
if (this.ready) {
|
||||
this._h_get(ev);
|
||||
}
|
||||
},
|
||||
"_onRemoteClear": function() {
|
||||
if (this.ready) {
|
||||
this.broadcast(new Vocabulary(), "clear");
|
||||
}
|
||||
},
|
||||
"_onRemoteData": function() {
|
||||
this.setReady(true);
|
||||
|
||||
var vc = new Vocabulary();
|
||||
vc.insert("data", this.controller.data.clone())
|
||||
this.broadcast(vc, "get")
|
||||
},
|
||||
"_onRemoteNewElement": function(obj) {
|
||||
if (this.ready) {
|
||||
var vc = new Vocabulary();
|
||||
vc.insert("data", obj.clone());
|
||||
|
||||
this.broadcast(vc, "push");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = List;
|
180
libjs/wModel/proxy/proxy.js
Normal file
180
libjs/wModel/proxy/proxy.js
Normal file
|
@ -0,0 +1,180 @@
|
|||
"use strict";
|
||||
|
||||
var Model = require("../model");
|
||||
var Handler = require("../../wDispatcher/handler");
|
||||
var Vocabulary = require("../../wType/vocabulary");
|
||||
var Address = require("../../wType/address");
|
||||
|
||||
var config = require("../../../config/config.json");
|
||||
|
||||
var Proxy = Model.inherit({
|
||||
"className": "Proxy",
|
||||
"constructor": function(address, controller, socket) { //les't pretend - this class is abstract
|
||||
Model.fn.constructor.call(this, address);
|
||||
|
||||
this._socket = socket;
|
||||
this.ready = false;
|
||||
this.controller = controller;
|
||||
this.childrenPossible = false;
|
||||
this._destroyOnLastUnsubscription = false;
|
||||
this._destructionTimeout = undefined;
|
||||
this._childClass = undefined;
|
||||
this._waitingEvents = [];
|
||||
|
||||
this.addHandler("get");
|
||||
this.reporterHandler = new Handler(this._address["+"](new Address(["subscribeMember"])), this, this._h_subscribeMember);
|
||||
|
||||
this._uncyclic.push(function() {
|
||||
controller.destructor();
|
||||
});
|
||||
},
|
||||
"destructor": function() {
|
||||
if (this._destructionTimeout) {
|
||||
clearTimeout(this._destructionTimeout);
|
||||
}
|
||||
for (var i = 0; i < this._waitingEvents.length; ++i) {
|
||||
this._waitingEvents[i].destructor();
|
||||
}
|
||||
this.reporterHandler.destructor();
|
||||
Model.fn.destructor.call(this);
|
||||
},
|
||||
"checkSubscribersAndDestroy": function() {
|
||||
if (this._subscribersCount === 0 && this._destructionTimeout === undefined) {
|
||||
this.trigger("serviceMessage", this._address.toString() + " has no more subscribers, destroying model");
|
||||
this._destructionTimeout = setTimeout(this.trigger.bind(this, "destroyMe"), config.modelDestructionTimeout);
|
||||
}
|
||||
},
|
||||
"dispatchWaitingEvents": function() {
|
||||
for (var i = 0; i < this._waitingEvents.length; ++i) {
|
||||
var ev = this._waitingEvents[i];
|
||||
var cmd = "_h_" + ev.getDestination().back().toString();
|
||||
this[cmd](ev);
|
||||
ev.destructor();
|
||||
}
|
||||
this._waitingEvents = [];
|
||||
},
|
||||
"_getAllData": function() {
|
||||
return this.controller.data.clone();
|
||||
},
|
||||
"_h_get": function(ev) {
|
||||
if (this.ready) {
|
||||
var vc = new Vocabulary();
|
||||
|
||||
vc.insert("data", this._getAllData());
|
||||
this.response(vc, "get", ev);
|
||||
} else {
|
||||
this._waitingEvents.push(ev.clone());
|
||||
}
|
||||
},
|
||||
"_h_subscribe": function(ev) {
|
||||
Model.fn._h_subscribe.call(this, ev);
|
||||
|
||||
if (this._destructionTimeout) {
|
||||
clearTimeout(this._destructionTimeout);
|
||||
this._destructionTimeout = undefined;
|
||||
}
|
||||
},
|
||||
"_h_unsubscribe": function(ev) {
|
||||
Model.fn._h_unsubscribe.call(this, ev);
|
||||
|
||||
if (this._destroyOnLastUnsubscription) {
|
||||
this.checkSubscribersAndDestroy();
|
||||
}
|
||||
},
|
||||
"_h_subscribeMember": function(ev) {
|
||||
if (!this.childrenPossible) {
|
||||
return;
|
||||
}
|
||||
var dest = ev.getDestination();
|
||||
var lastHops = dest["<<"](this._address.length());
|
||||
|
||||
if (lastHops.length() === 2) {
|
||||
var command = lastHops.back().toString();
|
||||
var id = lastHops[">>"](1);
|
||||
if (command === "subscribe" || command === "get") {
|
||||
var child = new this._childClass(this._address["+"](id), this.controller._pairAddress["+"](id), this._socket);
|
||||
this.addModel(child);
|
||||
child._destroyOnLastUnsubscription = true;
|
||||
child["_h_" + command](ev);
|
||||
if (command === "get") {
|
||||
child.on("ready", child.checkSubscribersAndDestroy, child);
|
||||
}
|
||||
child.subscribe();
|
||||
child.on("destroyMe", this.destroyChild.bind(this, child)); //to remove model if it has no subscribers
|
||||
} else {
|
||||
this.trigger("serviceMessage", "Proxy model got a strange event: " + ev.toString(), 1);
|
||||
}
|
||||
} else {
|
||||
this.trigger("serviceMessage", "Proxy model got a strange event: " + ev.toString(), 1);
|
||||
}
|
||||
},
|
||||
"_onSocketDisconnected": function(ev, socket) {
|
||||
Model.fn._onSocketDisconnected.call(this, ev, socket);
|
||||
|
||||
if (this._destroyOnLastUnsubscription) {
|
||||
this.checkSubscribersAndDestroy();
|
||||
}
|
||||
},
|
||||
"register": function(dp, server) {
|
||||
Model.fn.register.call(this, dp, server);
|
||||
|
||||
this.controller.register(dp, this._socket);
|
||||
},
|
||||
"unregister": function() {
|
||||
Model.fn.unregister.call(this);
|
||||
|
||||
if (this.controller._subscribed) {
|
||||
this.controller.unsubscribe();
|
||||
}
|
||||
this.controller.unregister();
|
||||
},
|
||||
"setChildrenClass": function(Class) {
|
||||
if (this.childrenPossible) {
|
||||
this.trigger("serviceMessage", "An attempt to set another class for children in Proxy", 1);
|
||||
}
|
||||
if (!Class instanceof Proxy) {
|
||||
this.trigger("serviceMessage", "An attempt to set not inherited chidren class from Proxy to a Proxy", 2);
|
||||
}
|
||||
this.childrenPossible = true;
|
||||
this._childClass = Class;
|
||||
},
|
||||
"setReady": function(bool) {
|
||||
bool = !!bool;
|
||||
if (bool !== this.ready) {
|
||||
this.ready = bool;
|
||||
if (bool) {
|
||||
this.dispatchWaitingEvents();
|
||||
this.trigger("ready");
|
||||
} else {
|
||||
//todo do I realy need to trigger smth here?
|
||||
}
|
||||
}
|
||||
},
|
||||
"subscribe": function() {
|
||||
this.controller.subscribe();
|
||||
},
|
||||
"destroyChild": function(child) {
|
||||
this.removeModel(child);
|
||||
child.destructor();
|
||||
},
|
||||
"unsetChildrenClass": function() {
|
||||
if (!this.childrenPossible) {
|
||||
this.trigger("serviceMessage", "An attempt to unset children class in Proxy, which don't have it", 1);
|
||||
} else {
|
||||
delete this._childClass;
|
||||
this.childrenPossible = false;
|
||||
}
|
||||
},
|
||||
"unsubscribe": function() {
|
||||
this.controller.unsubscribe();
|
||||
this.setReady(false);
|
||||
}
|
||||
});
|
||||
|
||||
Proxy.onChildReady = function(ev) {
|
||||
this._h_get(ev);
|
||||
this.checkSubscribersAndDestroy();
|
||||
}
|
||||
|
||||
module.exports = Proxy;
|
||||
|
43
libjs/wModel/proxy/vocabulary.js
Normal file
43
libjs/wModel/proxy/vocabulary.js
Normal file
|
@ -0,0 +1,43 @@
|
|||
"use strict";
|
||||
|
||||
var Proxy = require("./proxy");
|
||||
var Vocabulary = require("../../wType/vocabulary");
|
||||
var Ctrl = require("../../wController/vocabulary");
|
||||
|
||||
var MVocabulary = Proxy.inherit({
|
||||
"className": "Vocabulary",
|
||||
"constructor": function(address, controllerAddress, socket) {
|
||||
var controller = new Ctrl(controllerAddress);
|
||||
Proxy.fn.constructor.call(this, address, controller, socket);
|
||||
|
||||
this.controller.on("data", this._onRemoteData, this);
|
||||
this.controller.on("clear", this._onRemoteClear, this);
|
||||
this.controller.on("change", this._onRemoteChange, this);
|
||||
},
|
||||
"_h_subscribe": function(ev) {
|
||||
Proxy.fn._h_subscribe.call(this, ev);
|
||||
|
||||
if (this.ready) {
|
||||
this._h_get(ev);
|
||||
}
|
||||
},
|
||||
"_onRemoteClear": function() {
|
||||
if (this.ready) {
|
||||
this.broadcast(new Vocabulary(), "clear");
|
||||
}
|
||||
},
|
||||
"_onRemoteData": function() {
|
||||
this.setReady(true);
|
||||
|
||||
var vc = new Vocabulary();
|
||||
vc.insert("data", this._getAllData());
|
||||
this.broadcast(vc, "get")
|
||||
},
|
||||
"_onRemoteChange": function(data) {
|
||||
if (this.ready) {
|
||||
this.broadcast(data, "change");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = MVocabulary;
|
47
libjs/wModel/string.js
Normal file
47
libjs/wModel/string.js
Normal file
|
@ -0,0 +1,47 @@
|
|||
"use strict";
|
||||
|
||||
var Model = require("./model");
|
||||
var String = require("../wType/string");
|
||||
var Address = require("../wType/address");
|
||||
var Vocabulary = require("../wType/vocabulary");
|
||||
|
||||
var ModelString = Model.inherit({
|
||||
"className": "String",
|
||||
"constructor": function(address, string) {
|
||||
Model.fn.constructor.call(this, address);
|
||||
|
||||
this._data = new String(string);
|
||||
|
||||
this.addHandler("get");
|
||||
},
|
||||
"destructor": function() {
|
||||
this._data.destructor();
|
||||
|
||||
Model.fn.destructor.call(this);
|
||||
},
|
||||
"_h_subscribe": function(ev) {
|
||||
Model.fn._h_subscribe.call(this, ev);
|
||||
|
||||
this._h_get(ev);
|
||||
},
|
||||
"_h_get": function(ev) {
|
||||
var vc = new Vocabulary();
|
||||
|
||||
vc.insert("data", this._data.clone());
|
||||
this.response(vc, "get", ev);
|
||||
},
|
||||
"set": function(value) {
|
||||
this._data.destructor();
|
||||
|
||||
this._data = new String(value.toString());
|
||||
|
||||
if (this._registered) {
|
||||
var vc = new Vocabulary();
|
||||
|
||||
vc.insert("data", this._data.clone());
|
||||
this.broadcast(vc, "get");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = ModelString;
|
70
libjs/wModel/theme.js
Normal file
70
libjs/wModel/theme.js
Normal file
|
@ -0,0 +1,70 @@
|
|||
"use strict";
|
||||
|
||||
var Model = require("./model");
|
||||
var Vocabulary = require("../wType/vocabulary");
|
||||
var String = require("../wType/string");
|
||||
var Uint64 = require("../wType/uint64");
|
||||
|
||||
var Theme = Model.inherit({
|
||||
"className": "Theme",
|
||||
"constructor": function(address, name, theme) {
|
||||
Model.fn.constructor.call(this, address);
|
||||
|
||||
this._themeName = name;
|
||||
var result = {};
|
||||
W.extend(result, Theme.default, theme);
|
||||
|
||||
var data = new Vocabulary();
|
||||
|
||||
for (var key in result) {
|
||||
if (result.hasOwnProperty(key)) {
|
||||
var type = typeof result[key];
|
||||
switch (type) {
|
||||
case "number":
|
||||
data.insert(key, new Uint64(result[key]));
|
||||
break;
|
||||
default:
|
||||
data.insert(key, new String(result[key]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this._data = data;
|
||||
|
||||
this.addHandler("get");
|
||||
},
|
||||
"getName": function() {
|
||||
return this._themeName;
|
||||
},
|
||||
"_h_get": function(ev) {
|
||||
var vc = new Vocabulary();
|
||||
|
||||
vc.insert("data", this._data.clone());
|
||||
vc.insert("name", new String(this._themeName));
|
||||
this.response(vc, "get", ev);
|
||||
},
|
||||
"_h_subscribe": function(ev) {
|
||||
Model.fn._h_subscribe.call(this, ev);
|
||||
|
||||
this._h_get(ev);
|
||||
}
|
||||
});
|
||||
|
||||
Theme.default = {
|
||||
mainColor: "#ffffff",
|
||||
mainFontColor: "#222222",
|
||||
primaryColor: "#0000ff",
|
||||
primaryFontColor: "#ffffff",
|
||||
secondaryColor: "#dddddd",
|
||||
secondaryFontColor: "#222222",
|
||||
|
||||
smallFont: "Liberation",
|
||||
smallFontSize: "12px",
|
||||
casualFont: "Liberation",
|
||||
casualFontSize: "16px",
|
||||
largeFont: "Liberation",
|
||||
largeFontSize: "20px"
|
||||
}
|
||||
|
||||
module.exports = Theme;
|
54
libjs/wModel/themeStorage.js
Normal file
54
libjs/wModel/themeStorage.js
Normal file
|
@ -0,0 +1,54 @@
|
|||
"use strict"
|
||||
|
||||
var Model = require("./model");
|
||||
|
||||
var Vocabulary = require("../wType/vocabulary");
|
||||
var Address = require("../wType/address");
|
||||
var String = require("../wType/string");
|
||||
var Theme = require("./theme")
|
||||
|
||||
var ThemeStorage = Model.inherit({
|
||||
"className": "ThemeStorage",
|
||||
"constructor": function(address) {
|
||||
Model.fn.constructor.call(this, address);
|
||||
|
||||
this._dtn = "budgie";
|
||||
this._data = new Vocabulary();
|
||||
|
||||
this.addHandler("get");
|
||||
this._initThemes();
|
||||
},
|
||||
"destructor": function() {
|
||||
this._data.destructor();
|
||||
|
||||
Model.fn.destructor.call(this);
|
||||
},
|
||||
"_h_subscribe": function(ev) {
|
||||
Model.fn._h_subscribe.call(this, ev);
|
||||
|
||||
this._h_get(ev);
|
||||
},
|
||||
"_h_get": function(ev) {
|
||||
var vc = new Vocabulary();
|
||||
|
||||
vc.insert("data", this._data.clone());
|
||||
vc.insert("default", new String(this._dtn));
|
||||
this.response(vc, "get", ev);
|
||||
},
|
||||
"_initThemes": function() {
|
||||
var budgie = new Theme(this._address["+"](new Address(["budgie"])), "budgie");
|
||||
this.insert(budgie);
|
||||
},
|
||||
"insert": function(theme) {
|
||||
this.addModel(theme);
|
||||
this._data.insert(theme.getName(), theme.getAddress());
|
||||
|
||||
var vc = new Vocabulary();
|
||||
vc.insert("name", new String(theme.getName()));
|
||||
vc.insert("address", theme.getAddress());
|
||||
|
||||
this.broadcast(vc, "insertion");
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = ThemeStorage;
|
79
libjs/wModel/vocabulary.js
Normal file
79
libjs/wModel/vocabulary.js
Normal file
|
@ -0,0 +1,79 @@
|
|||
"use strict";
|
||||
|
||||
var Model = require("./model");
|
||||
var Vector = require("../wType/vector");
|
||||
var Vocabulary = require("../wType/vocabulary");
|
||||
var Object = require("../wType/object")
|
||||
var String = require("../wType/string");
|
||||
|
||||
var ModelVocabulary = Model.inherit({
|
||||
"className": "Vocabulary",
|
||||
"constructor": function(address) {
|
||||
Model.fn.constructor.call(this, address);
|
||||
|
||||
this._data = new Vocabulary();
|
||||
|
||||
this.addHandler("get");
|
||||
},
|
||||
"destructor": function() {
|
||||
this._data.destructor();
|
||||
|
||||
Model.fn.destructor.call(this);
|
||||
},
|
||||
"clear": function() {
|
||||
this._data.clear();
|
||||
|
||||
if (this._regestered) {
|
||||
this.broadcast(new Vocabulary(), "clear");
|
||||
}
|
||||
},
|
||||
"erase": function(key) {
|
||||
this._data.erase(key);
|
||||
|
||||
if (this._registered) {
|
||||
var vc = new Vocabulary();
|
||||
var insert = new Vocabulary();
|
||||
var erase = new Vector();
|
||||
|
||||
erase.push(new String(key));
|
||||
vc.insert("insert", insert);
|
||||
vc.insert("erase", erase);
|
||||
|
||||
this.broadcast(vc, "change");
|
||||
}
|
||||
},
|
||||
"_h_subscribe": function(ev) {
|
||||
Model.fn._h_subscribe.call(this, ev);
|
||||
|
||||
this._h_get(ev);
|
||||
},
|
||||
"_h_get": function(ev) {
|
||||
var vc = new Vocabulary();
|
||||
|
||||
vc.insert("data", this._data.clone());
|
||||
this.response(vc, "get", ev);
|
||||
},
|
||||
"insert": function(key, value) {
|
||||
if (this._registered) {
|
||||
var vc = new Vocabulary();
|
||||
var insert = new Vocabulary();
|
||||
var erase = new Vector();
|
||||
|
||||
if (this._data.has(key)) {
|
||||
erase.push(new String(key));
|
||||
}
|
||||
this._data.insert(key, value);
|
||||
insert.insert(key, value.clone());
|
||||
|
||||
vc.insert("insert", insert);
|
||||
vc.insert("erase", erase);
|
||||
|
||||
this.broadcast(vc, "change");
|
||||
|
||||
} else {
|
||||
this._data.insert(key, value);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = ModelVocabulary;
|
0
libjs/wTest/CMakeLists.txt
Normal file
0
libjs/wTest/CMakeLists.txt
Normal file
136
libjs/wTest/abstractlist.js
Normal file
136
libjs/wTest/abstractlist.js
Normal file
|
@ -0,0 +1,136 @@
|
|||
"use strict";
|
||||
var WTest = require("./test");
|
||||
var AbstractList = require("../wContainer/abstractlist");
|
||||
|
||||
var String = require("../wType/string");
|
||||
|
||||
var TAbsctractList = WTest.inherit({
|
||||
"className": "TAbsctractList",
|
||||
"constructor": function() {
|
||||
WTest.fn.constructor.call(this, "AbstractList");
|
||||
|
||||
var List = AbstractList.template(String);
|
||||
this._list = new List();
|
||||
|
||||
this._actions.push(this.testBeginEnd);
|
||||
this._actions.push(this.testSize);
|
||||
this._actions.push(this.testIterators);
|
||||
this._actions.push(this.testErasing);
|
||||
this._actions.push(this.testClear);
|
||||
this._actions.push(this.testInsertion);
|
||||
},
|
||||
"destructor": function() {
|
||||
this._list.destructor();
|
||||
|
||||
WTest.fn.destructor.call(this);
|
||||
},
|
||||
"testBeginEnd": function() {
|
||||
if (!this._list.begin()["=="](this._list.end())) {
|
||||
throw new Error("problem with empty list");
|
||||
}
|
||||
},
|
||||
"testSize": function() {
|
||||
this._list.push_back(new String("h"));
|
||||
|
||||
if (this._list.size() !== 1) {
|
||||
throw new Error("problem with size");
|
||||
}
|
||||
},
|
||||
"testInsertion": function() {
|
||||
var str1 = new String("one");
|
||||
this._list.insert(str1, this._list.end());
|
||||
|
||||
if (!this._list.begin()["*"]()["=="](str1)) {
|
||||
throw new Error("Problem with insertion to an empty list");
|
||||
}
|
||||
|
||||
var str2 = new String("two");
|
||||
this._list.insert(str2, this._list.begin());
|
||||
|
||||
if (!this._list.begin()["*"]()["=="](str2)) {
|
||||
throw new Error("Problem with insertion to the beginning of the list");
|
||||
}
|
||||
|
||||
var itr = this._list.begin();
|
||||
itr["++"]();
|
||||
var str3 = new String("oneAndAHalf");
|
||||
this._list.insert(str3, itr);
|
||||
|
||||
itr["--"]();
|
||||
if (!itr["*"]()["=="](str3)) {
|
||||
throw new Error("Problem with insertion to the middle of the list");
|
||||
}
|
||||
|
||||
var arr = [str2, str3, str1];
|
||||
var itr1 = this._list.begin();
|
||||
for (var i = 0; i < arr.length; ++i, itr1["++"]()) {
|
||||
if (!itr1["*"]()["=="](arr[i])) {
|
||||
throw new Error("Problem with the order of elements in list after insertion");
|
||||
}
|
||||
}
|
||||
},
|
||||
"testIterators": function() {
|
||||
var beg = this._list.begin();
|
||||
var end = this._list.end();
|
||||
|
||||
beg["++"]();
|
||||
end["--"]();
|
||||
|
||||
if (!beg["=="](this._list.end())) {
|
||||
throw new Error("problem with iterator incrementation");
|
||||
}
|
||||
if (!end["=="](this._list.begin())) {
|
||||
throw new Error("problem with iterator decrementation");
|
||||
}
|
||||
|
||||
this._list.pop_back();
|
||||
|
||||
if (!this._list.begin()["=="](this._list.end())) {
|
||||
throw new Error("problem with empty list");
|
||||
}
|
||||
},
|
||||
"testErasing": function() {
|
||||
this._list.push_back(new String("h"));
|
||||
this._list.push_back(new String("e"));
|
||||
this._list.push_back(new String("l"));
|
||||
this._list.push_back(new String("l"));
|
||||
this._list.push_back(new String("o"));
|
||||
this._list.push_back(new String(","));
|
||||
this._list.push_back(new String(" "));
|
||||
this._list.push_back(new String("w"));
|
||||
this._list.push_back(new String("w"));
|
||||
|
||||
var itr = this._list.end();
|
||||
itr["--"]();
|
||||
|
||||
this._list.push_back(new String("o"));
|
||||
this._list.push_back(new String("r"));
|
||||
this._list.push_back(new String("l"));
|
||||
this._list.push_back(new String("d"));
|
||||
this._list.push_back(new String("!"));
|
||||
|
||||
this._list.erase(itr);
|
||||
|
||||
var beg = this._list.begin();
|
||||
var end = this._list.end();
|
||||
|
||||
var str = new String();
|
||||
|
||||
for (; !beg["=="](end); beg["++"]()) {
|
||||
str["+="](beg["*"]());
|
||||
}
|
||||
|
||||
if (str.toString() !== "hello, world!") {
|
||||
throw new Error("Error push back and erasing");
|
||||
}
|
||||
},
|
||||
"testClear": function() {
|
||||
this._list.clear();
|
||||
|
||||
if (!this._list.begin()["=="](this._list.end())) {
|
||||
throw new Error("problem with empty list");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = TAbsctractList;
|
78
libjs/wTest/abstractmap.js
Normal file
78
libjs/wTest/abstractmap.js
Normal file
|
@ -0,0 +1,78 @@
|
|||
"use strict";
|
||||
var WTest = require("./test");
|
||||
var AbstractMap = require("../wContainer/abstractmap");
|
||||
|
||||
var String = require("../wType/string");
|
||||
var Address = require("../wType/address");
|
||||
|
||||
var TAbsctractMap = WTest.inherit({
|
||||
"className": "TAbsctractMap",
|
||||
"constructor": function() {
|
||||
WTest.fn.constructor.call(this, "AbstractMap");
|
||||
|
||||
var Map = AbstractMap.template(Address, String);
|
||||
this._map = new Map();
|
||||
|
||||
this._actions.push(this.testEnd);
|
||||
this._actions.push(this.testSize);
|
||||
this._actions.push(this.testIterators);
|
||||
this._actions.push(this.testClear);
|
||||
},
|
||||
"destructor": function() {
|
||||
this._map.destructor();
|
||||
|
||||
WTest.fn.destructor.call(this);
|
||||
},
|
||||
"testEnd": function() {
|
||||
var noEl = this._map.find(new Address(["addr1", "hop1"]));
|
||||
if (!noEl["=="](this._map.end())) {
|
||||
throw new Error("problem with end!");
|
||||
}
|
||||
},
|
||||
"testSize": function() {
|
||||
this._map.insert(new Address(["addr1", "hop1"]), new String("hello"));
|
||||
this._map.insert(new Address(["addr2", "hop2"]), new String("world"));
|
||||
this._map.insert(new Address(["addr2", "/hop2"]), new String("world2"));
|
||||
this._map.insert(new Address(["addr2", "/hop2", "hop4"]), new String("world3"));
|
||||
|
||||
if (this._map.size() !== 4) {
|
||||
throw new Error("problem with insertion!");
|
||||
}
|
||||
},
|
||||
"testIterators": function() {
|
||||
var itr = this._map.find(new Address(["addr1", "hop1"]));
|
||||
|
||||
if (itr["=="](this._map.end())) {
|
||||
throw new Error("problem with finding!");
|
||||
}
|
||||
|
||||
if (itr["*"]().second.toString() !== "hello") {
|
||||
throw new Error("wrong element found");
|
||||
}
|
||||
itr["++"]();
|
||||
if (itr["*"]().second.toString() !== "world2") {
|
||||
throw new Error("iterator dereferenced into wrong element after incrementetion");
|
||||
}
|
||||
|
||||
this._map.erase(itr);
|
||||
itr = this._map.find(new Address(["addr2", "/hop2"]));
|
||||
|
||||
if (!itr["=="](this._map.end())) {
|
||||
throw new Error("problem with erasing!");
|
||||
}
|
||||
|
||||
itr = this._map.find(new Address(["addr2", "/hop2", "hop4"]));
|
||||
if (itr["=="](this._map.end()) || itr["*"]().second.toString() !== "world3") {
|
||||
throw new Error("Something is wrong with finding");
|
||||
}
|
||||
},
|
||||
"testClear": function() {
|
||||
this._map.clear();
|
||||
|
||||
if (this._map.size() > 0) {
|
||||
throw new Error("problem with clearing!");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = TAbsctractMap;
|
93
libjs/wTest/abstractorder.js
Normal file
93
libjs/wTest/abstractorder.js
Normal file
|
@ -0,0 +1,93 @@
|
|||
"use strict";
|
||||
var WTest = require("./test");
|
||||
var AbstractOrder = require("../wContainer/abstractorder");
|
||||
var Address = require("../wType/address");
|
||||
|
||||
var TAbstractOrder = WTest.inherit({
|
||||
"className": "TAbstractOrder",
|
||||
"constructor": function() {
|
||||
WTest.fn.constructor.call(this, "AbstractOrder");
|
||||
|
||||
var Order = AbstractOrder.template(Address);
|
||||
this._order = new Order();
|
||||
|
||||
this._actions.push(this.testSize);
|
||||
this._actions.push(this.testIterators);
|
||||
this._actions.push(this.testEmpty);
|
||||
this._actions.push(this.testPushBackFind);
|
||||
},
|
||||
"destructor": function() {
|
||||
this._order.destructor();
|
||||
|
||||
WTest.fn.destructor.call(this);
|
||||
},
|
||||
"testSize": function() {
|
||||
var addr1 = new Address(["hop1", "hop2"]);
|
||||
this._order.push_back(addr1);
|
||||
|
||||
if (this._order.size() !== 1) {
|
||||
throw new Error("problem with size");
|
||||
}
|
||||
},
|
||||
"testIterators": function() {
|
||||
var addr1 = new Address(["hop1", "hop2"]);
|
||||
|
||||
var begin = this._order.begin();
|
||||
var itr = begin.clone();
|
||||
|
||||
if (!begin["*"]()["=="](addr1)) {
|
||||
throw new Error("problem with iterator");
|
||||
}
|
||||
|
||||
itr["++"]();
|
||||
if (!itr["=="](this._order.end())) {
|
||||
throw new Error("problem with iterator, end");
|
||||
}
|
||||
|
||||
if (!this._order.find(addr1)["=="](begin)) {
|
||||
throw new Error("problem with finding");
|
||||
}
|
||||
|
||||
this._order.erase(addr1);
|
||||
|
||||
if (addr1.toString() !== new Address(["hop1", "hop2"]).toString()) {
|
||||
throw new Error("key have been destroyed afrer eresing element");
|
||||
}
|
||||
},
|
||||
"testEmpty": function() {
|
||||
if (!this._order.begin()["=="](this._order.end())) {
|
||||
throw new Error("error: problem with empty order");
|
||||
}
|
||||
},
|
||||
"testPushBackFind": function() {
|
||||
this._order.push_back(new Address(["hop1", "hop2"]))
|
||||
this._order.push_back(new Address(["hop1", "hop3"]))
|
||||
this._order.push_back(new Address(["hop1", "hop4"]))
|
||||
this._order.push_back(new Address(["hop1", "hop5"]))
|
||||
this._order.push_back(new Address(["hop1", "hop6"]))
|
||||
this._order.push_back(new Address(["hop1", "hop7"]))
|
||||
|
||||
if (this._order.size() !== 6) {
|
||||
throw new Error("problem with size");
|
||||
}
|
||||
|
||||
var itr = this._order.find(new Address(["hop1", "hop4"]));
|
||||
var end = this._order.end();
|
||||
var arr = [
|
||||
new Address(["hop1", "hop4"]),
|
||||
new Address(["hop1", "hop5"]),
|
||||
new Address(["hop1", "hop6"]),
|
||||
new Address(["hop1", "hop7"])
|
||||
]
|
||||
var i = 0;
|
||||
|
||||
for (; !itr["=="](end); itr["++"]()) {
|
||||
if (!itr["*"]()["=="](arr[i])) {
|
||||
throw new Error("problem with finding element in the middle and iteration to the end");
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = TAbstractOrder;
|
29
libjs/wTest/test.js
Normal file
29
libjs/wTest/test.js
Normal file
|
@ -0,0 +1,29 @@
|
|||
"use strict";
|
||||
|
||||
var Class = require("../utils/subscribable");
|
||||
|
||||
var Test = Class.inherit({
|
||||
"className": "Test",
|
||||
"constructor": function(name) {
|
||||
Class.fn.constructor.call(this);
|
||||
|
||||
this._name = name;
|
||||
this._actions = [];
|
||||
},
|
||||
"run": function() {
|
||||
this.trigger("start", this._name);
|
||||
var succsess = this._actions.length;
|
||||
for (var i = 0; i < this._actions.length; ++i) {
|
||||
this.trigger("progress", this._name, i + 1, this._actions.length);
|
||||
try {
|
||||
this._actions[i].call(this);
|
||||
} catch (e) {
|
||||
this.trigger("fail", this._name, i + 1, e);
|
||||
--succsess;
|
||||
}
|
||||
}
|
||||
this.trigger("end", this._name, succsess, this._actions.length);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Test;
|
40
libjs/wTest/uint64.js
Normal file
40
libjs/wTest/uint64.js
Normal file
|
@ -0,0 +1,40 @@
|
|||
"use strict";
|
||||
var WTest = require("./test");
|
||||
var Uint64 = require("../wType/uint64");
|
||||
|
||||
var TUint64 = WTest.inherit({
|
||||
"className": "TUint64",
|
||||
"constructor": function() {
|
||||
WTest.fn.constructor.call(this, "Uint64");
|
||||
|
||||
this._actions.push(this.testEq);
|
||||
this._actions.push(this.testGt);
|
||||
this._actions.push(this.testLt);
|
||||
},
|
||||
"testEq": function() {
|
||||
var first = new Uint64(5);
|
||||
var second = new Uint64(5);
|
||||
|
||||
if (!first["=="](second)) {
|
||||
throw new Error("problem with equals low");
|
||||
}
|
||||
},
|
||||
"testGt": function() {
|
||||
var first = new Uint64(5);
|
||||
var second = new Uint64(4);
|
||||
|
||||
if (!first[">"](second)) {
|
||||
throw new Error("problem with greater low");
|
||||
}
|
||||
},
|
||||
"testLt": function() {
|
||||
var first = new Uint64(4);
|
||||
var second = new Uint64(5);
|
||||
|
||||
if (!first["<"](second)) {
|
||||
throw new Error("problem with lower low");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = TUint64;
|
12
libjs/wType/CMakeLists.txt
Normal file
12
libjs/wType/CMakeLists.txt
Normal file
|
@ -0,0 +1,12 @@
|
|||
cmake_minimum_required(VERSION 2.8.12)
|
||||
|
||||
configure_file(string.js string.js)
|
||||
configure_file(bytearray.js bytearray.js)
|
||||
configure_file(object.js object.js)
|
||||
configure_file(uint64.js uint64.js)
|
||||
configure_file(vocabulary.js vocabulary.js)
|
||||
configure_file(vector.js vector.js)
|
||||
configure_file(address.js address.js)
|
||||
configure_file(event.js event.js)
|
||||
configure_file(boolean.js boolean.js)
|
||||
configure_file(blob.js blob.js)
|
228
libjs/wType/address.js
Normal file
228
libjs/wType/address.js
Normal file
|
@ -0,0 +1,228 @@
|
|||
"use strict";
|
||||
var Object = require("./object");
|
||||
var String = require("./string");
|
||||
|
||||
var Address = Object.inherit({
|
||||
"className": "Address",
|
||||
"constructor": function(data) {
|
||||
Object.fn.constructor.call(this);
|
||||
|
||||
this._data = [];
|
||||
this._parseSource(data || []);
|
||||
},
|
||||
"destructor": function() {
|
||||
this.clear();
|
||||
|
||||
Object.fn.destructor.call(this);
|
||||
},
|
||||
"<": function(other) {
|
||||
if (!(other instanceof Address)) {
|
||||
throw new Error("Can compare Address only with Address");
|
||||
}
|
||||
var hopMe;
|
||||
var hopOt;
|
||||
|
||||
for (var i = 0; i < this._data.length; ++i) {
|
||||
hopMe = this._data[i];
|
||||
hopOt = other._data[i];
|
||||
|
||||
if (hopOt === undefined) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (hopMe["<"](hopOt)) {
|
||||
return true;
|
||||
}
|
||||
if (hopMe[">"](hopOt)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return this._data.length < other._data.length;
|
||||
},
|
||||
">": function(other) {
|
||||
if (!(other instanceof Address)) {
|
||||
throw new Error("Can compare Address only with Address");
|
||||
}
|
||||
var hopMe;
|
||||
var hopOt;
|
||||
|
||||
for (var i = 0; i < this._data.length; ++i) {
|
||||
hopMe = this._data[i];
|
||||
hopOt = other._data[i];
|
||||
|
||||
if (hopOt === undefined) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (hopMe[">"](hopOt)) {
|
||||
return true;
|
||||
}
|
||||
if (hopMe["<"](hopOt)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return this._data.length > other._data.length;
|
||||
},
|
||||
"==": function(other) {
|
||||
if (this.getType() !== other.getType()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this._data.length !== other._data.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var hopMe;
|
||||
var hopOt;
|
||||
|
||||
for (var i = 0; i < this._data.length; ++i) {
|
||||
hopMe = this._data[i];
|
||||
hopOt = other._data[i];
|
||||
if ( !(hopMe["=="](hopOt)) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
"+": function(other) {
|
||||
var res = this.clone();
|
||||
res["+="](other);
|
||||
return res;
|
||||
},
|
||||
"+=": function(other) {
|
||||
if (other instanceof Address) {
|
||||
for (var i = 0; i < other._data.length; ++i) {
|
||||
this._data.push(other._data[i].clone());
|
||||
}
|
||||
} else {
|
||||
throw new Error("Can add to Address only Address");
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
"<<": function(n) {
|
||||
var res = new Address();
|
||||
for (var i = n; i < this._data.length; ++i) {
|
||||
res._data.push(this._data[i].clone());
|
||||
}
|
||||
return res;
|
||||
},
|
||||
">>": function(n) {
|
||||
var res = new Address();
|
||||
for (var i = 0; i < this._data.length - n; ++i) {
|
||||
res._data.push(this._data[i].clone());
|
||||
}
|
||||
return res;
|
||||
},
|
||||
"clear": function() {
|
||||
for (var i = 0; i < this._data.length; ++i) {
|
||||
this._data[i].destructor();
|
||||
}
|
||||
this._data = [];
|
||||
},
|
||||
"clone": function() {
|
||||
var clone = new Address();
|
||||
|
||||
for (var i = 0; i < this._data.length; ++i) {
|
||||
clone._data.push(this._data[i].clone());
|
||||
}
|
||||
|
||||
return clone;
|
||||
},
|
||||
"deserialize": function(ba) {
|
||||
this.clear()
|
||||
var length = ba.pop32();
|
||||
|
||||
for (var i = 0; i < length; ++i) {
|
||||
var hop = new String();
|
||||
hop.deserialize(ba);
|
||||
this._data.push(hop);
|
||||
}
|
||||
},
|
||||
"serialize": function(ba) {
|
||||
ba.push32(this._data.length)
|
||||
|
||||
for (var i = 0; i < this._data.length; ++i) {
|
||||
this._data[i].serialize(ba);
|
||||
}
|
||||
},
|
||||
"length": function() {
|
||||
return this._data.length;
|
||||
},
|
||||
"size": function() {
|
||||
var size = 4;
|
||||
for (var i = 0; i < this._data.length; ++i) {
|
||||
size += this._data[i].size();
|
||||
}
|
||||
|
||||
return size;
|
||||
},
|
||||
"toString": function() {
|
||||
var str = "";
|
||||
str += "["
|
||||
|
||||
for (var i = 0; i < this._data.length; ++i) {
|
||||
if (i !== 0) {
|
||||
str +=", ";
|
||||
}
|
||||
str += this._data[i].toString();
|
||||
}
|
||||
|
||||
str += "]";
|
||||
return str;
|
||||
},
|
||||
"begins": function(other) {
|
||||
var size = other._data.length;
|
||||
if (size > this._data.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (var i = 0; i < size; ++i) {
|
||||
var myHop = this._data[i];
|
||||
var othHop = other._data[i];
|
||||
|
||||
if (!myHop["=="](othHop)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
"ends": function(other) {
|
||||
var size = other._data.length;
|
||||
if (size > this._data.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (var i = 1; i <= size; ++i) {
|
||||
var myHop = this._data[this._data.length - i];
|
||||
var othHop = other._data[other._data.length - i];
|
||||
|
||||
if (!myHop["=="](othHop)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
"back": function() {
|
||||
return this._data[this._data.length - 1].clone();
|
||||
},
|
||||
"front": function() {
|
||||
return this._data[0].clone();
|
||||
},
|
||||
"toArray": function() {
|
||||
var arr = [];
|
||||
for (var i = 0; i < this._data.length; ++i) {
|
||||
arr.push(this._data[i].toString());
|
||||
}
|
||||
return arr;
|
||||
},
|
||||
"_parseSource": function(data) {
|
||||
for (var i = 0; i < data.length; ++i) {
|
||||
this._data.push(new String(data[i]));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Address;
|
65
libjs/wType/blob.js
Normal file
65
libjs/wType/blob.js
Normal file
|
@ -0,0 +1,65 @@
|
|||
"use strict";
|
||||
|
||||
var Object = require("./object");
|
||||
|
||||
var Blob = Object.inherit({
|
||||
"className": "Blob",
|
||||
"constructor": function(/*ArrayBuffer*/data) {
|
||||
Object.fn.constructor.call(this);
|
||||
|
||||
data = data || new ArrayBuffer(0);
|
||||
this._data = data;
|
||||
},
|
||||
"==": function(other) {
|
||||
if (this.getType() !== other.getType()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.size() == other.size(); //TODO let's pretend one shall never wish to compare blobs)
|
||||
},
|
||||
"base64": function() {
|
||||
var arr = new Uint8Array(this._data);
|
||||
var bin = "";
|
||||
for (var i = 0; i < arr.length; ++i) {
|
||||
bin += String.fromCharCode(arr[i]);
|
||||
}
|
||||
|
||||
return btoa(bin);
|
||||
},
|
||||
"clone": function() {
|
||||
var clone = new Blob(this._data.slice(0));
|
||||
|
||||
return clone;
|
||||
},
|
||||
"deserialize": function(ba) {
|
||||
var length = ba.pop32();
|
||||
this._data = new ArrayBuffer(length);
|
||||
var view = new Uint8Array(this._data);
|
||||
|
||||
for (var i = 0; i < length; ++i) {
|
||||
view[i] = ba.pop8();
|
||||
}
|
||||
},
|
||||
"length": function() {
|
||||
return this._data.byteLength;
|
||||
},
|
||||
"serialize": function(ba) {
|
||||
ba.push32(this._data.byteLength);
|
||||
var view = new Uint8Array(this._data);
|
||||
|
||||
for (var i = 0; i < view.length; ++i) {
|
||||
ba.push8(view[i]);
|
||||
}
|
||||
},
|
||||
"size": function() {
|
||||
return this._data.byteLength + 4;
|
||||
},
|
||||
"toString": function() {
|
||||
return "File <" + this._data.byteLength + ">";
|
||||
},
|
||||
"valueOf": function() {
|
||||
return this._data;
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Blob;
|
62
libjs/wType/boolean.js
Normal file
62
libjs/wType/boolean.js
Normal file
|
@ -0,0 +1,62 @@
|
|||
"use strict";
|
||||
var Object = require("./object");
|
||||
|
||||
var Boolean = Object.inherit({
|
||||
"className": "Boolean",
|
||||
"constructor": function(bool) {
|
||||
Object.fn.constructor.call(this);
|
||||
|
||||
this._data = bool === true;
|
||||
},
|
||||
"<": function(other) {
|
||||
if (!(other instanceof Boolean)) {
|
||||
throw new Error("Can compare Boolean only with Boolean");
|
||||
}
|
||||
return this._data < other._data;
|
||||
},
|
||||
">": function(other) {
|
||||
if (!(other instanceof Boolean)) {
|
||||
throw new Error("Can compare Boolean only with Boolean");
|
||||
}
|
||||
return this._data > other._data;
|
||||
},
|
||||
"==": function(other) {
|
||||
if (this.getType() !== other.getType()) {
|
||||
return false;
|
||||
}
|
||||
return this._data === other._data;
|
||||
},
|
||||
"clone": function() {
|
||||
return new Boolean(this._data);
|
||||
},
|
||||
"deserialize": function(ba) {
|
||||
var int = ba.pop8();
|
||||
|
||||
if (int === 253) {
|
||||
this._data = true;
|
||||
} else {
|
||||
this._data = false;
|
||||
}
|
||||
},
|
||||
"length": function() {
|
||||
return 1;
|
||||
},
|
||||
"size": function() {
|
||||
return 1;
|
||||
},
|
||||
"serialize": function(ba) {
|
||||
if (this._data) {
|
||||
ba.push8(253);
|
||||
} else {
|
||||
ba.push8(0);
|
||||
}
|
||||
},
|
||||
"toString": function() {
|
||||
return this._data.toString();
|
||||
},
|
||||
"valueOf": function() {
|
||||
return this._data;
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Boolean;
|
106
libjs/wType/bytearray.js
Normal file
106
libjs/wType/bytearray.js
Normal file
|
@ -0,0 +1,106 @@
|
|||
"use strict";
|
||||
var Class = require("../utils/class");
|
||||
|
||||
var ByteArray = Class.inherit({
|
||||
"className": "ByteArray",
|
||||
"constructor": function(size) {
|
||||
Class.fn.constructor.call(this);
|
||||
|
||||
this._referenceMode = false;
|
||||
this._data = new Uint8Array(size);
|
||||
this._shiftBegin = 0;
|
||||
this._shiftEnd = 0;
|
||||
},
|
||||
"_checkReference": function() {
|
||||
if (this._referenceMode) {
|
||||
var buffer = new ArrayBuffer(this._data.length - this._shiftBegin);
|
||||
var newData = new Uint8Array(buffer);
|
||||
newData.set(this._data, this._shiftBegin);
|
||||
this._data = newData;
|
||||
this._shiftBegin = 0;
|
||||
this._referenceMode = false;
|
||||
}
|
||||
},
|
||||
"fill": function(/*Uint8Array*/arr, /*Number*/size, /*[Number]*/shift) {
|
||||
this._checkReference();
|
||||
shift = shift || 0;
|
||||
|
||||
if (this._shiftEnd === 0 && (this._data.length <= size - shift)) {
|
||||
this._referenceMode = true;
|
||||
this._data = arr.subarray(shift, this._data.length + shift);
|
||||
this._shiftEnd = this._data.length;
|
||||
shift += this._shiftEnd;
|
||||
} else {
|
||||
while (!this.filled() && shift < size) {
|
||||
this._data[this._shiftEnd] = arr[shift];
|
||||
++shift;
|
||||
++this._shiftEnd;
|
||||
}
|
||||
}
|
||||
|
||||
return shift;
|
||||
},
|
||||
"filled": function() {
|
||||
return this._data.length === this._shiftEnd;
|
||||
},
|
||||
"size": function() {
|
||||
return this._shiftEnd - this._shiftBegin;
|
||||
},
|
||||
"maxSize": function() {
|
||||
return this._data.length;
|
||||
},
|
||||
"push8": function(int) {
|
||||
this._checkReference();
|
||||
|
||||
this._data[this._shiftEnd] = int;
|
||||
++this._shiftEnd;
|
||||
},
|
||||
"push16": function(int) {
|
||||
var h = (int >> 8) & 0xff;
|
||||
var l = int & 0xff;
|
||||
|
||||
this.push8(h);
|
||||
this.push8(l);
|
||||
},
|
||||
"push32": function(int) {
|
||||
var hh = (int >> 24) & 0xff;
|
||||
var hl = (int >> 16) & 0xff;
|
||||
var lh = (int >> 8) & 0xff;
|
||||
var ll = int & 0xff;
|
||||
|
||||
this.push8(hh);
|
||||
this.push8(hl);
|
||||
this.push8(lh);
|
||||
this.push8(ll);
|
||||
},
|
||||
"push64": function(int) {
|
||||
|
||||
},
|
||||
"pop8": function(int) {
|
||||
var ret = this._data[this._shiftBegin];
|
||||
++this._shiftBegin;
|
||||
return ret;
|
||||
},
|
||||
"pop16": function(int) {
|
||||
var ret = (this.pop8() << 8);
|
||||
ret = ret | this.pop8();
|
||||
|
||||
return ret;
|
||||
},
|
||||
"pop32": function(int) {
|
||||
var ret = this.pop8() << 24;
|
||||
ret = ret | (this.pop8() << 16);
|
||||
ret = ret | (this.pop8() << 8);
|
||||
ret = ret | this.pop8();
|
||||
|
||||
return ret;
|
||||
},
|
||||
"pop64": function(int) {
|
||||
|
||||
},
|
||||
"data": function() {
|
||||
return this._data.subarray(this._shiftBegin, this._shiftEnd);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = ByteArray;
|
121
libjs/wType/event.js
Normal file
121
libjs/wType/event.js
Normal file
|
@ -0,0 +1,121 @@
|
|||
"use strict";
|
||||
var Object = require("./object");
|
||||
var Uint64 = require("./uint64");
|
||||
var Address = require("./address");
|
||||
var Boolean = require("./boolean");
|
||||
|
||||
var Event = Object.inherit({
|
||||
"className": "Event",
|
||||
"constructor": function(addr, object, isSystem) {
|
||||
Object.fn.constructor.call(this);
|
||||
|
||||
if (!(object instanceof Object) && object !== undefined) {
|
||||
throw new Error("Wrong arguments to construct Event");
|
||||
}
|
||||
if (!(addr instanceof Address) && addr !== undefined) {
|
||||
throw new Error("Wrong arguments to construct Event");
|
||||
}
|
||||
|
||||
this._destination = addr !== undefined ? addr : new Address();
|
||||
this._data = object !== undefined ? object : new Object();
|
||||
this._senderId = new Uint64();
|
||||
this._system = new Boolean(isSystem);
|
||||
},
|
||||
"destructor": function() {
|
||||
this.clear();
|
||||
|
||||
Object.fn.destructor.call(this);
|
||||
},
|
||||
"==": function(other) {
|
||||
if (this.getType() !== other.getType()) {
|
||||
return false;
|
||||
}
|
||||
return this._destination["=="](other._destination) &&
|
||||
this._system["=="](other._system) &&
|
||||
this._senderId["=="](other._senderId) &&
|
||||
this._data["=="](other._data)
|
||||
},
|
||||
"clear": function() {
|
||||
this._system.destructor();
|
||||
this._destination.destructor();
|
||||
this._senderId.destructor();
|
||||
this._data.destructor();
|
||||
},
|
||||
"clone": function() {
|
||||
var clone = new Event();
|
||||
|
||||
clone._destination = this._destination.clone();
|
||||
clone._data = this._data.clone();
|
||||
clone._senderId = this._senderId.clone();
|
||||
clone._system = this._system.clone();
|
||||
|
||||
return clone;
|
||||
},
|
||||
"deserialize": function(ba) {
|
||||
this._system = new Boolean();
|
||||
this._system.deserialize(ba);
|
||||
|
||||
if (!this.isSystem()) {
|
||||
this._destination = new Address();
|
||||
this._destination.deserialize(ba);
|
||||
|
||||
this._senderId = new Uint64();
|
||||
this._senderId.deserialize(ba);
|
||||
}
|
||||
|
||||
this._data = Object.fromByteArray(ba);
|
||||
},
|
||||
"getData": function() {
|
||||
return this._data;
|
||||
},
|
||||
"getDestination": function() {
|
||||
return this._destination;
|
||||
},
|
||||
"getSenderId": function() {
|
||||
return this._senderId;
|
||||
},
|
||||
"isSystem": function() {
|
||||
return this._system.valueOf();
|
||||
},
|
||||
"length": function() {
|
||||
return 2 + this._destination.length() + this._data.length();
|
||||
},
|
||||
"serialize": function(ba) {
|
||||
this._system.serialize(ba);
|
||||
|
||||
if (!this.isSystem()) {
|
||||
this._destination.serialize(ba);
|
||||
this._senderId.serialize(ba);
|
||||
}
|
||||
|
||||
ba.push8(this._data.getType());
|
||||
this._data.serialize(ba);
|
||||
},
|
||||
"setSenderId": function(id) {
|
||||
if (!(id instanceof Uint64)) {
|
||||
throw new Error("Can't set id, which is not Uint64");
|
||||
}
|
||||
this._senderId = id;
|
||||
},
|
||||
"size": function() {
|
||||
var size = this._system.size() + this._data.size() + 1
|
||||
if (!this.isSystem()) {
|
||||
size += this._senderId.size() + this._destination.size();
|
||||
}
|
||||
return size;
|
||||
},
|
||||
"toString": function() {
|
||||
var str = "{";
|
||||
|
||||
str += "system: " + this._system.toString();
|
||||
str += " destination: " + this._destination.toString();
|
||||
str += " sender: " + this._senderId.toString();
|
||||
str += " data: " + this._data.toString();
|
||||
|
||||
str += "}";
|
||||
|
||||
return str;
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Event;
|
42
libjs/wType/factory.js
Normal file
42
libjs/wType/factory.js
Normal file
|
@ -0,0 +1,42 @@
|
|||
"use strict";
|
||||
|
||||
var Object = require("./object");
|
||||
var types = {
|
||||
"String" : require("./string"),
|
||||
"Vocabulary": require("./vocabulary"),
|
||||
"Uint64" : require("./uint64"),
|
||||
"Address" : require("./address"),
|
||||
"Boolean" : require("./boolean"),
|
||||
"Event" : require("./event"),
|
||||
"Vector" : require("./vector"),
|
||||
"Blob" : require("./blob")
|
||||
}
|
||||
|
||||
var storage = global.Object.create(null);
|
||||
|
||||
for (var name in types) {
|
||||
if (types.hasOwnProperty(name)) {
|
||||
var typeId = Object.objectType[name];
|
||||
if (typeId === undefined) {
|
||||
throw new Error("wType initialization error - can't find type id for type " + name);
|
||||
}
|
||||
storage[typeId] = types[name];
|
||||
}
|
||||
}
|
||||
|
||||
function create(/*ByteArray*/ba) {
|
||||
var type = ba.pop8();
|
||||
var Type = storage[type];
|
||||
|
||||
if (Type === undefined) {
|
||||
throw new Error("Unsupported data type found during deserialization: " + type);
|
||||
}
|
||||
|
||||
var obj = new Type();
|
||||
obj.deserialize(ba);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
Object.fromByteArray = create;
|
||||
module.exports = create;
|
70
libjs/wType/object.js
Normal file
70
libjs/wType/object.js
Normal file
|
@ -0,0 +1,70 @@
|
|||
"use strict";
|
||||
var Class = require("../utils/class");
|
||||
|
||||
var Object = Class.inherit({
|
||||
"className": "Object",
|
||||
"constructor": function() {
|
||||
Class.fn.constructor.call(this);
|
||||
},
|
||||
"<": function(other) {
|
||||
throw new Error(this.className + " has no reimplemented method \"<\"");
|
||||
},
|
||||
">": function(other) {
|
||||
throw new Error(this.className + " has no reimplemented method \">\"");
|
||||
},
|
||||
"==": function(other) {
|
||||
throw new Error(this.className + " has no reimplemented method \"==\"");
|
||||
},
|
||||
"clone": function() {
|
||||
throw new Error(this.className + " has no reimplemented method \"clone\"");
|
||||
},
|
||||
"getType": function() {
|
||||
var type = Object.objectType[this.className];
|
||||
|
||||
if (type === undefined) {
|
||||
throw new Error("Undefined type of " + this.className);
|
||||
}
|
||||
|
||||
return type;
|
||||
},
|
||||
"length": function() {
|
||||
throw new Error(this.className + " has no reimplemented method \"length\"");
|
||||
},
|
||||
"size": function() {
|
||||
throw new Error(this.className + " has no reimplemented method \"size\"");
|
||||
},
|
||||
"toString": function() {
|
||||
throw new Error(this.className + " has no reimplemented method \"toString\"");
|
||||
},
|
||||
"valueOf": function() {
|
||||
throw new Error(this.className + " has no reimplemented method \"valueOf\"");
|
||||
}
|
||||
});
|
||||
|
||||
Object.objectType = {
|
||||
"String" : 0,
|
||||
"Vocabulary": 1,
|
||||
"Uint64" : 2,
|
||||
"Address" : 3,
|
||||
"Boolean" : 4,
|
||||
"Event" : 5,
|
||||
"Vector" : 6,
|
||||
"Blob" : 7
|
||||
};
|
||||
|
||||
Object.reverseObjectType = {
|
||||
0 : "String",
|
||||
1 : "Vocabulary",
|
||||
2 : "Uint64",
|
||||
3 : "Address",
|
||||
4 : "Boolean",
|
||||
5 : "Event",
|
||||
6 : "Vector",
|
||||
7 : "Blob"
|
||||
}
|
||||
|
||||
Object.fromByteArray = function() {
|
||||
throw new Error("Initialization error. Object.fromByteArray is not implemented, it implements in factory.js");
|
||||
}
|
||||
|
||||
module.exports = Object;
|
84
libjs/wType/string.js
Normal file
84
libjs/wType/string.js
Normal file
|
@ -0,0 +1,84 @@
|
|||
"use strict";
|
||||
var Object = require("./object");
|
||||
|
||||
var String = Object.inherit({
|
||||
"className": "String",
|
||||
"constructor": function(source) {
|
||||
Object.fn.constructor.call(this);
|
||||
|
||||
this._data = "";
|
||||
this._parseSource(source || "");
|
||||
},
|
||||
"destructor": function () {
|
||||
this.clear();
|
||||
|
||||
Object.fn.destructor.call(this);
|
||||
},
|
||||
"<": function(other) {
|
||||
if (!(other instanceof String)) {
|
||||
throw new Error("Can compare String only with String");
|
||||
}
|
||||
return this._data < other._data;
|
||||
},
|
||||
">": function(other) {
|
||||
if (!(other instanceof String)) {
|
||||
throw new Error("Can compare String only with String");
|
||||
}
|
||||
return this._data > other._data;
|
||||
},
|
||||
"==": function(other) {
|
||||
if (this.getType() !== other.getType()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this._data === other._data;
|
||||
},
|
||||
"+=": function(str) {
|
||||
this._data += str.toString();
|
||||
},
|
||||
"clear": function() {
|
||||
this._data = "";
|
||||
},
|
||||
"clone": function() {
|
||||
var clone = new String(this._data);
|
||||
|
||||
return clone;
|
||||
},
|
||||
"deserialize": function(ba) {
|
||||
this.clear();
|
||||
var size = ba.pop32();
|
||||
|
||||
for (var i = 0; i < size; ++i) {
|
||||
var cc = ba.pop16();
|
||||
this._data += global.String.fromCharCode(cc);
|
||||
}
|
||||
},
|
||||
"length": function() {
|
||||
return this._data.length;
|
||||
},
|
||||
"serialize": function(ba) {
|
||||
ba.push32(this._data.length);
|
||||
|
||||
for (var i = 0; i < this._data.length; ++i) {
|
||||
var code = this._data.charCodeAt(i);
|
||||
ba.push16(code);
|
||||
}
|
||||
},
|
||||
"size": function() {
|
||||
return this._data.length * 2 + 4;
|
||||
},
|
||||
"toString": function() {
|
||||
return this._data;
|
||||
},
|
||||
"valueOf": function() {
|
||||
return this.toString();
|
||||
},
|
||||
"_parseSource": function(source) {
|
||||
if (typeof source !== "string") {
|
||||
throw new Error("Wrong argument to construct String");
|
||||
}
|
||||
this._data = source;
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = String;
|
95
libjs/wType/uint64.js
Normal file
95
libjs/wType/uint64.js
Normal file
|
@ -0,0 +1,95 @@
|
|||
"use strict";
|
||||
var Object = require("./object");
|
||||
|
||||
var Uint64 = Object.inherit({
|
||||
"className": "Uint64",
|
||||
"constructor": function(int) {
|
||||
Object.fn.constructor.call(this);
|
||||
|
||||
this._h = 0;
|
||||
this._l = 0;
|
||||
|
||||
this._parseSource(int || 0);
|
||||
},
|
||||
"<": function(other) {
|
||||
if (!(other instanceof Uint64)) {
|
||||
throw new Error("Can compare Uint64 only with Uint64");
|
||||
}
|
||||
if (this._h < other._h) {
|
||||
return true;
|
||||
} else if(this._h === other._h) {
|
||||
return this._l < other._l;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
">": function(other) {
|
||||
if (!(other instanceof Uint64)) {
|
||||
throw new Error("Can compare Uint64 only with Uint64");
|
||||
}
|
||||
if (this._h > other._h) {
|
||||
return true;
|
||||
} else if(this._h === other._h) {
|
||||
return this._l > other._l;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
"==": function(other) {
|
||||
if (this.getType() !== other.getType()) {
|
||||
return false;
|
||||
}
|
||||
return (this._h == other._h) && (this._l == other._l);
|
||||
},
|
||||
"++": function() {
|
||||
++this._l;
|
||||
if (this._l === 4294967296) {
|
||||
this._l = 0;
|
||||
++this._h;
|
||||
}
|
||||
},
|
||||
"clone": function() {
|
||||
var clone = new Uint64();
|
||||
clone._l = this._l;
|
||||
clone._h = this._h;
|
||||
|
||||
return clone;
|
||||
},
|
||||
"deserialize": function(ba) {
|
||||
this._h = ba.pop32();
|
||||
this._l = ba.pop32();
|
||||
},
|
||||
"length": function() {
|
||||
return 1;
|
||||
},
|
||||
"serialize": function(ba) {
|
||||
ba.push32(this._h);
|
||||
ba.push32(this._l);
|
||||
},
|
||||
"size": function() {
|
||||
return 8;
|
||||
},
|
||||
"toString": function() {
|
||||
if (this._h !== 0) {
|
||||
console.log(this._h);
|
||||
console.log(this._l);
|
||||
throw new Error("Don't know yet how to show uint64 in javascript");
|
||||
}
|
||||
return this._l.toString();
|
||||
},
|
||||
"valueOf": function() {
|
||||
if (this._h !== 0) {
|
||||
throw new Error("Don't know yet how to show uint64 in javascript");
|
||||
}
|
||||
return this._l;
|
||||
},
|
||||
"_parseSource": function(int) {
|
||||
if (parseInt(int) !== int) {
|
||||
throw new Error("Wrong argument to construct Uint64");
|
||||
}
|
||||
|
||||
this._l = int & 0xffffffff;
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Uint64;
|
112
libjs/wType/vector.js
Normal file
112
libjs/wType/vector.js
Normal file
|
@ -0,0 +1,112 @@
|
|||
"use strict";
|
||||
var Object = require("./object");
|
||||
|
||||
var Vector = Object.inherit({
|
||||
"className": "Vector",
|
||||
"constructor": function() {
|
||||
Object.fn.constructor.call(this);
|
||||
|
||||
this._data = [];
|
||||
},
|
||||
"destructor": function() {
|
||||
this.clear();
|
||||
|
||||
Object.fn.destructor.call(this);
|
||||
},
|
||||
"==": function(other) {
|
||||
if (this.getType() !== other.getType()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this._data.length !== other._data.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var hopMe;
|
||||
var hopOt;
|
||||
|
||||
for (var i = 0; i < this._data.length; ++i) {
|
||||
hopMe = this._data[i];
|
||||
hopOt = other._data[i];
|
||||
if ( !(hopMe["=="](hopOt)) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
"at": function(index) {
|
||||
return this._data[index];
|
||||
},
|
||||
"clear": function() {
|
||||
for (var i = 0; i < this._data.length; ++i) {
|
||||
this._data[i].destructor();
|
||||
}
|
||||
|
||||
this._data = [];
|
||||
},
|
||||
"clone": function() {
|
||||
var clone = new Vector();
|
||||
|
||||
for (var i = 0; i < this._data.length; ++i) {
|
||||
clone.push(this._data[i].clone());
|
||||
}
|
||||
|
||||
return clone;
|
||||
},
|
||||
"deserialize": function(ba) {
|
||||
this.clear();
|
||||
|
||||
var length = ba.pop32();
|
||||
|
||||
for (var i = 0; i < length; ++i) {
|
||||
var value = Object.fromByteArray(ba);
|
||||
this.push(value);
|
||||
}
|
||||
},
|
||||
"length": function() {
|
||||
return this._data.length;
|
||||
},
|
||||
"push": function(value) {
|
||||
if (!(value instanceof Object)) {
|
||||
throw new Error("An attempt to insert not a W::Object into a vector");
|
||||
}
|
||||
this._data.push(value);
|
||||
},
|
||||
"serialize": function(ba) {
|
||||
ba.push32(this._data.length);
|
||||
|
||||
for (var i = 0; i < this._data.length; ++i) {
|
||||
var el = this._data[i];
|
||||
ba.push8(el.getType());
|
||||
el.serialize(ba);
|
||||
}
|
||||
},
|
||||
"size": function() {
|
||||
var size = 4;
|
||||
|
||||
for (var i = 0; i < this._data.length; ++i) {
|
||||
size += this._data[i].size() + 1;
|
||||
}
|
||||
|
||||
return size;
|
||||
},
|
||||
"toString": function() {
|
||||
var str = "[";
|
||||
|
||||
var ft = true;
|
||||
|
||||
for (var i = 0; i < this._data.length; ++i) {
|
||||
if (ft) {
|
||||
ft = false;
|
||||
} else {
|
||||
str += ", ";
|
||||
}
|
||||
str += this._data[i].toString();
|
||||
|
||||
}
|
||||
str += "]";
|
||||
return str;
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Vector;
|
155
libjs/wType/vocabulary.js
Normal file
155
libjs/wType/vocabulary.js
Normal file
|
@ -0,0 +1,155 @@
|
|||
"use strict";
|
||||
var Object = require("./object");
|
||||
var String = require("./string");
|
||||
|
||||
var Vocabulary = Object.inherit({
|
||||
"className": "Vocabulary",
|
||||
"constructor": function() {
|
||||
Object.fn.constructor.call(this);
|
||||
|
||||
this._data = global.Object.create(null);
|
||||
this._length = 0;
|
||||
},
|
||||
"destructor": function() {
|
||||
this.clear();
|
||||
|
||||
Object.fn.destructor.call(this);
|
||||
},
|
||||
"==": function(other) {
|
||||
if (this.getType() !== other.getType()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this._length !== other._length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var keysMe = this.getKeys();
|
||||
var key;
|
||||
var mValue;
|
||||
var oValue;
|
||||
|
||||
for (var i = 0; i < this._length; ++i) {
|
||||
key = keysMe[i];
|
||||
oValue = other._data[key];
|
||||
if (oValue === undefined) {
|
||||
return false;
|
||||
}
|
||||
mValue = this._data[key];
|
||||
if (!oValue["=="](mValue)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
"at": function(str) {
|
||||
return this._data[str];
|
||||
},
|
||||
"clear": function() {
|
||||
for (var key in this._data) {
|
||||
this._data[key].destructor();
|
||||
}
|
||||
|
||||
this._data = global.Object.create(null);
|
||||
this._length = 0;
|
||||
},
|
||||
"clone": function() {
|
||||
var clone = new Vocabulary();
|
||||
|
||||
for (var key in this._data) {
|
||||
clone._data[key] = this._data[key].clone();
|
||||
}
|
||||
clone._length = this._length;
|
||||
|
||||
return clone;
|
||||
},
|
||||
"deserialize": function(ba) {
|
||||
this.clear();
|
||||
|
||||
this._length = ba.pop32()
|
||||
|
||||
for (var i = 0; i < this._length; ++i) {
|
||||
var key = new String();
|
||||
key.deserialize(ba);
|
||||
|
||||
var value = Object.fromByteArray(ba);
|
||||
this._data[key.toString()] = value;
|
||||
}
|
||||
},
|
||||
"erase": function(key) {
|
||||
var value = this._data[key];
|
||||
if (value === undefined) {
|
||||
throw new Error("An attempt to erase not existing object from vocabulary");
|
||||
}
|
||||
value.destructor();
|
||||
delete this._data[key];
|
||||
--this._length;
|
||||
},
|
||||
"getKeys": function() {
|
||||
return global.Object.keys(this._data);
|
||||
},
|
||||
"has": function(key) {
|
||||
return this._data[key] instanceof Object;
|
||||
},
|
||||
"insert": function(key, value) {
|
||||
if (!(value instanceof Object)) {
|
||||
throw new Error("An attempt to insert not a W::Object into vocabulary");
|
||||
}
|
||||
var oldValue = this._data[key];
|
||||
if (oldValue !== undefined) {
|
||||
oldValue.destructor();
|
||||
--this._length;
|
||||
}
|
||||
this._data[key] = value
|
||||
|
||||
++this._length;
|
||||
},
|
||||
"length": function() {
|
||||
return this._length;
|
||||
},
|
||||
"serialize": function(ba) {
|
||||
ba.push32(this._length);
|
||||
|
||||
for (var key in this._data) {
|
||||
var sKey = new String(key);
|
||||
var value = this._data[key];
|
||||
|
||||
sKey.serialize(ba);
|
||||
ba.push8(value.getType());
|
||||
value.serialize(ba);
|
||||
}
|
||||
},
|
||||
"size": function() {
|
||||
var size = 4;
|
||||
|
||||
for (var key in this._data) {
|
||||
var sKey = new String(key);
|
||||
var value = this._data[key];
|
||||
|
||||
size += sKey.size();
|
||||
size += value.size() + 1;
|
||||
}
|
||||
|
||||
return size;
|
||||
},
|
||||
"toString": function() {
|
||||
var str = "{";
|
||||
|
||||
var ft = true;
|
||||
|
||||
for (var key in this._data) {
|
||||
if (ft) {
|
||||
ft = false;
|
||||
} else {
|
||||
str += ", ";
|
||||
}
|
||||
str += key + ": ";
|
||||
str += this._data[key].toString();
|
||||
|
||||
}
|
||||
str += "}";
|
||||
return str;
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Vocabulary;
|
Loading…
Add table
Add a link
Reference in a new issue