jaydata
Version:
Cross-platform HTML5 data-management, JavaScript Language Query (JSLQ) support for OData, SQLite, WebSQL, IndexedDB, YQL and Facebook (packaged for Node.JS)
323 lines (283 loc) • 17.4 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 }; }
(0, _index.$C)('$data.Expressions.CodeToEntityConverter', _index2.default.Expressions.ExpressionVisitor, null, {
constructor: function constructor(scopeContext) {
///<summary>This visitor converts a JS language tree into a semantical Entity Expression Tree This visitor should be invoked on a CodeExpression</summary>
///<param name="context">context.thisArg contains parameters, context.lambdaParams should have an array value</param>
this.scopeContext = scopeContext;
this.parameters = [];
},
VisitBinary: function VisitBinary(expression, context) {
var left = this.Visit(expression.left, context);
var right = this.Visit(expression.right, context);
if (!(left instanceof _index2.default.Expressions.ConstantExpression) && right instanceof _index2.default.Expressions.ConstantExpression || !(right instanceof _index2.default.Expressions.ConstantExpression) && left instanceof _index2.default.Expressions.ConstantExpression) {
var refExpression, constExpr;
if (right instanceof _index2.default.Expressions.ConstantExpression) {
refExpression = left;
constExpr = right;
} else {
refExpression = right;
constExpr = left;
}
var memInfo;
if ((memInfo = refExpression.selector) instanceof _index2.default.Expressions.MemberInfoExpression || (memInfo = refExpression.operation) instanceof _index2.default.Expressions.MemberInfoExpression) {
if (memInfo.memberDefinition && (memInfo.memberDefinition.type || memInfo.memberDefinition.dataType)) {
var fieldType = _index.Container.resolveType(memInfo.memberDefinition.type || memInfo.memberDefinition.dataType);
var constExprType = _index.Container.resolveType(constExpr.type);
if (fieldType !== constExprType) {
var value = constExpr.value;
if (expression.operator === _index2.default.Expressions.ExpressionType.In) {
if (Array.isArray(value)) {
var resultExp = [];
for (var i = 0; i < value.length; i++) {
resultExp.push(new _index2.default.Expressions.ConstantExpression(value[i], fieldType));
}
value = resultExp;
fieldType = _index2.default.Array;
} else {
fieldType = constExprType;
}
}
if (right === constExpr) {
right = new _index2.default.Expressions.ConstantExpression(value, fieldType, right.name);
} else {
left = new _index2.default.Expressions.ConstantExpression(value, fieldType, left.name);
}
}
}
}
}
var operatorResolution = this.scopeContext.resolveBinaryOperator(expression.nodeType, expression, context.frameType);
var result = _index.Container.createSimpleBinaryExpression(left, right, expression.nodeType, expression.operator, expression.type, operatorResolution);
return result;
},
VisitUnary: function VisitUnary(expression, context) {
var operand = this.Visit(expression.operand, context);
var operatorResolution = this.scopeContext.resolveUnaryOperator(expression.nodeType, expression, context.frameType);
var result = _index.Container.createUnaryExpression(operand, expression.operator, expression.nodeType, operatorResolution);
return result;
},
VisitParameter: function VisitParameter(expression, context) {
_index.Guard.requireValue("context", context);
var et = _index2.default.Expressions.ExpressionType;
switch (expression.nodeType) {
case et.LambdaParameterReference:
var result = _index.Container.createEntityExpression(context.lambdaParameters[expression.paramIndex], { lambda: expression.name });
return result;
case et.LambdaParameter:
//TODO: throw descriptive exception or return a value
break;
default:
_index.Guard.raise("Parameter '" + expression.name + "' is missing!");
break;
}
},
VisitThis: function VisitThis(expression, context) {
///<summary>converts the ThisExpression into a QueryParameterExpression tha't value will be evaluated and stored in this.parameters collection</summary>
var index = this.parameters.push({ name: "", value: undefined }) - 1;
var result = _index.Container.createQueryParameterExpression("", index, context.queryParameters, undefined);
return result;
},
VisitFunction: function VisitFunction(expression, context) {
var result = _index2.default.Expressions.ExpressionVisitor.prototype.VisitFunction.apply(this, arguments);
return result.body;
},
VisitCall: function VisitCall(expression, context) {
//var exp = this.Visit(expression.expression);
var self = this;
var exp = this.Visit(expression.expression, context);
var member = this.Visit(expression.member, context);
var args = expression.args.map(function (arg) {
if (arg instanceof _index2.default.Expressions.FunctionExpression && (exp instanceof _index2.default.Expressions.EntitySetExpression || exp instanceof _index2.default.Expressions.FrameOperationExpression)) {
var operation = self.scopeContext.resolveSetOperations(member.value, exp, context.frameType);
if (!operation) {
_index.Guard.raise("Unknown entity field operation: " + member.getJSON());
}
var entitySet = self.scopeContext.getEntitySetFromElementType(exp.elementType);
var setExpr = null;
if (!entitySet) {
//TODO
_index.Guard.raise("Nested operations without entity set is not supported");
} else {
setExpr = entitySet.expression;
}
var frameType = context.frameType;
context.frameType = operation.frameType;
context.lambdaParameters.push(setExpr);
var res = self.Visit(arg, context);
context.lambdaParameters.pop();
context.frameType = frameType;
if (operation.frameTypeFactory) {
return operation.frameTypeFactory(setExpr, res);
} else {
return new operation.frameType(setExpr, res);
}
} else {
return self.Visit(arg, context);
}
});
var result;
///filter=>function(p) { return p.Title == this.xyz.BogusFunction('asd','basd');}
switch (true) {
case exp instanceof _index2.default.Expressions.QueryParameterExpression:
var argValues = args.map(function (a) {
return a.value;
});
result = expression.implementation(exp.value, member.value, argValues);
//var args = expressions
return _index.Container.createQueryParameterExpression(exp.name + "$" + member.value, exp.index, result, typeof result === 'undefined' ? 'undefined' : _typeof(result));
case exp instanceof _index2.default.Expressions.EntityFieldExpression:
case exp instanceof _index2.default.Expressions.EntityFieldOperationExpression:
var operation = this.scopeContext.resolveFieldOperation(member.value, exp, context.frameType);
if (!operation) {
_index.Guard.raise("Unknown entity field operation: " + member.getJSON());
}
member = _index.Container.createMemberInfoExpression(operation);
result = _index.Container.createEntityFieldOperationExpression(exp, member, this._resolveFunctionArguments(args, operation.parameters));
return result;
case exp instanceof _index2.default.Expressions.EntitySetExpression:
case exp instanceof _index2.default.Expressions.FrameOperationExpression:
var operation = this.scopeContext.resolveSetOperations(member.value, exp, context.frameType);
if (!operation) {
_index.Guard.raise("Unknown entity field operation: " + member.getJSON());
}
member = _index.Container.createMemberInfoExpression(operation);
result = _index.Container.createFrameOperationExpression(exp, member, this._resolveFunctionArguments(args, operation.parameters));
return result;
case exp instanceof _index2.default.Expressions.EntityExpression:
var operation = this.scopeContext.resolveTypeOperations(member.value, exp, context.frameType);
if (!operation) {
_index.Guard.raise("Unknown entity function operation: " + member.getJSON());
}
member = _index.Container.createMemberInfoExpression(operation);
result = _index.Container.createEntityFunctionOperationExpression(exp, member, this._resolveFunctionArguments(args, operation.method.params));
return result;
break;
case exp instanceof _index2.default.Expressions.EntityContextExpression:
var operation = this.scopeContext.resolveContextOperations(member.value, exp, context.frameType);
if (!operation) {
_index.Guard.raise("Unknown entity function operation: " + member.getJSON());
}
member = _index.Container.createMemberInfoExpression(operation);
result = _index.Container.createContextFunctionOperationExpression(exp, member, this._resolveFunctionArguments(args, operation.method.params));
return result;
break;
default:
_index.Guard.raise("VisitCall: Only fields can have operations: " + expression.getType().name);
//TODO we must not alter the visited tree
}
},
_resolveFunctionArguments: function _resolveFunctionArguments(args, params) {
if (params) // remove current field poz
params = params.filter(function (p, i) {
return p.name !== '@expression';
});
//objectArgs
if (args.length === 1 && args[0] instanceof _index2.default.Expressions.ConstantExpression && _typeof(args[0].value) === 'object' && args[0].value && params && params[0] && args[0].value.constructor === _index2.default.Object && params.some(function (param) {
return param.name in args[0].value;
})) {
return params.map(function (p) {
var type = p.type || p.dataType || args[0].type;
return new _index2.default.Expressions.ConstantExpression(args[0].value[p.name], _index.Container.resolveType(type), p.name);
});
} else {
return args.map(function (expr, i) {
if (expr instanceof _index2.default.Expressions.ConstantExpression && params && params[i]) {
var type = params[i].type || params[i].dataType || expr.type;
return new _index2.default.Expressions.ConstantExpression(expr.value, _index.Container.resolveType(type), params[i].name);
} else {
return expr;
}
});
}
},
VisitProperty: function VisitProperty(expression, context) {
///<param name="expression" type="$data.Expressions.PropertyExpression" />
var exp = this.Visit(expression.expression, context);
var member = this.Visit(expression.member, context);
//Guard.requireType("member", member, $data.Expressions.ConstantExpression);
_index.Guard.requireType("member", member, _index2.default.Expressions.ConstantExpression);
function isPrimitiveType(memberDefinitionArg) {
var t = memberDefinitionArg.dataType;
if (typeof t === 'function') {
return false;
}
// suspicious code
/*switch (t) {
//TODO: implement this
}*/
}
switch (exp.expressionType) {
case _index2.default.Expressions.EntitySetExpression:
case _index2.default.Expressions.EntityExpression:
var memberDefinition = exp.getMemberDefinition(member.value);
if (!memberDefinition) {
_index.Guard.raise(new _index.Exception("Unknown member: " + member.value, "MemberNotFound"));
}
//var storageMemberDefinition =
var storageField = memberDefinition.storageModel.PhysicalType.memberDefinitions.getMember(memberDefinition.name);
var res;
var memberDefinitionExp;
switch (storageField.kind) {
case "property":
memberDefinitionExp = _index.Container.createMemberInfoExpression(memberDefinition);
res = _index.Container.createEntityFieldExpression(exp, memberDefinitionExp);
return res;
case "navProperty":
var assocInfo = memberDefinition.storageModel.Associations[memberDefinition.name];
var setExpression = _index.Container.createEntitySetExpression(exp, _index.Container.createAssociationInfoExpression(assocInfo));
if (assocInfo.ToMultiplicity !== "*") {
var ee = _index.Container.createEntityExpression(setExpression, {});
return ee;
} /* else {
context.lambdaParameters.push(setExpression);
}*/
return setExpression;
case "complexProperty":
memberDefinitionExp = _index.Container.createMemberInfoExpression(memberDefinition);
res = _index.Container.createComplexTypeExpression(exp, memberDefinitionExp);
return res;
//TODO: missing default case
}
//s/switch => property or navigationproperty
case _index2.default.Expressions.ComplexTypeExpression:
var memDef = exp.getMemberDefinition(member.value);
if (!memDef) {
_index.Guard.raise("Unknown member " + member.value + " on " + exp.entityType.name);
}
var memDefExp = _index.Container.createMemberInfoExpression(memDef);
var result;
//TODO!!!!
if (_index.Container.isPrimitiveType(_index.Container.resolveType(memDef.dataType))) {
result = _index.Container.createEntityFieldExpression(exp, memDefExp);
return result;
}
result = _index.Container.createComplexTypeExpression(exp, memDefExp);
return result;
case _index2.default.Expressions.QueryParameterExpression:
var value = expression.implementation(exp.value, member.value);
this.parameters[exp.index].name += "$" + member.value;
this.parameters[exp.index].value = value;
return _index.Container.createQueryParameterExpression(exp.name + "$" + member.value, exp.index, value, _index.Container.getTypeName(value));
case _index2.default.Expressions.EntityFieldExpression:
case _index2.default.Expressions.EntityFieldOperationExpression:
var operation = this.scopeContext.resolveFieldOperation(member.value, exp, context.frameType);
if (!operation) {
_index.Guard.raise("Unknown entity field operation: " + member.getJSON());
}
member = _index.Container.createMemberInfoExpression(operation);
result = _index.Container.createEntityFieldOperationExpression(exp, member, []);
return result;
default:
_index.Guard.raise("Unknown expression type to handle: " + exp.expressionType.name);
}
}
});
exports.default = _index2.default;
module.exports = exports['default'];