UNPKG

jaydata-core

Version:

Cross-platform HTML5 data-management, JavaScript Language Query (JSLQ) support for OData, SQLite, WebSQL, IndexedDB, YQL and Facebook (packaged for Node.JS)

1,134 lines (993 loc) 65.2 kB
(function init($data, global) { function il(msg) { if (typeof intellisense !== 'undefined') { if (!intellisense.i) { intellisense.i = 0; } intellisense.i = intellisense.i + 1; intellisense.logMessage(msg + ":" + intellisense.i); } } function MemberDefinition(memberDefinitionData, definedClass) { ///<field name="name" type="String">*</field> ///<field name="dataType" type="Object">*</field> ///<field name="elementType" type="Object"></field> ///<field name="kind" type="String" /> ///<field name="classMember" type="Boolean" /> ///<field name="set" type="Function" /> ///<field name="get" type="Function" /> ///<field name="value" type="Object" /> ///<field name="initialValue" type="Object" /> ///<field name="method" type="Function" /> ///<field name="enumerable" type="Boolean" /> ///<field name="configurable" type="Boolean" /> ///<field name="key" type="Boolean" /> ///<field name="computed" type="Boolean" /> ///<field name="storeOnObject" type="Boolean">[false] if false value is stored in initData, otherwise on the object</field> ///<field name="monitorChanges" type="Boolean">[true] if set to false propertyChange events are not raise and property tracking is disabled</field> this.kind = MemberTypes.property; //this.definedBy = definedClass; Object.defineProperty(this, 'definedBy', { value: definedClass, enumerable: false, configurable: false, writable: false }); if (memberDefinitionData) { if (typeof memberDefinitionData === 'function' || typeof memberDefinitionData.asFunction === 'function') { this.method = memberDefinitionData; this.kind = MemberTypes.method; } else { this.enumerable = true; this.configurable = true; if (typeof memberDefinitionData === "number") { this.value = memberDefinitionData; this.type = $data.Number; this.dataType = $data.Number; } else if (typeof memberDefinitionData === "string") { this.value = memberDefinitionData; this.dataType = $data.String; this.type = $data.String; } else { for (var item in memberDefinitionData) { if (memberDefinitionData.hasOwnProperty(item)) { this[item] = memberDefinitionData[item]; } } } } if (this.type !== undefined) { this.dataType = this.dataType || this.type; } else { this.type = this.dataType; } this.originalType = this.type; if (this.elementType !== undefined) { this.originalElementType = this.elementType; } } } MemberDefinition.prototype.createPropertyDescriptor = function (classFunction, value) { ///<returns type="Object" /> var pd = this; var result = { enumerable: this.enumerable == undefined ? true : this.enumerable, configurable: this.configurable == undefined ? true : this.configurable }; if (this.set && this.get) { result.set = this.set; result.get = this.get; } else if ("value" in this || value) { result.value = value || this.value; //TODO //result.writable = this.writable; result.writable = true; } else { result.set = function (value) { this.storeProperty(pd, value); }; result.get = function () { return this.retrieveProperty(pd); }; } return result; }; MemberDefinition.prototype.createStorePropertyDescriptor = function (value) { var pd = this; return { enumerable: false, writable: true, configurable: pd.configurable, value: value }; }; MemberDefinition.prototype.createGetMethod = function () { var pd = this; return { enumerable: false, writable: false, configurable: false, value: function (callback, tran) { return this.getProperty(pd, callback, tran); } }; }; MemberDefinition.prototype.createSetMethod = function () { var pd = this; return { enumerable: false, writable: false, configurable: false, value: function (value, callback, tran) { return this.setProperty(pd, value, callback, tran); } }; }; MemberDefinition.translateDefinition = function (memDef, name, classFunction) { var holder = classFunction; var memberDefinition; if (memDef.type && Container.isTypeRegistered(memDef.type)) { holder = Container.resolveType(memDef.type); if (typeof holder.translateDefinition === 'function') { memberDefinition = holder.translateDefinition.apply(holder, arguments); memberDefinition.name = memberDefinition.name || name; } else { holder = classFunction; } } if (!(memberDefinition instanceof MemberDefinition)) { memberDefinition = new MemberDefinition(memberDefinition || memDef, holder); memberDefinition.name = name; } classFunction.resolverThunks = classFunction.resolverThunks || []; classFunction.childResolverThunks = classFunction.childResolverThunks || []; var t = memberDefinition.type; var et = memberDefinition.elementType; function addChildThunk(referencedType) { if (referencedType && referencedType.isAssignableTo && $data.Entity && referencedType.isAssignableTo($data.Entity)) { classFunction.childResolverThunks.push(function () { if (referencedType.resolveForwardDeclarations) { referencedType.resolveForwardDeclarations(); } }); } } addChildThunk(t); addChildThunk(et); if ("string" === typeof t) { if ("@" === t[0]) { memberDefinition.type = t.substr(1); memberDefinition.dataType = t.substr(1); } else { //forward declared types get this callback when type is registered classFunction.resolverThunks.push(function () { var rt = classFunction.container.resolveType(t); addChildThunk(rt); memberDefinition.type = rt; memberDefinition.dataType = rt; }); } } if (et) { if ("string" === typeof et) { if ("@" === et[0]) { memberDefinition.elementType = et.substr(1); } else { //forward declared types get this callback when type is registered classFunction.resolverThunks.push(function () { var rt = classFunction.container.resolveType(et); addChildThunk(rt); memberDefinition.elementType = rt; }); } } } //if (!classFunction) classFunction.resolveForwardDeclarations = function () { classFunction.resolveForwardDeclarations = function () { }; $data.Trace.log("resolving: " + classFunction.fullName); this.resolverThunks.forEach(function (thunk) { thunk(); }); //this.resolverThunks = []; this.childResolverThunks.forEach(function (thunk) { thunk(); }); //this.childResolverThunks = []; } return memberDefinition; }; MemberDefinition.prototype.toJSON = function () { var property = {}; for (var name in this) { if (name !== 'defineBy' && name !== 'storageModel') { if ((name === 'type' || name === 'dataType') && (this[name] && typeof this[name] === 'function')) { try { property[name] = Container.resolveName(this[name]); } catch (e) { property[name] = this[name]; } } else { property[name] = this[name]; } } } return property; } //TODO global/window $data.MemberDefinition = window["MemberDefinition"] = MemberDefinition; var memberDefinitionPrefix = '$'; function MemberDefinitionCollection() { }; MemberDefinitionCollection.prototype = { clearCache: function () { this.arrayCache = undefined; this.pubMapPropsCache = undefined; this.keyPropsCache = undefined; this.propByTypeCache = undefined; this.pubMapMethodsCache = undefined; this.pubMapPropNamesCache = undefined; }, asArray: function () { if (!this.arrayCache) { this.arrayCache = []; for (var i in this) { if (i.indexOf(memberDefinitionPrefix) === 0) this.arrayCache.push(this[i]); } } return this.arrayCache; }, getPublicMappedProperties: function () { if (!this.pubMapPropsCache) { this.pubMapPropsCache = []; for (var i in this) { if (i.indexOf(memberDefinitionPrefix) === 0 && this[i].kind == 'property' && !this[i].notMapped && this[i].enumerable) this.pubMapPropsCache.push(this[i]); } } return this.pubMapPropsCache;// || (this.pubMapPropsCache = this.asArray().filter(function (m) { return m.kind == 'property' && !m.notMapped && m.enumerable; })); }, getPublicMappedPropertyNames: function () { if (!this.pubMapPropNamesCache) { this.pubMapPropNamesCache = []; for (var i in this) { if (i.indexOf(memberDefinitionPrefix) === 0 && this[i].kind == 'property' && !this[i].notMapped && this[i].enumerable) this.pubMapPropNamesCache.push(this[i].name); } } return this.pubMapPropNamesCache; }, getKeyProperties: function () { if (!this.keyPropsCache) { this.keyPropsCache = []; for (var i in this) { if (i.indexOf(memberDefinitionPrefix) === 0 && this[i].kind == 'property' && this[i].key) this.keyPropsCache.push(this[i]); } } return this.keyPropsCache; //return this.keyPropsCache || (this.keyPropsCache = this.asArray().filter(function (m) { return m.kind == 'property' && m.key; })); }, getPublicMappedMethods: function () { if (!this.pubMapMethodsCache) { this.pubMapMethodsCache = []; for (var i in this) { if (i.indexOf(memberDefinitionPrefix) === 0 && this[i].kind == 'method' && this[i].method/* && this.hasOwnProperty(i)*/) this.pubMapMethodsCache.push(this[i]); } } return this.pubMapMethodsCache; }, getPropertyByType: function (type) { if (!this.propByTypeCache) { this.propByTypeCache = []; for (var i in this) { if (i.indexOf(memberDefinitionPrefix) === 0 && this[i].dataType == type) this.propByTypeCache.push(this[i]); } } return this.propByTypeCache; //return this.propByTypeCache || (this.propByTypeCache = this.asArray().filter(function (m) { return m.dataType == type; })); }, getMember: function (name) { return this[memberDefinitionPrefix + name]; }, setMember: function (value) { this[memberDefinitionPrefix + value.name] = value; } }; MemberDefinitionCollection.prototype.constructor = MemberDefinitionCollection; $data.MemberDefinitionCollection = window["MemberDefinitionCollection"] = MemberDefinitionCollection; function ClassEngineBase() { this.classNames = {}; } function MemberTypes() { ///<field name="method" type="string" /> ///<field name="property" type="string" /> ///<field name="field" type="string" /> ///<field name="complexProperty" type="string" /> } MemberTypes.__enum = true; MemberTypes.method = "method"; MemberTypes.property = "property"; MemberTypes.navProperty = "navProperty"; MemberTypes.complexProperty = "complexProperty"; MemberTypes.field = "field"; $data.MemberTypes = MemberTypes; //function classToJSON() { // var ret = {}; // for (var i in this) { // if (this.hasOwnProperty(i)) { // ret[i] = this[i]; // } // } // return ret; //} //$data.Base.toJSON = classToJSON; ClassEngineBase.prototype = { //getClass: function (classReference) { //}, //getProperties: function (classFunction) { // return classFunction.propertyDefinitions; //}, define: function (className, baseClass, container, instanceDefinition, classDefinition) { /// <signature> /// <summary>Creates a Jaydata type</summary> /// <param name="className" type="String">Name of the class</param> /// <param name="baseClass" type="Function">Basetype of the class</param> /// <param name="interfaces" type="Object" elementType="Function" /> /// <param name="instanceDefinition" type="Object">Class definition (properties, methods, etc)</param> /// <param name="classDefinition" type="Object">Class static definition</param> /// <example> /// /// var t = new $data.Class.define('Types.A', $data.Base, null, { /// constructor: function(){ }, /// func1: function(){ }, /// member1: { type: 'string' } /// }, { /// staticFunc1: function() {} /// }) /// /// </example> /// </signature> return this.defineEx(className, [{ type: baseClass }], container, instanceDefinition, classDefinition); }, defineEx: function (className, baseClasses, container, instanceDefinition, classDefinition) { /// <signature> /// <summary>Creates a Jaydata type</summary> /// <param name="className" type="String">Name of the class</param> /// <param name="baseClasses" type="Array" elementType="Functions">Basetypes of the class. First is a real base, others are mixins</param> /// <param name="interfaces" type="Object" elementType="Function" /> /// <param name="instanceDefinition" type="Object">Class definition (properties, methods, etc)</param> /// <param name="classDefinition" type="Object">Class static definition</param> /// <example> /// /// var t = new $data.Class.define('Types.A', [$data.Base, $data.Mixin1, $data.Mixin2], null, { /// constructor: function(){ }, /// func1: function(){ }, /// member1: { type: 'string' } /// }, { /// staticFunc1: function() {} /// }) /// /// </example> /// </signature> /// <signature> /// <summary>Creates a Jaydata type</summary> /// <param name="className" type="String">Name of the class</param> /// <param name="baseClasses" type="Array" elementType="Object">Basetypes of the class. First is a real base, others are mixins or propagations</param> /// <param name="interfaces" type="Object" elementType="Function" /> /// <param name="instanceDefinition" type="Object">Class definition (properties, methods, etc)</param> /// <param name="classDefinition" type="Object">Class static definition</param> /// <example> /// /// var t = new $data.Class.define('Types.A', [ /// { type: $data.Base, params: [1, 'secondParameterValue', new ConstructorParameter(0)] }, /// { type: $data.Mixin1, }, /// { type: $data.Mixin2, }, /// { type: $data.Propagation1, params: [new ConstructorParameter(1)], propagateTo:'Propagation1' }, /// { type: $data.Propagation2, params: ['firstParameterValue'], propagateTo:'Propagation2' } /// ], null, { /// constructor: function(){ }, /// func1: function(){ }, /// member1: { type: 'string' } /// }, { /// staticFunc1: function() {} /// }) /// /// </example> /// </signature> container = container || $data.Container; if (baseClasses.length == 0) { baseClasses.push({ type: $data.Base }); } else if (baseClasses.length > 0 && !baseClasses[0].type) { baseClasses[0].type = $data.Base; } for (var i = 0, l = baseClasses.length; i < l; i++) { if (typeof baseClasses[i] === 'function') baseClasses[i] = { type: baseClasses[i] }; } var providedCtor = instanceDefinition ? instanceDefinition.constructor : undefined; var classNameParts = className.split('.'); var shortClassName = classNameParts.splice(classNameParts.length - 1, 1)[0]; var root = container === $data.Container ? window : container; for (var i = 0; i < classNameParts.length; i++) { var part = classNameParts[i]; if (!root[part]) { var ns = {}; ns.__namespace = true; root[part] = ns; } root = root[part]; } var classFunction = null; classFunction = this.classFunctionBuilder(shortClassName, baseClasses, classDefinition, instanceDefinition); classFunction.fullName = className; classFunction.namespace = classNameParts.join('.'); //classname splitted classFunction.name = shortClassName; classFunction.container = container; classFunction.container.registerType(className, classFunction); this.buildType(classFunction, baseClasses, instanceDefinition, classDefinition); if (typeof intellisense !== 'undefined') { if (instanceDefinition && instanceDefinition.constructor) { intellisense.annotate(classFunction, instanceDefinition.constructor); } } root[shortClassName] = this.classNames[className] = classFunction; //classFunction.toJSON = classToJSON; var baseCount = classFunction.baseTypes.length; for (var i = 0; i < baseCount; i++) { var b = classFunction.baseTypes[i]; if ("inheritedTypeProcessor" in b) { b.inheritedTypeProcessor(classFunction); } } //classFunction.prototype.constructor = instanceDefinition.constructor; //classFunction.constructor = instanceDefinition.constructor; //classFunction.toJSON = function () { return classFunction.memberDefinitions.filter( function(md) { return md; }; return classFunction; }, classFunctionBuilder: function (name, base, classDefinition, instanceDefinition) { var body = this.bodyBuilder(base, classDefinition, instanceDefinition); return new Function('base', 'classDefinition', 'instanceDefinition', 'name', 'return function ' + name + ' (){ ' + body + ' \n}; ')(base, classDefinition, instanceDefinition, name); }, bodyBuilder: function (bases, classDefinition, instanceDefinition) { var mixin = ''; var body = ''; var propagation = ''; for (var i = 0, l = bases.length; i < l; i++) { var base = bases[i]; var index = i; if (index == 0) { //ctor func if (base && base.type && base.type !== $data.Base && base.type.fullName) { body += ' var baseArguments = $data.typeSystem.createCtorParams(arguments, base[' + index + '].params, this); \n'; body += ' ' + base.type.fullName + '.apply(this, baseArguments); \n'; } } else { if (base && base.type && base.propagateTo) { //propagation propagation += ' ' + (!propagation ? 'var ' : '' + '') + 'propagationArguments = $data.typeSystem.createCtorParams(arguments, base[' + index + '].params, this); \n'; propagation += ' this["' + base.propagateTo + '"] = Object.create(' + base.type.fullName + '.prototype); \n' + ' ' + base.type.fullName + '.apply(this["' + base.propagateTo + '"], propagationArguments); \n'; } else if (base && base.type && base.type.memberDefinitions && base.type.memberDefinitions.$constructor && !base.propagateTo) { //mixin mixin += ' ' + base.type.fullName + '.memberDefinitions.$constructor.method.apply(this); \n'; } } } if (instanceDefinition && instanceDefinition.constructor != Object) body += " instanceDefinition.constructor.apply(this, arguments); \n"; return '\n //mixins \n' + mixin + '\n //construction \n' + body + '\n //propagations \n' + propagation; }, buildType: function (classFunction, baseClasses, instanceDefinition, classDefinition) { var baseClass = baseClasses[0].type; classFunction.inheritsFrom = baseClass; if (baseClass) { classFunction.prototype = Object.create(baseClass.prototype); classFunction.memberDefinitions = Object.create(baseClass.memberDefinitions || new MemberDefinitionCollection()); classFunction.memberDefinitions.clearCache(); var staticDefs = baseClass.staticDefinitions; if (staticDefs) { staticDefs = staticDefs.asArray(); if (staticDefs) { for (var i = 0; i < staticDefs.length; i++) { this.buildMember(classFunction, staticDefs[i], undefined, 'staticDefinitions'); } } } classFunction.baseTypes = baseClass.baseTypes ? [].concat(baseClass.baseTypes) : []; for (var i = 0; i < baseClasses.length; i++) { classFunction.baseTypes.push(baseClasses[i].type); } //classFunction.baseTypes = (baseClass.baseTypes || []).concat(baseClasses.map(function (base) { return base.type; })); if (!classFunction.isAssignableTo) { Object.defineProperty(classFunction, "isAssignableTo", { value: function (type) { return this === type || this.baseTypes.indexOf(type) >= 0; }, writable: false, enumerable: false, configurable: false }); } } if (classDefinition) { this.buildStaticMembers(classFunction, classDefinition); if (classDefinition.constructor) classFunction.classConstructor = classDefinition.constructor; } if (instanceDefinition) { this.buildInstanceMembers(classFunction, instanceDefinition); } var mixins = [].concat(baseClasses); mixins.shift(); if (Object.keys(mixins).length > 0) this.buildInstanceMixins(classFunction, mixins); classFunction.__class = true; classFunction.prototype.constructor = classFunction; Object.defineProperty(classFunction.prototype, "getType", { value: function () { return classFunction; }, writable: false, enumerable: false, configurable: false }); }, addMethod: function (holder, name, method, propagation) { if (!propagation || (typeof intellisense !== 'undefined')) { holder[name] = method; } else { holder[name] = function () { return method.apply(this[propagation], arguments); }; } }, addProperty: function (holder, name, propertyDescriptor, propagation) { //holder[name] = {}; if (propagation) { propertyDescriptor.configurable = true; if (propertyDescriptor.get) { var origGet = propertyDescriptor.get; propertyDescriptor.get = function () { if (!this[propagation]) Guard.raise(new Exception("not inicialized")); return origGet.apply(this[propagation], arguments); }; } if (propertyDescriptor.set) { var origSet = propertyDescriptor.set; propertyDescriptor.set = function () { if (!this[propagation]) Guard.raise(new Exception("not inicialized")); origSet.apply(this[propagation], arguments); }; } } Object.defineProperty(holder, name, propertyDescriptor); }, addField: function (holder, name, field) { Guard.raise("not implemented"); }, buildMethod: function (classFunction, memberDefinition, propagation) { ///<param name="classFunction" type="Function">The object that will receive member</param> ///<param name="memberDefinition" type="MemberDefinition">the newly added member</param> var holder = memberDefinition.classMember ? classFunction : classFunction.prototype; this.addMethod(holder, memberDefinition.name, memberDefinition.method, propagation); }, buildProperty: function (classFunction, memberDefinition, propagation) { ///<param name="classFunction" type="Function">The object that will receive member</param> ///<param name="memberDefinition" type="MemberDefinition">the newly added member</param> var holder = memberDefinition.classMember ? classFunction : classFunction.prototype; var pd = memberDefinition.createPropertyDescriptor(classFunction); this.addProperty(holder, memberDefinition.name, pd, propagation); //if lazyload TODO if (!memberDefinition.classMember && classFunction.__setPropertyfunctions == true && memberDefinition.withoutGetSetMethod !== true && !('get_' + memberDefinition.name in holder || 'set_' + memberDefinition.name in holder)) { var pdGetMethod = memberDefinition.createGetMethod(); this.addProperty(holder, 'get_' + memberDefinition.name, pdGetMethod, propagation); var pdSetMethod = memberDefinition.createSetMethod(); this.addProperty(holder, 'set_' + memberDefinition.name, pdSetMethod, propagation); } }, buildMember: function (classFunction, memberDefinition, propagation, memberCollectionName) { ///<param name="memberDefinition" type="MemberDefinition" /> memberCollectionName = memberCollectionName || 'memberDefinitions'; classFunction[memberCollectionName] = classFunction[memberCollectionName] || new MemberDefinitionCollection(); classFunction[memberCollectionName].setMember(memberDefinition); switch (memberDefinition.kind) { case MemberTypes.method: this.buildMethod(classFunction, memberDefinition, propagation); break; case MemberTypes.navProperty: case MemberTypes.complexProperty: case MemberTypes.property: this.buildProperty(classFunction, memberDefinition, propagation); break; default: Guard.raise("Unknown member type: " + memberDefinition.kind + "," + memberDefinition.name); } }, buildStaticMembers: function (classFunction, memberListDefinition) { ///<param name="classFunction" type="Object">The class constructor that will be extended</param> ///<param name="memberListDefinition" type="Object"></param> var t = this; for (var item in memberListDefinition) { if (memberListDefinition.hasOwnProperty(item)) { var memberDefinition = MemberDefinition.translateDefinition(memberListDefinition[item], item, classFunction); memberDefinition.classMember = true; t.buildMember(classFunction, memberDefinition, undefined, 'staticDefinitions'); } } }, buildInstanceMembers: function (classFunction, memberListDefinition) { ///<param name="classFunction" type="Function">The class constructor whose prototype will be extended</param> ///<param name="memberListDefinition" type="Object"></param> ///pinning t outside of the closure seems actually faster then passing in the this and referencing var t = this; for (var item in memberListDefinition) { if (memberListDefinition.hasOwnProperty(item)) { var memberDefinition = MemberDefinition.translateDefinition(memberListDefinition[item], item, classFunction); t.buildMember(classFunction, memberDefinition, undefined, 'memberDefinitions'); } } }, copyMembers: function (sourceType, targetType) { ///<param name="sourceType" type="Function" /> ///<param name="targetType" type="Function" /> function il(msg) { if (typeof intellisense === 'undefined') { return; } intellisense.logMessage(msg); } Object.keys(sourceType.prototype).forEach(function (item, i, src) { if (item !== 'constructor' && item !== 'toString') { il("copying item:" + item); targetType.prototype[item] = sourceType[item]; } }); }, buildInstanceMixins: function (classFunction, mixinList) { ///<param name="classFunction" type="Function">The class constructor whose prototype will be extended</param> ///<param name="mixinList" type="Array"></param> classFunction.mixins = classFunction.mixins || []; classFunction.propagations = classFunction.propagations || []; for (var i = 0; i < mixinList.length; i++) { var item = mixinList[i]; //if (classFunction.memberDefinitions.getMember(item.type.name)) { if (item.propagateTo) { this.buildInstancePropagation(classFunction, item); classFunction.propagations.push(item); classFunction.propagations[item.type.name] = true; } else { this.buildInstanceMixin(classFunction, item); classFunction.mixins.push(item); classFunction.mixins[item.type.name] = true; } }; }, buildInstanceMixin: function (classFunction, typeObj) { ///<param name="classFunction" type="Function">The class constructor whose prototype will be extended</param> ///<param name="typeObj" type="Object"></param> var memberDefs = typeObj.type.memberDefinitions.asArray(); for (var i = 0, l = memberDefs.length; i < l; i++) { var itemName = memberDefs[i].name; if (itemName !== 'constructor' && !classFunction.memberDefinitions.getMember(itemName)) { this.buildMember(classFunction, memberDefs[i]); } } if (typeObj.type.staticDefinitions) { var staticDefs = typeObj.type.staticDefinitions.asArray(); for (var i = 0, l = staticDefs.length; i < l; i++) { var itemName = staticDefs[i].name; if (itemName !== 'constructor' && !classFunction.memberDefinitions.getMember(itemName)) { this.buildMember(classFunction, staticDefs[i], undefined, 'staticDefinitions'); } } } }, buildInstancePropagation: function (classFunction, typeObj) { ///<param name="classFunction" type="Function">The class constructor whose prototype will be extended</param> ///<param name="typeObj" type="Object"></param> var memberDefs = typeObj.type.memberDefinitions.asArray(); for (var i = 0, l = memberDefs.length; i < l; i++) { var itemName = memberDefs[i].name; if (itemName !== 'constructor' && !classFunction.memberDefinitions.getMember(itemName)) { this.buildMember(classFunction, memberDefs[i], typeObj.propagateTo); } } } }; $data.Class = Class = new ClassEngineBase(); //(function (global) { global = window; function ContainerCtor(parentContainer) { var parent = parentContainer; if (parent) { parent.addChildContainer(this); } var classNames = {}; var consolidatedClassNames = []; var classTypes = []; this.classNames = classNames; this.consolidatedClassNames = consolidatedClassNames; this.classTypes = classTypes; var mappedTo = []; this.mappedTo = mappedTo; var self = this; this["holder"] = null; var IoC = function (type, parameters) { var t = self.resolveType(type); var inst = Object.create(t.prototype); t.apply(inst, parameters); return inst; }; var pendingResolutions = {}; this.pendingResolutions = pendingResolutions; function addPendingResolution(name, onResolved) { pendingResolutions[name] = pendingResolutions[name] || []; pendingResolutions[name].push(onResolved); } this.addChildContainer = function (container) { //children.push(container); } this.createInstance = function (type, parameters) { return IoC(type, parameters); }; this.mapType = function (aliasTypeOrName, realTypeOrName) { Guard.requireValue("aliasType", aliasTypeOrName); Guard.requireValue("realType", realTypeOrName); var aliasT = this.getType(aliasTypeOrName); var realT = this.getType(realTypeOrName); var aliasPos = classTypes.indexOf(aliasT); var realPos = classTypes.indexOf(realT); mappedTo[aliasPos] = realPos; }, //this.resolve = function (type, parameters) { // var classFunction = this.resolveType(type, parameters); // return new classFunction(parameters); //}; this.isPrimitiveType = function (type) { var t = this.resolveType(type); switch (true) { case t === Number: case t === String: case t === Date: case t === Boolean: case t === Array: case t === Object: case t === $data.Number: case t === $data.Integer: case t === $data.Date: case t === $data.String: case t === $data.Boolean: case t === $data.Array: case t === $data.Object: case t === $data.Guid: case t === $data.Byte: case t === $data.SByte: case t === $data.Decimal: case t === $data.Float: case t === $data.Int16: case t === $data.Int32: case t === $data.Int64: case t === $data.DateTimeOffset: case t === $data.Time: case t === $data.SimpleBase: case t === $data.Geospatial: case t === $data.GeographyBase: case t === $data.GeographyPoint: case t === $data.GeographyLineString: case t === $data.GeographyPolygon: case t === $data.GeographyMultiPoint: case t === $data.GeographyMultiLineString: case t === $data.GeographyMultiPolygon: case t === $data.GeographyCollection: case t === $data.GeometryBase: case t === $data.GeometryPoint: case t === $data.GeometryLineString: case t === $data.GeometryPolygon: case t === $data.GeometryMultiPoint: case t === $data.GeometryMultiLineString: case t === $data.GeometryMultiPolygon: case t === $data.GeometryCollection: return true; default: return false; } //return t === Number || t === String || t === Date || t === String || t === Boolean || t === Array || t === Object || // t === $data.Number || t === $data.Integer || t === $data.Date || t === $data.String || t === $data.Boolean || t === $data.Array || t === $data.Object || // t === $data.GeographyPoint || t === $data.Guid; }; this.resolveName = function (type) { var t = this.resolveType(type); var tPos = classTypes.indexOf(t); return consolidatedClassNames[tPos]; }; this.resolveType = function (typeOrName, onResolved) { //if ("string" === typeof typeOrName) { // console.log("@@@@String type!!!", typeOrName) //} var t = typeOrName; t = this.getType(t, onResolved ? true : false, onResolved); var posT = classTypes.indexOf(t); return typeof mappedTo[posT] === 'undefined' ? t : classTypes[mappedTo[posT]]; }; this.getType = function (typeOrName, doNotThrow, onResolved) { Guard.requireValue("typeOrName", typeOrName); if (typeof typeOrName === 'function') { return typeOrName; }; if (!(typeOrName in classNames)) { if (parent) { var tp = parent.getType(typeOrName, true); if (tp) return tp; } if (onResolved) { addPendingResolution(typeOrName, onResolved); return; } else if (doNotThrow) { return undefined; } else { Guard.raise(new Exception("Unable to resolve type:" + typeOrName)); } }; var result = classTypes[classNames[typeOrName]]; if (onResolved) { onResolved(result); } return result; }; this.getName = function (typeOrName) { var t = this.getType(typeOrName); var tPos = classTypes.indexOf(t); if (tPos == -1) Guard.raise("unknown type to request name for: " + typeOrName); return consolidatedClassNames[tPos]; }; this.getTypes = function () { var keys = Object.keys(classNames); var ret = []; for (var i = 0; i < keys.length; i++) { var className = keys[i]; ret.push({ name: className, type: classTypes[classNames[className]], toString: function () { return this.name; } }); } return ret; }; //this.getTypeName( in type); //this.resolveType() //this.inferTypeFromValue = function (value) { this.getTypeName = function (value) { //TODO refactor switch (typeof value) { case 'object': if (value == null) return '$data.Object'; if (value instanceof Array) return '$data.Array'; if (value.getType) return value.getType().fullName; if (value instanceof Date) return '$data.Date'; if (value instanceof $data.Guid) return '$data.Guid'; if (value instanceof $data.DateTimeOffset) return '$data.DateTimeOffset'; if (value instanceof $data.GeographyPoint) return '$data.GeographyPoint'; if (value instanceof $data.GeographyLineString) return '$data.GeographyLineString'; if (value instanceof $data.GeographyPolygon) return '$data.GeographyPolygon'; if (value instanceof $data.GeographyMultiPoint) return '$data.GeographyMultiPoint'; if (value instanceof $data.GeographyMultiLineString) return '$data.GeographyMultiLineString'; if (value instanceof $data.GeographyMultiPolygon) return '$data.GeographyMultiPolygon'; if (value instanceof $data.GeographyCollection) return '$data.GeographyCollection'; if (value instanceof $data.GeographyBase) return '$data.GeographyBase'; if (value instanceof $data.GeometryPoint) return '$data.GeometryPoint'; if (value instanceof $data.GeometryLineString) return '$data.GeometryLineString'; if (value instanceof $data.GeometryPolygon) return '$data.GeometryPolygon'; if (value instanceof $data.GeometryMultiPoint) return '$data.GeometryMultiPoint'; if (value instanceof $data.GeometryMultiLineString) return '$data.GeometryMultiLineString'; if (value instanceof $data.GeometryMultiPolygon) return '$data.GeometryMultiPolygon'; if (value instanceof $data.GeometryCollection) return '$data.GeometryCollection'; if (value instanceof $data.GeometryBase) return '$data.GeometryBase'; if (value instanceof $data.Geospatial) return '$data.Geospatial'; if (value instanceof $data.SimpleBase) return '$data.SimpleBase'; if (typeof value.toHexString === 'function') return '$data.ObjectID'; //if(value instanceof "number") return default: return typeof value; } }; this.isTypeRegistered = function (typeOrName) { if (typeof typeOrName === 'function') { return classTypes.indexOf(typeOrName) > -1; } else { return typeOrName in classNames; } }; this.unregisterType = function (type) { Guard.raise("Unimplemented"); }; this.getDefault = function (typeOrName) { var t = this.resolveType(typeOrName); switch (t) { case $data.Number: return 0.0; case $data.Float: return 0.0; case $data.Decimal: return '0.0'; case $data.Integer: return 0; case $data.Int16: return 0; case $data.Int32: return 0; case $data.Int64: return '0'; case $data.Byte: return 0; case $data.SByte: return 0; case $data.String: return null; case $data.Boolean: return false; default: return null; } }; //name array ['', '', ''] this.getIndex = function (typeOrName) { var t = this.resolveType(typeOrName); return classTypes.indexOf(t); } this.resolveByIndex = function (index) { return classTypes[index]; } this.registerType = function (nameOrNamesArray, type, factoryFunc) { ///<signature> ///<summary>Registers a type and optionally a lifetimeManager with a name ///that can be used to later resolve the type or create new instances</summary> ///<param name="nameOrNamesArray" type="Array">The names of the type</param> ///<param name="type" type="Function">The type to register</param> ///<param name="instanceManager" type="Function"></param> ///</signature> ///<signature> ///<summary>Registers a new type that </summary> ///<param name="aliasType" type="Function">The name of the type</param> ///<param name="actualType" type="Function">The type to register</param> ///</signature> ///TODO remove /*if (typeof typeNameOrAlias === 'string') { if (classNames.indexOf(typeNameOrAlias) > -1) { Guard.raise("Type already registered. Remove first"); } }*/ if (!nameOrNamesArray) { return; } //todo add ('number', 'number') if (typeof type === "string") { type = self.resolveType(type); } var namesArray = []; if (typeof nameOrNamesArray === 'string') { var tmp = []; tmp.push(nameOrNamesArray); namesArray = tmp; } else { namesArray = nameOrNamesArray; } for (var i = 0; i < namesArray.length; i++) { var parts = namesArray[i].split('.'); var item = {}; item.shortName = parts[parts.length - 1]; item.fullName = namesArray[i]; namesArray[i] = item; } //if (type. var creatorFnc = function () { return IoC(type, arguments); }; if (typeof intellisense !== 'undefined') { intellisense.annotate(creatorFnc, type); } for (var i = 0, l = namesArray.length; i < l; i++) { var item = namesArray[i]; if (!(("create" + item.shortName) in self)) { if (typeof factoryFunc === 'function') { self["create" + item.shortName] = factoryFunc; } else { self["create" + item.shortName] = creatorFnc; } } var typePos = classTypes.indexOf(type); if (typePos == -1) { //new type typePos = classTypes.push(type) - 1; var fn = item.fullName; consolidatedClassNames[typePos] = item.fullName; }; classNames[item.fullName] = typePos; var pending = pendingResolutions[item.fullName] || []; if (pending.length > 0) { pending.forEach(function (t) { t(type); }); pendingResolutions[item.fullName] = []; } } if (parent) { parent.registerType.apply(parent, arguments); } if (!type.name) { type.name = namesArray[0].shortName; } }; var _converters = { from: {}, to: {} }; this.converters = _converters; this.convertTo = function (value, tType, eType /*if Array*/, options) { Guard.requireValue("typeOrName", tType); if(Object.isNullOrUndefined(value)) return value; var sourceTypeName = Container.getTypeName(value); var sourc