181 lines
6.2 KiB
JavaScript
181 lines
6.2 KiB
JavaScript
|
"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;
|
||
|
|