jaydata
Version:
Cross-platform HTML5 data-management, JavaScript Language Query (JSLQ) support for OData, SQLite, WebSQL, IndexedDB, YQL and Facebook (packaged for Node.JS)
447 lines (425 loc) • 26.6 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };
var _index = require('../TypeSystem/index.js');
var _index2 = _interopRequireDefault(_index);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
_index2.default.Class.define('$data.ModelBinder', null, null, {
constructor: function constructor(context) {
this.context = context;
this.providerName = null;
if (this.context.storageProvider && typeof this.context.storageProvider.getType === 'function') {
this.references = !(this.context.storageProvider.providerConfiguration.modelBinderOptimization || false);
this.providerName = this.context.storageProvider.providerName;
if (!this.providerName) {
for (var i in _index2.default.RegisteredStorageProviders) {
if (_index2.default.RegisteredStorageProviders[i] === this.context.storageProvider.getType()) {
this.providerName = i;
break;
}
}
}
}
},
_deepExtend: function _deepExtend(o, r) {
if (o === null || o === undefined) {
return r;
}
for (var i in r) {
if (o.hasOwnProperty(i)) {
if (_typeof(r[i]) === 'object') {
if (Array.isArray(r[i])) {
for (var j = 0; j < r[i].length; j++) {
if (o[i].indexOf(r[i][j]) < 0) {
o[i].push(r[i][j]);
}
}
} else this._deepExtend(o[i], r[i]);
}
} else {
o[i] = r[i];
}
}
return this._finalize(o);
},
_finalize: function _finalize(o) {
if (o instanceof _index2.default.Entity) {
o.changedProperties = undefined;
o.storeToken = this.context.storeToken;
}
return o;
},
_buildSelector: function _buildSelector(meta, context) {
if (meta.$selector) {
if (!Array.isArray(meta.$selector)) {
meta.$selector = [meta.$selector];
}
for (var i = 0; i < meta.$selector.length; i++) {
var selector = meta.$selector[i].replace('json:', '');
context.src += 'if(';
var path = selector.split('.');
for (var j = 0; j < path.length; j++) {
context.src += 'di["' + path.slice(0, j + 1).join('"]["') + '"]' + (j < path.length - 1 ? ' && ' : ' !== undefined && typeof di.' + selector + ' === "object"');
}
context.src += '){di = di["' + path.join('"]["') + '"];}' + (i < meta.$selector.length - 1 ? 'else ' : '');
}
context.src += 'if (di === null){';
if (context.iter) context.src += context.iter + ' = null;';
context.src += 'return null;';
context.src += '}';
}
},
_buildKey: function _buildKey(name, type, keys, context, data) {
if (keys) {
var type = _index.Container.resolveType(type);
var typeIndex = _index.Container.getIndex(type);
type = type.fullName || type.name;
context.src += 'var ' + name + 'Fn = function(di){';
if (!Array.isArray(keys) || keys.length == 1) {
if (typeof keys !== 'string') keys = keys[0];
context.src += 'if (typeof di["' + keys + '"] === "undefined") return undefined;';
context.src += 'if (di["' + keys + '"] === null) return null;';
context.src += 'var key = ("' + type + '_' + typeIndex + '_' + keys + '#" + di["' + keys + '"]);';
} else {
context.src += 'var key = "";';
for (var i = 0; i < keys.length; i++) {
var id = _typeof(keys[i]) !== 'object' ? keys[i] : keys[i].$source;
context.src += 'if (typeof di["' + id + '"] === "undefined") return undefined;';
context.src += 'if (di["' + id + '"] === null) return null;';
context.src += 'key += ("' + type + '_' + typeIndex + '_' + id + '#" + di["' + id + '"]);';
}
}
context.src += 'return key;};';
}
context.src += 'var ' + name + ' = ' + (keys ? name + 'Fn(' + (data || 'di') + ')' : 'undefined') + ';';
},
build: function build(meta, context) {
if (meta.$selector) {
if (!Array.isArray(meta.$selector)) meta.$selector = [meta.$selector];
for (var i = 0; i < meta.$selector.length; i++) {
meta.$selector[i] = meta.$selector[i].replace('json:', '');
}
}
if (meta.$value) {
if (typeof meta.$value === 'function') {
context.src += 'var di = di || data;';
context.src += 'var fn = function(){ return meta' + (context.meta.length ? '.' + context.meta.join('.') : '') + '.$value.call(self, meta' + (context.meta.length ? '.' + context.meta.join('.') : '') + ', di); };';
if (meta.$type) {
var type = _index.Container.resolveName(_index.Container.resolveType(meta.$type));
var typeIndex = _index.Container.getIndex(_index.Container.resolveType(meta.$type));
var converter = this.context.storageProvider.fieldConverter.fromDb[type];
if (converter) {
context.item = 'self.context.storageProvider.fieldConverter.fromDb["' + type + '"](fn())';
} else {
context.item = 'new (Container.resolveByIndex(' + typeIndex + '))(fn())';
}
} else context.item = 'fn()';
} else if (meta.$type) {
var type = _index.Container.resolveName(_index.Container.resolveType(meta.$type));
var typeIndex = _index.Container.getIndex(_index.Container.resolveType(meta.$type));
var converter = this.context.storageProvider.fieldConverter.fromDb[type];
if (converter) {
context.item = 'self.context.storageProvider.fieldConverter.fromDb["' + type + '"](' + meta.$value + ')';
} else {
context.item = 'new (Container.resolveByIndex(' + typeIndex + '))(' + meta.$value + ')';
}
} else context.item = meta.$value;
} else if (meta.$source) {
var type = _index.Container.resolveName(_index.Container.resolveType(meta.$type));
var typeIndex = _index.Container.getIndex(_index.Container.resolveType(meta.$type));
var converter = this.context.storageProvider.fieldConverter.fromDb[type];
var item = '_' + type.replace(/\./gi, '_') + '_';
if (!context.forEach) context.src += 'var di = data;';
context.item = item;
this._buildSelector(meta, context);
if (converter) {
context.src += 'var ' + item + ' = self.context.storageProvider.fieldConverter.fromDb["' + type + '"](di["' + meta.$source + '"]);';
} else {
context.src += 'var ' + item + ' = new (Container.resolveByIndex(' + typeIndex + '))(di["' + meta.$source + '"]);';
}
context.src += 'var ' + item + '_inheritance;';
} else if (meta.$item) {
context.meta.push('$item');
var iter = context.item && context.current ? context.item + '.' + context.current : context.item ? context.item : 'result';
context.iter = iter;
if (iter.indexOf('.') < 0) {
context.src += 'var ' + iter + ';';
context.src += 'var ' + iter + '_inheritance;';
}
context.src += 'var fn = function(di){';
if (meta.$selector) {
context.src += 'if (typeof di !== "undefined" && !(Array.isArray(di))){';
this._buildSelector(meta, context);
context.src += '}';
}
if (this.references && meta.$keys) this._buildKey('forKey', meta.$type, meta.$keys, context);
context.src += iter + ' = typeof ' + iter + ' == "undefined" ? [] : ' + iter + ';';
if (this.references && meta.$item.$keys) {
var keycacheName = 'keycache_' + iter.replace(/\./gi, '_');
context.src += 'var ' + keycacheName + ';';
context.src += 'var kci = keycacheIter.indexOf(' + iter + ');';
context.src += 'if (kci < 0){';
context.src += keycacheName + ' = [];';
context.src += 'keycache.push(' + keycacheName + ');';
context.src += 'keycacheIter.push(' + iter + ');';
context.src += '}else{';
context.src += keycacheName + ' = keycache[kci];';
context.src += '}';
}
context.iter = undefined;
context.forEach = true;
var itemForKey = 'itemForKey_' + iter.replace(/\./gi, '_');
context.src += 'var forEachFn = function(di, i){';
context.src += 'var diBackup = di;';
if (this.providerName == "sqLite" && this.references && meta.$item.$keys) this._buildKey(itemForKey, meta.$type, meta.$item.$keys, context);
var item = context.item || 'iter';
context.item = item;
if (!meta.$item.$source) {
this._buildSelector(meta.$item, context);
}
this.build(meta.$item, context);
if (this.references && meta.$keys) {
context.src += 'if (forKey){';
context.src += 'if (cache[forKey]){';
context.src += iter + ' = cache[forKey];';
context.src += 'if (' + iter + '.indexOf(' /*+ (context.item || item) + '_inheritance || '*/ + (context.item || item) + ') < 0){';
context.src += iter + '.push(' /*+ (context.item || item) + '_inheritance || '*/ + (context.item || item) + ');';
context.src += '}}else{';
context.src += 'cache[forKey] = ' + iter + ';';
context.src += iter + '.push(' /*+ (context.item || item) + '_inheritance || '*/ + (context.item || item) + ');';
context.src += '}}else{';
if (this.references && meta.$item.$keys) this._buildKey('cacheKey', meta.$type, meta.$item.$keys, context, 'diBackup');
context.src += 'if (typeof cacheKey != "undefined" && cacheKey !== null){';
context.src += 'if (keycache_' + iter.replace(/\./gi, '_') + ' && cacheKey){';
context.src += 'if (keycache_' + iter.replace(/\./gi, '_') + '.indexOf(cacheKey) < 0){';
context.src += iter + '.push(' /*+ (context.item || item) + '_inheritance || '*/ + (context.item || item) + ');';
context.src += 'keycache_' + iter.replace(/\./gi, '_') + '.push(cacheKey);';
context.src += '}';
context.src += '}else{';
context.src += iter + '.push(' /*+ (context.item || item) + '_inheritance || '*/ + (context.item || item) + ');';
context.src += '}';
context.src += '}';
context.src += '}';
} else {
if (this.references && meta.$item.$keys) {
context.src += 'if (typeof ' + itemForKey + ' !== "undefined" && ' + itemForKey + ' !== null){';
context.src += 'if (typeof keycache_' + iter.replace(/\./gi, '_') + ' !== "undefined" && ' + itemForKey + '){';
context.src += 'if (keycache_' + iter.replace(/\./gi, '_') + '.indexOf(' + itemForKey + ') < 0){';
context.src += iter + '.push(' /*+ (context.item || item) + '_inheritance || '*/ + (context.item || item) + ');';
context.src += 'keycache_' + iter.replace(/\./gi, '_') + '.push(' + itemForKey + ');';
context.src += '}}else{';
context.src += iter + '.push(' /*+ (context.item || item) + '_inheritance || '*/ + (context.item || item) + ');';
context.src += '}}else{';
context.src += iter + '.push(' /*+ (context.item || item) + '_inheritance || '*/ + (context.item || item) + ');';
context.src += '}';
} else {
context.src += iter + '.push(' /*+ (context.item || item) + '_inheritance || '*/ + (context.item || item) + ');';
}
}
context.src += '};';
context.src += 'if (Array.isArray(di)) di.forEach(forEachFn);';
context.src += 'else forEachFn(di, 0);';
context.forEach = false;
context.item = null;
context.src += '};fn(typeof di === "undefined" ? data : di);';
context.meta.pop();
} else if (meta.$type) {
if (!context.forEach) {
context.src += 'if (typeof di === "undefined"){';
context.src += 'var di = data;';
this._buildSelector(meta, context);
context.src += '}';
}
var resolvedType = _index.Container.resolveType(meta.$type);
var type = _index.Container.resolveName(resolvedType);
var typeIndex = _index.Container.getIndex(resolvedType);
var isEntityType = resolvedType.isAssignableTo && resolvedType.isAssignableTo(_index2.default.Entity);
var item = '_' + type.replace(/\./gi, '_') + '_';
if (context.item == item) item += 'new_';
context.item = item;
var isPrimitive = false;
if (!meta.$source && !meta.$value && resolvedType !== _index2.default.Array && resolvedType !== _index2.default.Object && !resolvedType.isAssignableTo) isPrimitive = true;
if (resolvedType === _index2.default.Object || resolvedType === _index2.default.Array) {
var keys = Object.keys(meta);
if (keys.length == 1 || keys.length == 2 && meta.$selector) isPrimitive = true;
}
if (isPrimitive) {
var converter = this.context.storageProvider.fieldConverter.fromDb[type];
if (converter) {
context.src += 'var ' + item + ' = di != undefined ? self.context.storageProvider.fieldConverter.fromDb["' + type + '"](di) : di;';
} else {
context.src += 'var ' + item + ' = di;';
}
context.src += 'var ' + item + '_inheritance;';
} else {
if (this.references && meta.$keys) {
this._buildKey('itemKey', meta.$type, meta.$keys, context);
context.src += 'if (itemKey === null) return null;';
context.src += 'var ' + item + ';';
context.src += 'var ' + item + '_inheritance;';
context.src += 'if (itemKey && cache[itemKey]){';
context.src += item + ' = cache[itemKey];';
context.src += '}else{';
if (resolvedType.inheritedTo) {
context.src += 'if (di && di["@odata.type"]){';
context.src += 'var odataTypeName = di["@odata.type"].split("#")[1];';
context.src += 'var odataType = Container.resolveType(odataTypeName);';
context.src += 'if (odataType){';
context.src += item + '_inheritance = new odataType(undefined, { setDefaultValues: false });'; //di);';
context.src += '}';
context.src += '}else{';
}
if (isEntityType) {
context.src += item + ' = new (Container.resolveByIndex(' + typeIndex + '))(undefined, { setDefaultValues: false });';
} else {
context.src += item + ' = new (Container.resolveByIndex(' + typeIndex + '))();';
}
if (resolvedType.inheritedTo) {
context.src += '}';
}
context.src += 'if (itemKey){';
context.src += 'cache[itemKey] = ' + item + ' || ' + item + '_inheritance;';
context.src += '}';
context.src += '}';
} else {
var isEnum = resolvedType.isAssignableTo && resolvedType.isAssignableTo(_index2.default.Enum);
context.src += 'var ' + item + ';';
context.src += 'var ' + item + '_inheritance;';
if (resolvedType.inheritedTo) {
context.src += 'if (di["' + context.current + '"] && di["' + context.current + '"]["@odata.type"]){';
context.src += 'var odataType = Container.resolveType(di["' + context.current + '"]["@odata.type"].split("#")[1]);';
context.src += 'if (odataType){';
context.src += item + '_inheritance = new odataType(undefined, { setDefaultValues: false });'; /*di["' + context.current + '"])';*/
context.src += '}';
context.src += '}else{';
}
if (isEntityType) {
context.src += item + ' = new (Container.resolveByIndex(' + typeIndex + '))(undefined, { setDefaultValues: false });';
} else if (isEnum) {
context.src += item + ' = Container.resolveByIndex(' + typeIndex + ')[di["' + context.current + '"]];';
} else {
context.src += item + ' = new (Container.resolveByIndex(' + typeIndex + '))();';
}
if (resolvedType.inheritedTo) {
context.src += '}';
}
}
}
var openTypeProperty = null;
if (this.providerName == "oData" && resolvedType && resolvedType.openType) {
openTypeProperty = resolvedType.openType === true ? _index2.default.defaults.openTypeDefaultPropertyName : resolvedType.openType;
context.src += item + '.' + openTypeProperty + ' = {};';
context.src += 'for (var prop in di){ if ([' + resolvedType.memberDefinitions.getPublicMappedPropertyNames().map(function (prop) {
return '"' + prop + '"';
}).join(',') + '].indexOf(prop) < 0 && prop.indexOf("@") < 0 && prop.indexOf("#") < 0){ ' + item + '.' + openTypeProperty + '[prop] = di[prop]; } };';
}
context.src += 'var ' + context.item + '_type;';
context.src += 'var ' + context.item + '_memberDefinitionNames;';
context.src += 'if (' + context.item + '_inheritance){';
context.src += context.item + ' = ' + context.item + '_inheritance;';
context.src += 'if (typeof ' + context.item + '.getType == "function"){';
context.src += context.item + '_type = ' + context.item + '.getType();';
context.src += context.item + '_memberDefinitionNames = ' + context.item + '_type' + '.memberDefinitions.getPublicMappedProperties()' + '.filter(function(it){ return it.definedBy == ' + context.item + '_type || it.definedBy == ' + context.item + '_type.inheritsFrom; })' + '.map(function(it){ return it.name; });';
context.src += '}';
context.src += '}';
for (var i in meta) {
if (i.indexOf('$') < 0 && i != openTypeProperty) {
context.src += 'if (!' + context.item + '_memberDefinitionNames || (' + context.item + '_memberDefinitionNames && ' + context.item + '_memberDefinitionNames.indexOf("' + i + '") >= 0)){';
context.current = i;
if (!meta[i].$item) {
if (meta[i].$value) {
context.meta.push(i);
var item = context.item;
this.build(meta[i], context);
context.src += item + '.' + i + ' = ' + context.item + ';';
context.item = item;
context.meta.pop();
} else if (meta[i].$source) {
context.src += 'var fn = function(di){';
this._buildSelector(meta[i], context);
if (meta[i].$type) {
var type = _index.Container.resolveName(_index.Container.resolveType(meta[i].$type));
var typeIndex = _index.Container.getIndex(_index.Container.resolveType(meta[i].$type));
var converter = this.context.storageProvider.fieldConverter.fromDb[type];
if (converter) {
context.src += 'return self.context.storageProvider.fieldConverter.fromDb["' + type + '"](di["' + meta[i].$source + '"]);';
} else {
context.src += 'return new (Container.resolveByIndex(' + typeIndex + '))(di["' + meta[i].$source + '"]);';
}
} else {
context.src += item + '.' + i + ' = di["' + meta[i].$source + '"];';
}
context.src += '};';
if (meta[i].$type) context.src += item + '.' + i + ' = fn(di);';else context.src += 'fn(di);';
} else if (meta[i].$type) {
context.meta.push(i);
context.src += 'var fn = function(di){';
this._buildSelector(meta[i], context);
this.build(meta[i], context);
context.src += 'return ' + context.item + ';};';
if (meta[i].$type === _index2.default.Object) context.src += item + '.' + i + ' = self._deepExtend(' + item + '.' + i + ', fn(di));';else context.src += item + '.' + i + ' = fn(di);';
context.item = item;
context.meta.pop();
} else if (meta.$type) {
var memDef = _index.Container.resolveType(meta.$type).memberDefinitions.getMember(i);
var type = _index.Container.resolveName(memDef.type);
var entityType = _index.Container.resolveType(meta.$type);
var entityTypeIndex = _index.Container.getIndex(meta.$type);
var converter = this.context.storageProvider.fieldConverter.fromDb[type];
if (entityType.inheritedTo) {
context.src += 'if (di["' + meta[i] + '"] && di["' + meta[i] + '"]["@odata.type"]){';
context.src += 'var odataType = Container.resolveType(di["' + meta[i] + '"]["@odata.type"].split("#")[1]);';
context.src += 'if (odataType){';
context.src += item + '.' + i + ' = new odataType(undefined, { setDefaultValues: false });'; //di["' + meta[i] + '"])';
context.src += '}';
context.src += '}else{';
}
if (this.providerName && memDef && memDef.converter && memDef.converter[this.providerName] && typeof memDef.converter[this.providerName].fromDb == 'function') {
context.src += item + '.' + i + ' = Container.resolveByIndex("' + entityTypeIndex + '").memberDefinitions.getMember("' + i + '").converter.' + this.providerName + '.fromDb(di["' + meta[i] + '"], Container.resolveByIndex("' + entityTypeIndex + '").memberDefinitions.getMember("' + i + '"), self.context, Container.resolveByIndex("' + entityTypeIndex + '"));';
} else if (converter) {
context.src += item + '.' + i + ' = self.context.storageProvider.fieldConverter.fromDb["' + type + '"](di["' + meta[i] + '"]);';
} else {
var typeIndex = _index.Container.getIndex(_index.Container.resolveType(type.memberDefinitions.getMember(i).type));
context.src += item + '.' + i + ' = new (Container.resolveByIndex(' + typeIndex + '))(di["' + meta[i] + '"]);';
}
if (entityType.inheritedTo) {
context.src += '}';
}
}
} else {
context.meta.push(i);
this.build(meta[i], context);
context.item = item;
context.meta.pop();
}
context.src += '}';
}
}
context.src += item + ' = self._finalize(' + /*item + '_inheritance' + ' || ' +*/item + ');';
}
},
call: function call(data, meta) {
if (!Object.getOwnPropertyNames(meta).length) {
return data;
}
var context = {
src: '',
meta: []
};
context.src += 'var self = this;';
context.src += 'var result;';
context.src += 'var cache = {};';
context.src += 'var keycache = [];';
context.src += 'var keycacheIter = [];';
this.build(meta, context);
if (context.item) context.src += 'if (typeof result === "undefined") result = ' + context.item + ';';
context.src += 'return result;';
var fn = new Function('meta', 'data', 'Container', context.src).bind(this);
var ret = fn(meta, data, _index.Container);
return ret;
}
});
exports.default = _index2.default;
module.exports = exports['default'];