diff src/implab/di/ActivationContext.js @ 0:fc2517695ee1

Initial commit, draft import of existing work
author cin
date Thu, 01 Jun 2017 13:20:03 +0300
parents
children 00779cb63b12
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/implab/di/ActivationContext.js	Thu Jun 01 13:20:03 2017 +0300
@@ -0,0 +1,139 @@
+define([
+        "../declare",
+        "../safe",
+        "./Descriptor",
+        "./ValueDescriptor"
+    ],
+
+    function (declare, safe, Descriptor, Value) {
+        var Context = declare(null, {
+
+            _cache: null,
+
+            _services: null,
+
+            _stack: null,
+
+            _visited: null,
+
+            container: null,
+
+            _trace: false,
+
+            constructor: function (container, services, cache, visited) {
+                safe.argumentNotNull(container, "container");
+                safe.argumentNotNull(services, "services");
+
+                this._visited = visited || {};
+                this._stack = [];
+                this._cache = cache || {};
+                this._services = services;
+                this.container = container;
+            },
+
+            getService: function (name, def) {
+                var d = this._services[name];
+
+                if (!d)
+                    if (arguments.length > 1)
+                        return def;
+                    else
+                        throw new Error("Service '" + name + "' not found");
+
+                return d.activate(this, name);
+            },
+
+            /**
+             * registers services local to the the activation context
+             * 
+             * @name{string} the name of the service
+             * @service{string} the service descriptor to register
+             */
+            register: function (name, service) {
+                safe.argumentNotEmptyString(name, "name");
+
+                if (!(service instanceof Descriptor))
+                    service = new Value(service, true);
+                this._services[name] = service;
+            },
+
+            clone: function () {
+                return new Context(
+                    this.container,
+                    safe.create(this._services),
+                    this._cache,
+                    this._visited
+                );
+
+            },
+
+            has: function (id) {
+                return id in this._cache;
+            },
+
+            get: function (id) {
+                return this._cache[id];
+            },
+
+            store: function (id, value) {
+                return (this._cache[id] = value);
+            },
+
+            parse: function (data, name) {
+                var me = this;
+                if (safe.isPrimitive(data))
+                    return data;
+
+                if (data instanceof Descriptor) {
+                    return data.activate(this, name);
+                } else if (data instanceof Array) {
+                    me.enter(name);
+                    var v = data.map(function (x, i) {
+                        return me.parse(x, "." + i);
+                    });
+                    me.leave();
+                    return v;
+                } else {
+                    me.enter(name);
+                    var result = {};
+                    for (var p in data)
+                        result[p] = me.parse(data[p], "." + p);
+                    me.leave();
+                    return result;
+                }
+            },
+
+            visit: function (id) {
+                var count = this._visited[id] || 0;
+                this._visited[id] = count + 1;
+                return count;
+            },
+
+            getStack: function () {
+                return this._stack.slice().reverse();
+            },
+
+            enter: function (name, d, localize) {
+                if (this._trace)
+                    console.log("enter " + name + " " + (d || "") +
+                        (localize ? " localize" : ""));
+                this._stack.push({
+                    name: name,
+                    service: d,
+                    scope: this._services
+                });
+                if (localize)
+                    this._services = safe.create(this._services);
+            },
+
+            leave: function () {
+                var ctx = this._stack.pop();
+                this._services = ctx.scope;
+
+                if (this._trace)
+                    console.log("leave " + ctx.name + " " + (ctx.service || ""));
+            }
+        });
+
+        return Context;
+    });
\ No newline at end of file