UNPKG

jaydata-reso

Version:

Jaydata fork for RESO Web API

380 lines (352 loc) 18.8 kB
$C('$data.modelBinder.FindProjectionVisitor', $data.Expressions.EntityExpressionVisitor, null, { VisitProjectionExpression: function (expression) { this.projectionExpression = expression; } }); $C('$data.modelBinder.ModelBinderConfigCompiler', $data.Expressions.EntityExpressionVisitor, null, { constructor: function (query, includes, oDataProvider) { this._query = query; this._includes = includes; this._isoDataProvider = oDataProvider || false; }, VisitSingleExpression: function (expression) { this._defaultModelBinder(expression); }, VisitSomeExpression: function (expression) { this._defaultModelBinder(expression); }, VisitFindExpression: function (expression) { this._defaultModelBinder(expression); }, VisitEveryExpression: function (expression) { this._defaultModelBinder(expression); }, VisitToArrayExpression: function (expression) { this._defaultModelBinder(expression); }, VisitFirstExpression: function (expression) { this._defaultModelBinder(expression); }, VisitForEachExpression: function (expression) { this._defaultModelBinder(expression); }, VisitServiceOperationExpression: function (expression) { if (expression.cfg.returnType) { var returnType = Container.resolveType(expression.cfg.returnType); if ((typeof returnType.isAssignableTo === 'function' && returnType.isAssignableTo($data.Queryable)) || returnType === $data.Array) { this._defaultModelBinder(expression); } else { var builder = Container.createqueryBuilder(); builder.modelBinderConfig['$type'] = returnType; if (typeof returnType.isAssignableTo === 'function' && returnType.isAssignableTo($data.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 (expression) { var builder = Container.createqueryBuilder(); builder.modelBinderConfig['$type'] = $data.Array; builder.selectModelBinderProperty('$item'); builder.modelBinderConfig['$type'] = $data.Integer; builder.modelBinderConfig['$source'] = 'cnt'; builder.resetModelBinderProperty(); this._query.modelBinderConfig = builder.modelBinderConfig; }, VisitBatchDeleteExpression: function (expression) { var builder = Container.createqueryBuilder(); builder.modelBinderConfig['$type'] = $data.Array; builder.selectModelBinderProperty('$item'); builder.modelBinderConfig['$type'] = $data.Integer; builder.modelBinderConfig['$source'] = 'cnt'; builder.resetModelBinderProperty(); this._query.modelBinderConfig = builder.modelBinderConfig; }, VisitConstantExpression: function (expression, builder) { builder.modelBinderConfig['$type'] = expression.type; builder.modelBinderConfig['$value'] = expression.value; }, VisitExpression: function (expression, builder) { var projVisitor = Container.createFindProjectionVisitor(); projVisitor.Visit(expression); if (projVisitor.projectionExpression) { this.Visit(projVisitor.projectionExpression, builder); } else { this.DefaultSelection(builder, this._query.defaultType, this._includes); } }, _defaultModelBinder: function (expression) { var builder = Container.createqueryBuilder(); builder.modelBinderConfig['$type'] = $data.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; }, _addPropertyToModelBinderConfig: function (elementType, builder) { var storageModel = this._query.context._storageModel.getStorageModel(elementType); if (elementType.memberDefinitions) { elementType.memberDefinitions.getPublicMappedProperties().forEach(function (prop) { if ((!storageModel) || (storageModel && !storageModel.Associations[prop.name] && !storageModel.ComplexTypes[prop.name])) { var type = 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 === $data.ConcurrencyMode.Fixed) { builder.modelBinderConfig[prop.name] = { $selector: 'json:__metadata', $source: 'etag' } } else if (type === $data.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 = Container.resolveType(prop.elementType); builder.modelBinderConfig['$type'] = arrayElementType; this._addPropertyToModelBinderConfig(arrayElementType, builder); builder.popModelBinderProperty(); builder.popModelBinderProperty(); } else { builder.modelBinderConfig[prop.name] = prop.name; } } } }, this); } else { /*builder._binderConfig = { $selector: ['json:results'], $type: $data.Array, $item:{ $type: elementType, $value: function (meta, data) { return data; } } }*/ if (builder._binderConfig.$type === $data.Array) { builder._binderConfig.$item = builder._binderConfig.$item || {}; builder.modelBinderConfig = builder._binderConfig.$item; } } if (storageModel) { this._addComplexTypeProperties(storageModel.ComplexTypes, builder); } }, _addComplexTypeProperties: function (complexTypes, builder) { complexTypes.forEach(function (ct) { if (ct.ToType !== $data.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 = Container.resolveType(ct.FromType.memberDefinitions.getMember(ct.FromPropertyName).elementType); if (dt === $data.Array && et && et.isAssignableTo && et.isAssignableTo($data.Entity)){ config = { $type: $data.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 (builder, type, allIncludes) { //no projection, get all item from entitySet builder.modelBinderConfig['$type'] = type; var storageModel = this._query.context._storageModel.getStorageModel(type); this._addPropertyToModelBinderConfig(type, builder); if (allIncludes) { allIncludes.forEach(function (include) { var includes = include.name.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'] = $data.Array; builder.selectModelBinderProperty('$item'); builder.modelBinderConfig['$type'] = include.type; this._addPropertyToModelBinderConfig(include.type, builder); builder.popModelBinderProperty(); } else { builder.modelBinderConfig['$type'] = include.type; this._addPropertyToModelBinderConfig(include.type, builder); } for (var i = 0; i < includes.length + itemCount; i++) { builder.popModelBinderProperty(); } }, this); } }, VisitProjectionExpression: function (expression, builder) { this.hasProjection = true; this.Visit(expression.selector, builder); if (expression.selector && expression.selector.expression instanceof $data.Expressions.ObjectLiteralExpression) { builder.modelBinderConfig['$type'] = expression.projectionAs || builder.modelBinderConfig['$type'] || $data.Object; } }, VisitParametricQueryExpression: function (expression, builder) { if (expression.expression instanceof $data.Expressions.EntityExpression || expression.expression instanceof $data.Expressions.EntitySetExpression) { this.VisitEntityAsProjection(expression, builder); } else { this.Visit(expression.expression, builder); } }, VisitEntityAsProjection: function (expression, builder) { this.mapping = ''; this.Visit(expression.expression, builder); var includes; 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!'); } } if (expression.expression instanceof $data.Expressions.EntityExpression) { this.DefaultSelection(builder, expression.expression.entityType/*, includes*/) } else if (expression.expression instanceof $data.Expressions.EntitySetExpression) { builder.modelBinderConfig.$type = $data.Array; builder.modelBinderConfig.$item = {}; builder.selectModelBinderProperty('$item'); this.DefaultSelection(builder, expression.expression.elementType /*, includes*/) builder.popModelBinderProperty(); } }, VisitEntityFieldExpression: function (expression, builder) { this.Visit(expression.source, builder); this.Visit(expression.selector, builder); }, VisitMemberInfoExpression: function (expression, builder) { builder.modelBinderConfig['$type'] = expression.memberDefinition.type; if (expression.memberDefinition.storageModel && expression.memberName in expression.memberDefinition.storageModel.ComplexTypes) { this._addPropertyToModelBinderConfig(Container.resolveType(expression.memberDefinition.type), builder); } else { if (!(builder.modelBinderConfig.$type && Container.resolveType(builder.modelBinderConfig.$type).isAssignableTo && Container.resolveType(builder.modelBinderConfig.$type).isAssignableTo($data.Entity))) builder.modelBinderConfig['$source'] = expression.memberName; } }, VisitEntitySetExpression: function (expression, builder) { if (expression.source instanceof $data.Expressions.EntityExpression) { this.Visit(expression.source, builder); this.Visit(expression.selector, builder); } }, VisitComplexTypeExpression: function (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 $data.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 (expression, builder) { this.Visit(expression.source, builder); }, VisitAssociationInfoExpression: function (expression, builder) { if (('$selector' in builder.modelBinderConfig) && (builder.modelBinderConfig.$selector.length > 0)) { if (builder.modelBinderConfig.$selector instanceof $data.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 (expression, builder) { builder.modelBinderConfig['$type'] = $data.Object; expression.members.forEach(function (of) { this.Visit(of, builder); }, this); }, VisitObjectFieldExpression: function (expression, builder) { builder.selectModelBinderProperty(expression.fieldName); if (expression.expression instanceof $data.Expressions.EntityExpression || expression.expression instanceof $data.Expressions.EntitySetExpression) { this.VisitEntityAsProjection(expression, builder); } else { this.Visit(expression.expression, builder); } builder.popModelBinderProperty(); } });