UNPKG

jaydata

Version:

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

518 lines (482 loc) 26.3 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _index = require('../../TypeSystem/index.js'); var _index2 = _interopRequireDefault(_index); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } (0, _index.$C)('$data.modelBinder.FindProjectionVisitor', _index2.default.Expressions.EntityExpressionVisitor, null, { constructor: function constructor(includes) { this._includes = includes; }, VisitProjectionExpression: function VisitProjectionExpression(expression, context) { this.projectionExpression = this.projectionExpression || expression; context && (context.projectionExpression = context.projectionExpression || expression); this.Visit(expression.source, context); }, VisitIncludeExpression: function VisitIncludeExpression(expression, context) { this.Visit(expression.source, context); if (!(expression.selector instanceof _index2.default.Expressions.ConstantExpression)) { var selectorContext = {}; this.Visit(expression.selector.expression, selectorContext); if (selectorContext.hasIncludeProjectionExpression) { var include = this._includes.filter(function (it) { return it.name === selectorContext.includePath; })[0]; if (include) { include.projectionExpression = selectorContext.includeProjectionExpression; } context && (context.hasIncludeProjectionExpression = true); } } }, VisitFrameOperationExpression: function VisitFrameOperationExpression(expression, context) { this.Visit(expression.source, context); var opDef = expression.operation.memberDefinition; if (opDef && opDef.frameType === _index2.default.Expressions.ProjectionExpression) { var paramCounter = 0; var params = opDef.parameters || [{ name: "@expression" }]; var args = params.map(function (item, index) { if (item.name === "@expression") { return expression.source; } else { return expression.parameters[paramCounter++]; }; }); for (var i = 0; i < args.length; i++) { var arg = args[i]; if (arg instanceof _index2.default.Expressions.ConstantExpression && arg.value instanceof _index2.default.Queryable) { var preparator = _index.Container.createQueryExpressionCreator(arg.value.entityContext); arg = preparator.Visit(arg.value.expression); } var visitor = new _index2.default.modelBinder.FindProjectionVisitor(this._inculdes); var visitorContext = {}; var compiled = visitor.Visit(arg, visitorContext); if (context && visitorContext.projectionExpression) { context.hasIncludeProjectionExpression = true; context.includeProjectionExpression = visitorContext.projectionExpression; } } } }, VisitAssociationInfoExpression: function VisitAssociationInfoExpression(expression, context) { var propName = expression.associationInfo.FromPropertyName; if (context) { context.includePath = context.includePath ? context.includePath + '.' : ""; context.includePath += propName; } } }); (0, _index.$C)('$data.modelBinder.ModelBinderConfigCompiler', _index2.default.Expressions.EntityExpressionVisitor, null, { constructor: function constructor(query, includes, oDataProvider) { this._query = query; this._includes = includes; this._isoDataProvider = oDataProvider || false; this.depth = []; }, VisitSingleExpression: function VisitSingleExpression(expression) { this._defaultModelBinder(expression); }, VisitSomeExpression: function VisitSomeExpression(expression) { this._defaultModelBinder(expression); }, VisitFindExpression: function VisitFindExpression(expression) { this._defaultModelBinder(expression); }, VisitEveryExpression: function VisitEveryExpression(expression) { this._defaultModelBinder(expression); }, VisitToArrayExpression: function VisitToArrayExpression(expression) { this._defaultModelBinder(expression); }, VisitFirstExpression: function VisitFirstExpression(expression) { this._defaultModelBinder(expression); }, VisitForEachExpression: function VisitForEachExpression(expression) { this._defaultModelBinder(expression); }, VisitServiceOperationExpression: function VisitServiceOperationExpression(expression) { if (expression.cfg.returnType) { var returnType = _index.Container.resolveType(expression.cfg.returnType); if (typeof returnType.isAssignableTo === 'function' && returnType.isAssignableTo(_index2.default.Queryable) || returnType === _index2.default.Array) { this._defaultModelBinder(expression); } else { var builder = _index.Container.createqueryBuilder(); builder.modelBinderConfig['$type'] = returnType; if (typeof returnType.isAssignableTo === 'function' && returnType.isAssignableTo(_index2.default.Entity)) { builder.modelBinderConfig['$selector'] = ['json:' + expression.cfg.serviceName]; } else { builder.modelBinderConfig['$type'] = returnType; builder.modelBinderConfig['$value'] = function (a, v) { return expression.cfg.serviceName in v ? v[expression.cfg.serviceName] : v.value; }; } this.VisitExpression(expression, builder); builder.resetModelBinderProperty(); this._query.modelBinderConfig = builder.modelBinderConfig; } } }, VisitCountExpression: function VisitCountExpression(expression) { var builder = _index.Container.createqueryBuilder(); builder.modelBinderConfig['$type'] = _index2.default.Array; builder.selectModelBinderProperty('$item'); builder.modelBinderConfig['$type'] = _index2.default.Integer; builder.modelBinderConfig['$source'] = 'cnt'; builder.resetModelBinderProperty(); this._query.modelBinderConfig = builder.modelBinderConfig; }, VisitBatchDeleteExpression: function VisitBatchDeleteExpression(expression) { var builder = _index.Container.createqueryBuilder(); builder.modelBinderConfig['$type'] = _index2.default.Array; builder.selectModelBinderProperty('$item'); builder.modelBinderConfig['$type'] = _index2.default.Integer; builder.modelBinderConfig['$source'] = 'cnt'; builder.resetModelBinderProperty(); this._query.modelBinderConfig = builder.modelBinderConfig; }, VisitConstantExpression: function VisitConstantExpression(expression, builder) { builder.modelBinderConfig['$type'] = expression.type; builder.modelBinderConfig['$value'] = expression.value; }, VisitExpression: function VisitExpression(expression, builder) { var projVisitor = _index.Container.createFindProjectionVisitor(this._includes); var projContext = {}; projVisitor.Visit(expression, projContext); if (projContext.projectionExpression) { this.Visit(projContext.projectionExpression, builder); } else { this.DefaultSelection(builder, this._query.defaultType, this._includes, projContext.hasIncludeProjectionExpression); } }, _defaultModelBinder: function _defaultModelBinder(expression) { var builder = _index.Container.createqueryBuilder(); builder.modelBinderConfig['$type'] = _index2.default.Array; if (this._isoDataProvider) { builder.modelBinderConfig['$selector'] = ['json:d.results', 'json:d', 'json:results', 'json:value']; } builder.modelBinderConfig['$item'] = {}; builder.selectModelBinderProperty('$item'); this.VisitExpression(expression, builder); builder.resetModelBinderProperty(); this._query.modelBinderConfig = builder.modelBinderConfig; }, _inheritanceMemberDefinitions: function _inheritanceMemberDefinitions(type, memdefs) { var self = this; if (type.inheritedTo) { type.inheritedTo.forEach(function (it) { memdefs = self._inheritanceMemberDefinitions(it, memdefs.concat(it.memberDefinitions.getPublicMappedProperties())); }); } return memdefs; }, _addPropertyToModelBinderConfig: function _addPropertyToModelBinderConfig(elementType, builder) { var storageModel = this._query.context._storageModel.getStorageModel(elementType); if (elementType.memberDefinitions) { var memberDefinitions = this._inheritanceMemberDefinitions(elementType, elementType.memberDefinitions.getPublicMappedProperties()); memberDefinitions.forEach(function (prop) { if (!storageModel || storageModel && !storageModel.Associations[prop.name] && !storageModel.ComplexTypes[prop.name]) { var type = _index.Container.resolveType(prop.dataType); if (!storageModel && this._query.context.storageProvider.supportedDataTypes.indexOf(type) < 0) { //complex type builder.selectModelBinderProperty(prop.name); builder.modelBinderConfig['$type'] = type; if (this._isoDataProvider) { builder.modelBinderConfig['$selector'] = ['json:' + prop.name + '.results', 'json:' + prop.name]; } else { builder.modelBinderConfig['$selector'] = 'json:' + prop.name; } this._addPropertyToModelBinderConfig(type, builder); builder.popModelBinderProperty(); } else { if (prop.key) { builder.addKeyField(prop.name); } if (prop.concurrencyMode === _index2.default.ConcurrencyMode.Fixed) { builder.modelBinderConfig[prop.name] = { $source: '@odata.etag' }; } else if (type === _index2.default.Array && prop.elementType) { builder.selectModelBinderProperty(prop.name); builder.modelBinderConfig['$type'] = type; if (this._isoDataProvider) { builder.modelBinderConfig['$selector'] = ['json:' + prop.name + '.results', 'json:' + prop.name]; } else { builder.modelBinderConfig['$selector'] = 'json:' + prop.name; } builder.selectModelBinderProperty('$item'); var arrayElementType = _index.Container.resolveType(prop.elementType); builder.modelBinderConfig['$type'] = arrayElementType; this._addPropertyToModelBinderConfig(arrayElementType, builder); builder.popModelBinderProperty(); builder.popModelBinderProperty(); } else { builder.modelBinderConfig[prop.name] = { $source: prop.name, $type: prop.type }; } } } }, this); } else { /*builder._binderConfig = { $selector: ['json:results'], $type: $data.Array, $item:{ $type: elementType, $value: function (meta, data) { return data; } } }*/ if (builder._binderConfig.$type === _index2.default.Array) { builder._binderConfig.$item = builder._binderConfig.$item || {}; builder.modelBinderConfig = builder._binderConfig.$item; } } if (storageModel) { this._addComplexTypeProperties(storageModel.ComplexTypes, builder); } }, _addComplexTypeProperties: function _addComplexTypeProperties(complexTypes, builder) { complexTypes.forEach(function (ct) { if (ct.ToType !== _index2.default.Array) { builder.selectModelBinderProperty(ct.FromPropertyName); builder.modelBinderConfig['$type'] = ct.ToType; if (this._isoDataProvider) { builder.modelBinderConfig['$selector'] = ['json:' + ct.FromPropertyName + '.results', 'json:' + ct.FromPropertyName]; } else { builder.modelBinderConfig['$selector'] = 'json:' + ct.FromPropertyName; } this._addPropertyToModelBinderConfig(ct.ToType, builder); builder.popModelBinderProperty(); } else { var dt = ct.ToType; var et = _index.Container.resolveType(ct.FromType.memberDefinitions.getMember(ct.FromPropertyName).elementType); if (dt === _index2.default.Array && et && et.isAssignableTo && et.isAssignableTo(_index2.default.Entity)) { config = { $type: _index2.default.Array, $selector: 'json:' + ct.FromPropertyName, $item: { $type: et } }; var md = et.memberDefinitions.getPublicMappedProperties(); for (var i = 0; i < md.length; i++) { config.$item[md[i].name] = { $type: md[i].type, $source: md[i].name }; } builder.modelBinderConfig[ct.FromPropertyName] = config; } else { builder.modelBinderConfig[ct.FromPropertyName] = { $type: ct.ToType, $source: ct.FromPropertyName }; } } }, this); }, DefaultSelection: function DefaultSelection(builder, type, allIncludes, custom) { var _this = this; //no projection, get all item from entitySet builder.modelBinderConfig['$type'] = custom ? _index2.default.Object : type; var storageModel = this._query.context._storageModel.getStorageModel(type); this._addPropertyToModelBinderConfig(type, builder); if (allIncludes) { (function () { var excludeDeepInclude = []; allIncludes.forEach(function (include) { if (excludeDeepInclude.some(function (incName) { return include.name.length > incName.length && include.name.substr(0, incName.length) === incName; })) { return; } this.depth.push(include.name); var includes = include.name.split('/').pop().split('.'); var association = null; var tmpStorageModel = storageModel; var itemCount = 0; for (var i = 0; i < includes.length; i++) { if (builder.modelBinderConfig.$item) { builder.selectModelBinderProperty('$item'); itemCount++; } builder.selectModelBinderProperty(includes[i]); association = tmpStorageModel.Associations[includes[i]]; tmpStorageModel = this._query.context._storageModel.getStorageModel(association.ToType); } if (this._isoDataProvider) { builder.modelBinderConfig['$selector'] = ['json:' + includes[includes.length - 1] + '.results', 'json:' + includes[includes.length - 1]]; } else { builder.modelBinderConfig['$selector'] = 'json:' + includes[includes.length - 1]; } if (association.ToMultiplicity === '*') { builder.modelBinderConfig['$type'] = _index2.default.Array; builder.selectModelBinderProperty('$item'); builder.modelBinderConfig['$type'] = include.type; if (include.projectionExpression) { excludeDeepInclude.push(include.name); this.Visit(include.projectionExpression, builder); } else { this._addPropertyToModelBinderConfig(include.type, builder); } builder.popModelBinderProperty(); } else { builder.modelBinderConfig['$type'] = include.type; if (include.projectionExpression) { excludeDeepInclude.push(include.name); this.Visit(include.projectionExpression, builder); } else { this._addPropertyToModelBinderConfig(include.type, builder); } } for (var i = 0; i < includes.length + itemCount; i++) { builder.popModelBinderProperty(); } this.depth.pop(); }, _this); })(); } }, VisitProjectionExpression: function VisitProjectionExpression(expression, builder) { this.hasProjection = true; this.Visit(expression.selector, builder); if (expression.selector && expression.selector.expression instanceof _index2.default.Expressions.ObjectLiteralExpression) { builder.modelBinderConfig['$type'] = expression.projectionAs || builder.modelBinderConfig['$type'] || _index2.default.Object; } }, VisitParametricQueryExpression: function VisitParametricQueryExpression(expression, builder) { if (expression.expression instanceof _index2.default.Expressions.EntityExpression || expression.expression instanceof _index2.default.Expressions.EntitySetExpression) { this.VisitEntityAsProjection(expression, builder); } else { this.Visit(expression.expression, builder); } }, VisitEntityAsProjection: function VisitEntityAsProjection(expression, builder) { this.mapping = ''; this.Visit(expression.expression, builder); this.depth.push(this.mapping); this.mapping = this.depth.join('.'); var includes; var currentInclude; if (this.mapping && this._includes instanceof Array) { includes = this._includes.filter(function (inc) { return inc.name.indexOf(this.mapping + '.') === 0; }, this); includes = includes.map(function (inc) { return { name: inc.name.replace(this.mapping + '.', ''), type: inc.type }; }, this); // if (includes.length > 0){ // this.DefaultSelection(builder, expression.expression.entityType, includes); // //console.warn('WARN: include for mapped properties is not supported!'); // } currentInclude = this._includes.filter(function (inc) { return inc.name === this.mapping; }, this)[0]; } if (expression.expression instanceof _index2.default.Expressions.EntityExpression) { if (currentInclude && currentInclude.projectionExpression) { var tmpIncludes = this._includes; this._includes = includes; var tmpDepth = this.depth; this.depth = []; this.Visit(currentInclude.projectionExpression, builder); this._includes = tmpIncludes; this.depth = tmpDepth; } else { this.DefaultSelection(builder, expression.expression.entityType, includes); } } else if (expression.expression instanceof _index2.default.Expressions.EntitySetExpression) { builder.modelBinderConfig.$type = _index2.default.Array; builder.modelBinderConfig.$item = {}; builder.selectModelBinderProperty('$item'); if (currentInclude && currentInclude.projectionExpression) { var _tmpIncludes = this._includes; this._includes = includes; var _tmpDepth = this.depth; this.depth = []; this.Visit(currentInclude.projectionExpression, builder); this._includes = _tmpIncludes; this.depth = _tmpDepth; } else { this.DefaultSelection(builder, expression.expression.elementType, includes); } builder.popModelBinderProperty(); } this.depth.pop(); }, VisitEntityFieldExpression: function VisitEntityFieldExpression(expression, builder) { this.Visit(expression.source, builder); this.Visit(expression.selector, builder); }, VisitMemberInfoExpression: function VisitMemberInfoExpression(expression, builder) { builder.modelBinderConfig['$type'] = expression.memberDefinition.type; if (expression.memberDefinition.storageModel && expression.memberName in expression.memberDefinition.storageModel.ComplexTypes) { this._addPropertyToModelBinderConfig(_index.Container.resolveType(expression.memberDefinition.type), builder); } else { if (!(builder.modelBinderConfig.$type && _index.Container.resolveType(builder.modelBinderConfig.$type).isAssignableTo && _index.Container.resolveType(builder.modelBinderConfig.$type).isAssignableTo(_index2.default.Entity))) builder.modelBinderConfig['$source'] = expression.memberName; } }, VisitEntitySetExpression: function VisitEntitySetExpression(expression, builder) { if (expression.source instanceof _index2.default.Expressions.EntityExpression) { this.Visit(expression.source, builder); this.Visit(expression.selector, builder); } }, VisitComplexTypeExpression: function VisitComplexTypeExpression(expression, builder) { this.Visit(expression.source, builder); this.Visit(expression.selector, builder); if ('$selector' in builder.modelBinderConfig && builder.modelBinderConfig.$selector.length > 0) { if (builder.modelBinderConfig.$selector instanceof _index2.default.Array) { var temp = builder.modelBinderConfig.$selector[1]; builder.modelBinderConfig.$selector[0] = temp + '.' + expression.selector.memberName + '.results'; builder.modelBinderConfig.$selector[1] = temp + '.' + expression.selector.memberName; } else { builder.modelBinderConfig.$selector += '.' + expression.selector.memberName; } } else { if (this._isoDataProvider) { builder.modelBinderConfig['$selector'] = ['json:' + expression.selector.memberName + '.results', 'json:' + expression.selector.memberName]; } else { builder.modelBinderConfig['$selector'] = 'json:' + expression.selector.memberName; } } }, VisitEntityExpression: function VisitEntityExpression(expression, builder) { this.Visit(expression.source, builder); }, VisitAssociationInfoExpression: function VisitAssociationInfoExpression(expression, builder) { if ('$selector' in builder.modelBinderConfig && builder.modelBinderConfig.$selector.length > 0) { if (builder.modelBinderConfig.$selector instanceof _index2.default.Array) { var temp = builder.modelBinderConfig.$selector[1]; builder.modelBinderConfig.$selector[0] = temp + '.' + expression.associationInfo.FromPropertyName + '.results'; builder.modelBinderConfig.$selector[1] = temp + '.' + expression.associationInfo.FromPropertyName; } else { builder.modelBinderConfig.$selector += '.' + expression.associationInfo.FromPropertyName; } } else { if (this._isoDataProvider) { builder.modelBinderConfig['$selector'] = ['json:' + expression.associationInfo.FromPropertyName + '.results', 'json:' + expression.associationInfo.FromPropertyName]; } else { builder.modelBinderConfig['$selector'] = 'json:' + expression.associationInfo.FromPropertyName; } } if (this.mapping && this.mapping.length > 0) { this.mapping += '.'; } this.mapping += expression.associationInfo.FromPropertyName; }, VisitObjectLiteralExpression: function VisitObjectLiteralExpression(expression, builder) { builder.modelBinderConfig['$type'] = _index2.default.Object; expression.members.forEach(function (of) { this.Visit(of, builder); }, this); }, VisitObjectFieldExpression: function VisitObjectFieldExpression(expression, builder) { builder.selectModelBinderProperty(expression.fieldName); if (expression.expression instanceof _index2.default.Expressions.EntityExpression || expression.expression instanceof _index2.default.Expressions.EntitySetExpression) { this.VisitEntityAsProjection(expression, builder); } else { this.Visit(expression.expression, builder); } builder.popModelBinderProperty(); } }); exports.default = _index2.default; module.exports = exports['default'];