@allgemein/expressions
Version:
Library for mango expressions
288 lines (280 loc) • 10.7 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Expressions = void 0;
const base_1 = require("@allgemein/base");
const InDesc_1 = require("../descriptors/InDesc");
const NeqDesc_1 = require("../descriptors/NeqDesc");
const LtDesc_1 = require("../descriptors/LtDesc");
const GtDesc_1 = require("../descriptors/GtDesc");
const AndDesc_1 = require("../descriptors/AndDesc");
const EqDesc_1 = require("../descriptors/EqDesc");
const GeDesc_1 = require("../descriptors/GeDesc");
const KeyDesc_1 = require("../descriptors/KeyDesc");
const LeDesc_1 = require("../descriptors/LeDesc");
const OrDesc_1 = require("../descriptors/OrDesc");
const ValueDesc_1 = require("../descriptors/ValueDesc");
const GroupDesc_1 = require("../descriptors/GroupDesc");
const ExpressionInterpreter_1 = require("./ExpressionInterpreter");
const LikeDesc_1 = require("../descriptors/LikeDesc");
const lodash_1 = require("lodash");
const REGEX_ID = /^(([\w_]+)=((\d+)|(\d+(\.|\,)\d+)|\'([^\']*)\'),?)$/;
const REGEX_ID_G = /^(([\w_]+)=((\d+)|(\d+(\.|\,)\d+)|\'([^\']*)\'),?)$ /g;
const REGEX_ID_K = /^((\d+)|(\d+(\.|\,)\d+),?)+$/;
const REGEX_ID_KG = /^((\d+)|(\d+(\.|\,)\d+),?)+$/g;
const REGEX_ID_W = /^(\'([^\']*)\',?)+$/;
class Expressions {
static parse(str) {
if ((0, lodash_1.isString)(str)) {
// check if JSON string
try {
let obj = JSON.parse(str.trim());
return this.fromJson(obj);
}
catch (e) {
try {
let interpreter = new ExpressionInterpreter_1.ExpressionInterpreter();
return interpreter.interprete(str);
}
catch (e) {
throw e;
}
}
}
else if ((0, lodash_1.isPlainObject)(str)) {
return this.fromJson(str);
}
else {
throw new base_1.NotSupportedError('object cant be interpreted to conditions, wrong format');
}
}
//static validate(entityDef:EntityDef, condition:CondDesc)
/*
static fromJson(object: any): CondDesc {
let cond: CondDesc;
let q: any = [];
Helper.walk(object, (data: WalkValues) => {
console.log(data)
let op: CondDesc = null;
if (/^(\$and|\$or)$/.test(data.key) && isArray(data.value)) {
console.log(data.key);
if (data.key == '$and') {
op = And()
} else if (data.key == '$or') {
op = Or()
}
(<any>data).cond = op;
} else if (data.key.startsWith('$') && !isPlainObject(data.value)) {
if (data.key == '$eq') {
let value = null;
if (isPlainObject(data.value)) {
if (has(data.value, '$key')) {
value = Key(data.value.key);
} else {
// ???
throw new NotSupportedError('object given but without known operator')
}
} else {
value = data.value;
}
}
} else if (!data.key.startsWith('$')) {
if (isPlainObject(data.value)) {
} else {
// eq k = v
op = Eq(Key(data.key), Value(data.value));
}
}
if (!cond) {
cond = op;
}
});
return cond;
}
*/
static exprKeys() {
return Object.keys(this.EXPR_REGISTRY);
}
static fromJson(object, srcKey = null, parent = null) {
if ((0, lodash_1.isArray)(object)) {
if (!parent || !(parent instanceof GroupDesc_1.GroupDesc)) {
parent = (0, OrDesc_1.Or)();
}
for (let obj of object) {
let sub = this.fromJson(obj, null, parent);
if (!(sub instanceof GroupDesc_1.GroupDesc)) {
parent.values.push(sub);
}
}
return parent;
}
else if ((0, lodash_1.isPlainObject)(object)) {
let keys = Object.keys(object);
let operator = keys.filter(k => k.startsWith('$'));
if (keys.length == 1 && operator.length == 1) {
let op = operator.shift();
if (op == '$or' || op == '$and') {
if ((0, lodash_1.isArray)(object[op])) {
let desc = op == '$or' ? (0, OrDesc_1.Or)() : (0, AndDesc_1.And)();
if (parent instanceof GroupDesc_1.GroupDesc) {
parent.values.push(desc);
}
return this.fromJson(object[op], null, desc);
}
else {
throw new base_1.NotSupportedError('or|and must have an array as value ' + JSON.stringify(object, null, 2));
}
}
else if (this.exprKeys().indexOf(op) > -1) {
let key = (0, KeyDesc_1.Key)(srcKey);
let value = null;
if ((0, lodash_1.isArray)(object[op])) {
value = (0, ValueDesc_1.Value)(object[op]);
}
else if ((0, lodash_1.isPlainObject)(object[op])) {
if ((0, lodash_1.has)(object[op], '$key')) {
value = (0, KeyDesc_1.Key)(object[op].$key);
}
else {
// ???
throw new base_1.NotSupportedError('object given but without known operator');
}
}
else {
value = (0, ValueDesc_1.Value)(object[op]);
}
// @ts-ignore
return this.EXPR_REGISTRY[op](key, value);
}
else {
throw new base_1.NotSupportedError('operator ' + op + ' not supported');
}
}
else if (operator.length == 0) {
let desc = [];
for (let k of keys) {
desc.push(this.fromJson(object[k], k, null));
}
if (desc.length == 1) {
return desc.shift();
}
else {
return (0, AndDesc_1.And)(...desc);
}
}
else {
throw new base_1.NotSupportedError('object has wrong keys ' + JSON.stringify(object, null, 2));
}
}
else {
if (srcKey) {
return (0, EqDesc_1.Eq)((0, KeyDesc_1.Key)(srcKey), object);
}
throw new base_1.NotSupportedError('object cant be resolved ' + JSON.stringify(object, null, 2));
}
}
static parseLookupConditions(ref, id) {
let idProps = ref.getPropertyRefs().filter(p => p.isIdentifier());
if (/^\(.*(\)\s*,\s*\()?.*\)$/.test(id)) {
let ids = id.replace(/^\(|\)$/g, '').split(/\)\s*,\s*\(/);
return ids.map((_id) => this.parseLookupConditions(ref, _id));
}
else if (REGEX_ID.test(id)) {
let cond = {};
let e;
let keys = {};
while ((e = REGEX_ID_G.exec(id)) !== null) {
keys[e[2]] = e[4] || e[5] || e[7];
}
for (let idp of idProps) {
if (keys[idp.name]) {
cond[idp.name] = idp.convert(keys[idp.name]);
}
}
return cond;
}
else if (/^\d+(,\d+)+$/.test(id)) {
let ids = id.split(',');
return ids.map((_id) => this.parseLookupConditions(ref, (0, lodash_1.isString)(_id) ? parseInt(_id, 0) : _id));
}
else if (REGEX_ID_K.test(id)) {
if (/^\'.*\'$/.test(id)) {
id = id.replace(/^\'|\'$/g, '');
}
const conds = [];
let cond = {};
let e;
let c = 0;
while ((e = REGEX_ID_KG.exec(id)) !== null) {
let p = idProps[c];
let v = e[2] || e[3];
c += 1;
cond[p.name] = p.convert(v);
if (c >= idProps.length) {
conds.push((0, lodash_1.clone)(cond));
cond = {};
c = 0;
}
}
return conds.length === 1 ? conds.shift() : conds;
}
else {
if (idProps.length == 1) {
const prop = (0, lodash_1.first)(idProps);
const ids = id.split(',').map((x) => x.trim());
const conds = [];
for (const _id of ids) {
const cond = {};
cond[prop.name] = prop.convert(_id);
conds.push(cond);
}
return conds.length === 1 ? conds.shift() : conds;
}
else {
}
}
throw new base_1.NotYetImplementedError('for ' + id);
}
static buildLookupConditions(ref, data) {
let idProps = ref.getPropertyRefs().filter(p => p.isIdentifier());
if ((0, lodash_1.isArray)(data)) {
let collect = [];
data.forEach(d => {
collect.push(this._buildLookupconditions(idProps, d));
});
if (idProps.length > 1) {
return `(${collect.join('),(')})`;
}
else {
return `${collect.join(',')}`;
}
}
else {
return this._buildLookupconditions(idProps, data);
}
}
static _buildLookupconditions(idProps, data) {
let idPk = [];
idProps.forEach(id => {
let v = id.get(data);
if ((0, lodash_1.isString)(v)) {
idPk.push('\'' + v + '\'');
}
else {
idPk.push(v);
}
});
return idPk.join(',');
}
}
exports.Expressions = Expressions;
Expressions.EXPR_REGISTRY = {
'$eq': (k, v) => (0, EqDesc_1.Eq)(k, v),
'$ne': (k, v) => (0, NeqDesc_1.Neq)(k, v),
'$le': (k, v) => (0, LeDesc_1.Le)(k, v),
'$lt': (k, v) => (0, LtDesc_1.Lt)(k, v),
'$ge': (k, v) => (0, GeDesc_1.Ge)(k, v),
'$gt': (k, v) => (0, GtDesc_1.Gt)(k, v),
'$like': (k, v) => (0, LikeDesc_1.Like)(k, v),
'$in': (k, v) => (0, InDesc_1.In)(k, v)
};
//# sourceMappingURL=Expressions.js.map