UNPKG

spahql

Version:

A query language and data model for deep Javascript object structures.

64 lines (63 loc) 27.9 kB
SpahQL_classRegister=function(a,b){for(var c=a.split("."),d="undefined"==typeof window?{}:window,e="undefined"==typeof exports?{}:exports,d="undefined"==typeof SpahQL?d:SpahQL,e="undefined"==typeof SpahQL?e:SpahQL,f=1;f<c.length;f++){var g=c[f],h=g.toLowerCase();f<c.length-1?(d[g]=d[g]||{},d=d[g],e[h]=e[h]||{},e=e[h]):(d[g]=b,e[h]=b)}}; SpahQL_classExtend=function(a,b,c,d,e){var f;"function"==typeof c?(f=d||{},d=e||{},e=c):(f=c||{},d=d||{},e=d.init);var g,c=Object.create(b.prototype);for(g in d)Object.defineProperty(c,g,{value:d[g],enumerable:!1});g=e?e:c.init?function(){this.init&&this.init.apply(this,arguments)}:function(){};g.prototype=c;for(var h in b)g[h]=b[h];for(var i in f)g[i]=f[i];SpahQL_classRegister(a,g);return g};SpahQL_classCreate=function(a,b,c,d){return SpahQL_classExtend(a,Object,b,c,d)}; SpahQL=SpahQL_classExtend("SpahQL",Array,{db:function(a){return this.item("/",a,a)},result:function(a,b,c){return{path:a,value:b,sourceData:a?c:c||b}},item:function(a,b,c){return new this(this.result(a,b,c))},select:function(a,b,c,d){a=this.QueryParser.parseQuery(a);if(a.assertion)throw new this.SpahQLRunTimeError("Cannot call SpahQL.select() with an assertion query.");return new this(this.QueryRunner.select(a,b,c,d))},assert:function(a,b,c,d){return this.QueryRunner.assert(this.QueryParser.parseQuery(a), b,c,d)},verbose:!1,log:function(a){this.verbose&&"undefined"!=typeof console&&console.log.apply(console,arguments);return a},inBrowser:function(){return"undefined"!=typeof window&&"object"==typeof window.location},isHeadless:function(){return!this.inBrowser()},inCommonJS:function(){return"object"==typeof exports}},{init:function(a){Object.defineProperty(this,"dh",{value:SpahQL.DataHelper,enumerable:!1});if(a){var a=1<arguments.length?Array.prototype.slice.call(arguments):a,a=a.value&&"function"!= typeof a.value?[a]:a,b;for(b in a)this.push(a[b])}},item:function(a){return new SpahQL(this[a])},first:function(){return this.item(0)},last:function(){return this.item(this.length-1)},path:function(){return this[0]?this[0].path:null},paths:function(){return this.map(function(){return this.path()})},value:function(){return this[0]?this[0].value:null},values:function(){return this.map(function(){return this.value()})},sourceData:function(){return this[0]?this[0].sourceData:null},each:function(a){for(var b= 0;b<this.length&&!1!=a.apply(this.item(b),[b,this.length]);b++);return this},map:function(a){for(var b=[],c=0;c<this.length;c++)b.push(a.apply(this.item(c),[c,this.length]));return b},select:function(a){var b=[];this.each(function(){SpahQL.select(a,this.sourceData(),this.value(),this.path()).each(function(){b.push(this[0])})});return new SpahQL(b)},assert:function(a){var b=!0;this.each(function(){if(!SpahQL.assert(a,this.sourceData(),this.value(),this.path()))return b=!1});return b},parentPath:function(a){a= a||this.path();a=!a||"/"==a?null:a.substring(0,a.lastIndexOf("/"));return""==a?"/":a},parentPaths:function(){var a=this;return this.map(function(){return a.parentPath(this.path())})},parent:function(a){var a=a||this[0],b=this.parentPath(a.path);return b&&a?SpahQL.select(b,a.sourceData):null},parents:function(){var a=[],b=this;this.each(function(){var c=b.parent(this[0]);c&&c[0]&&a.push(c[0])});return new SpahQL(a)},keyName:function(a){a=a||this.path();return!a||"/"==a?null:a.substring(a.lastIndexOf("/")+ 1)},keyNames:function(){var a=this;return this.map(function(){return a.keyName(this.path())})},type:function(a){return this.dh.objectType(a||this.value())},types:function(){var a=this;return this.map(function(){return a.type(this.value())})},containing:function(a,b){var c,d;c="string"==typeof a?[a]:"function"==typeof a.paths?a.paths():a;d=b?c.length:1;var e=[],f=0;a:for(;f<this.length;f++){var g=this[f];if(g.path){var h=0,i=0;for(;i<c.length;i++)if(0==c[i].indexOf(g.path)&&(""==c[i].charAt(g.path.length)|| "/"==c[i].charAt(g.path.length)))if(h++,h>=d){e.push(g);continue a}}}return new SpahQL(e)},containingAll:function(a){return this.containing(a,!0)},filter:function(a){var b=[];this.each(function(){this.assert(a)&&b.push(this[0])});return new SpahQL(b)},concat:function(a){for(var b=[],c=0;c<this.length;c++)b.push(this[c]);for(c=0;c<a.length;c++)b.push(a[c]);return new SpahQL(b)},detach:function(){var a=this.dh.deepClone(this[0]?this[0].value:null);return SpahQL.db(a)},clone:function(){for(var a=[], b=[],c=[],d=0;d<this.length;d++){var e=this[d].sourceData,f=this[d].path;if(f){var g=b.indexOf(e);0>g?(g=SpahQL.db(this.dh.deepClone(e)),b.push(e),c.push(g)):g=c[g];e=g.select(f);e[0]&&a.push(e[0])}else a.push(this.dh.deepClone(this[d]))}return new SpahQL(a)},set:function(a,b,c){var d=c||this[0];if(!d)return this;"object"==this.dh.objectType(a)?c=a:(c={},c[a]=b);var a=!1,b=this.dh.deepClone(d.value),e;for(e in c){var f=c[e],g=this.dh.coerceKeyForObject(e,d.value);null!=g&&!this.dh.eq(f,d.value[g])&& (d.value[g]=f,a=!0)}a&&this.resultModified(d,b);return this},setAll:function(a,b){for(var c=0;c<this.length;c++)this.set(a,b,this[c]);return this},replace:function(a,b){var c=b||this[0],d=this.keyName(c.path);if(d&&c){var e=c.value;c.value=a;var f=this.parent(c);f?f.set(d,a):this.resultModified(c,e)}return this},replaceAll:function(a){for(var b=0;b<this.length;b++)this.replace(a,this[b]);return this},rename:function(a,b){var c=b||this[0];if(c){var d=c.value,e=this.parent(c);e?(e.set(a,d),e.destroy(c)): this.resultModified(c,d)}return this},renameAll:function(a){for(var b=0;b<this.length;b++)this.rename(a,this[b]);return this},destroy:function(a,b){if(!a||"object"!=typeof a)b=a,a=this[0];if(a&&b){var c,d=this.type(a.value),e=SpahQL.DataHelper.coerceKeyForObject(b,a.value);if("array"==d)c=a.value.slice(0),a.value.splice(e,1);else if("object"==d){c={};for(var f in a.value)c[f]=a.value[f];delete a.value[e]}this.resultModified(a,c)}else a&&(c=this.keyName(a.path),(d=this.parent(a))&&c&&d.destroy(c)); return this},destroyAll:function(a){for(var b=0;b<this.length;b++)this.destroy(this[b],a);return this},listen:function(a,b,c){for(var d=b?b:a,a=b?a:null,b=0;b<this.length;b++){var e=this[b],f="/"==e.path?a||e.path:e.path+(a||"");c?SpahQL.Callbacks.removeCallbackForPathModifiedOnObject(f,e.sourceData,d):SpahQL.Callbacks.addCallbackForPathModifiedOnObject(f,e.sourceData,d)}return this},unlisten:function(a,b){this.listen(a,b,!0)},resultModified:function(a,b){SpahQL.Callbacks.pathModifiedOnObject(a.path, a.sourceData,b,a.value)}});"undefined"!=typeof module&&"undefined"!=typeof module.exports&&(module.exports=SpahQL);"undefined"!=typeof window&&(window.SpahQL=SpahQL); SpahQL_classCreate("SpahQL.Callbacks",{callbacks:{},reset:function(){this.callbacks={}},callbacksForPathInObject:function(a,b){var c=this.callbacks[a],d=[];if(c)for(var e in c)c[0]==b&&d.push(a);return d},pathModifiedOnObject:function(a,b,c,d){if(a){var e=[],a=SpahQL.DataHelper.compare(c,d,a),f;for(f in a)for(c=f;c.lastIndexOf("/")>=0;){e.indexOf(c)<0&&e.push(c);c=c.lastIndexOf("/")==0&&c.length>1?"/":c.substring(0,c.lastIndexOf("/"))}e.sort(function(a,b){return a=="/"?1:b=="/"?-1:a.split("/").length> b.split("/").length?-1:1});SpahQL.log("Path modified on data store, formulated the following dispatch strategy: ["+e.join(" -> ")+"]. Data store: ",b);for(f=0;f<e.length;f++){a=e[f];c=this.callbacks[a];SpahQL.log("Triggering registered path callbacks for "+a+": "+(!c?"No callbacks to trigger":c.length+" callbacks to trigger"));if(c)for(d=0;d<c.length;d++)if(c[d][0]==b){for(var g=[],h=0;h<e.length;h++)e[h]!=a&&e[h].indexOf(a)==0&&g.push(e[h].substring(a.length));c[d][1](SpahQL.select(a,b),a,g)}}}}, addCallbackForPathModifiedOnObject:function(a,b,c){this.callbacks[a]=this.callbacks[a]||[];this.callbacks[a].push([b,c])},removeCallbackForPathModifiedOnObject:function(a,b,c){if(a=this.callbacks[a])for(var d=a.length-1;d>=0;d--)if(a[d][0]==b&&a[d][1]==c){a.splice(d,1);break}}});SpahQL.Errors={};SpahQL.Errors.SpahQLError=function(a){this.name="SpahQLError";this.message=a||""};SpahQL.Errors.SpahQLError.prototype=Error.prototype; SpahQL.Errors.SpahQLRunTimeError=function(a){this.name="SpahQLRunTimeError";this.message=a||""};SpahQL.Errors.SpahQLRunTimeError.prototype=SpahQL.Errors.SpahQLError.prototype;SpahQL_classCreate("SpahQL.Query",{},{init:function(a,b,c,d,e){this.primaryToken=a||null;this.comparisonOperator=b||null;this.secondaryToken=c||null;this.assertion=d||false;this.rawString=e||null}}); SpahQL_classCreate("SpahQL.QueryParser",{queryCache:{},parseQuery:function(a){var b=this.cleanQuery(a);if(this.queryCache[b])return this.queryCache[b];var c=new SpahQL.Query;c.rawString=a;for(var d,e=0;d=SpahQL.Token.parseAt(e,b);){var f=d[0];d=d[1];if(d instanceof SpahQL.Token.ComparisonOperator)if(c.comparisonOperator)this.throwParseAt(e,b,"Found unexpected TOKEN_COMPARISON_OPERATOR, expected EOL");else if(!c.primaryToken||c.primaryToken&&c.secondaryToken)this.throwParseAt(e,b,"Found unexpected TOKEN_COMPARISON_OPERATOR, expected evaluatable token type"); else{c.comparisonOperator=d;c.assertion=true}else{typeof d.toSet=="function"&&(d=d.toSet());if(c.primaryToken)if(c.comparisonOperator)c.secondaryToken?this.throwParseErrorAt(e,b,"Unexpected token, expected EOL"):c.secondaryToken=d;else{console.log("!!!",c);this.throwParseErrorAt(e,b,"Unexpected token, expected EOL or TOKEN_COMPARISON_OPERATOR")}else c.primaryToken=d}e=f}this.queryCache[b]=c;SpahQL.log("Generated and cached query '"+a+"' ->",c);return c},cleanQuery:function(a){for(var b=[],c="",d= 0;d<a.length;d++){var e=a.charAt(d);if((e=='"'||e=="'")&&(d==0||a.charAt(d-1)!="\\")){b[b.length-1]==e?b.pop():b.push(e);c=c+e}else e==" "?b.length>0&&(c=c+e):c=c+e}return c},throwParseErrorAt:function(a,b,c){throw Error("Parse error: '"+(c||"failure")+"' at index "+a+" in query '"+b+"'.");}}); SpahQL_classCreate("SpahQL.QueryRunner",{select:function(a,b,c,d){if(a.assertion)throw new SpahQL.Errors.SpahQLRunTimeError("Attempted to select from an assertion query.");return a.primaryToken.evaluate(b,c||b,d)},assert:function(a,b,c,d){return this.evalAssertion(a.primaryToken,a.secondaryToken,a.comparisonOperator,b,c||b,d)},evalAssertion:function(a,b,c,d,e,f){var g=a.evaluate(d,e,f),a=[],h;for(h in g)a.push(g[h].value);if(b){var b=b.evaluate(d,e,f),f=[],i;for(i in b)f.push(b[i].value)}else return SpahQL.DataHelper.truthySet(a); switch(c.evaluate(d,e)[0].value){case SpahQL.Token.ComparisonOperator.COMPARISON_STRICT_EQUALITY:return SpahQL.DataHelper.eqSetStrict(a,f);case SpahQL.Token.ComparisonOperator.COMPARISON_INEQUALITY:return!SpahQL.DataHelper.eqSetStrict(a,f);case SpahQL.Token.ComparisonOperator.COMPARISON_ROUGH_EQUALITY:return SpahQL.DataHelper.eqSetRough(a,f);case SpahQL.Token.ComparisonOperator.COMPARISON_LT:return SpahQL.DataHelper.ltSet(a,f);case SpahQL.Token.ComparisonOperator.COMPARISON_GT:return SpahQL.DataHelper.gtSet(a, f);case SpahQL.Token.ComparisonOperator.COMPARISON_LTE:return SpahQL.DataHelper.lteSet(a,f);case SpahQL.Token.ComparisonOperator.COMPARISON_GTE:return SpahQL.DataHelper.gteSet(a,f);case SpahQL.Token.ComparisonOperator.COMPARISON_JOINT_SET:return SpahQL.DataHelper.jointSet(a,f);case SpahQL.Token.ComparisonOperator.COMPARISON_DISJOINT_SET:return!SpahQL.DataHelper.jointSet(a,f);case SpahQL.Token.ComparisonOperator.COMPARISON_SUPERSET:return SpahQL.DataHelper.superSet(a,f);case SpahQL.Token.ComparisonOperator.COMPARISON_SUBSET:return SpahQL.DataHelper.superSet(f, a)}}}); SpahQL_classCreate("SpahQL.DataHelper",{compare:function(a,b,c){var d=c=="/"?"":c,e={},f=this.objectType(a),g=this.objectType(b),f=f!="object"&&f!="array",g=g!="object"&&g!="array";if(this.eq(a,b))return e;if(f&&g){var h=this.modificationSymbol(b,a);h&&(e[c]=[h,a,b])}if(!g)for(var i in b){h=this.compare(f?void 0:a[i],b[i],d+"/"+i);for(k in h)e[k]=h[k]}if(!f)for(var j in a){i=this.compare(a[j],g?void 0:b[j],d+"/"+j);for(var k in i)e[k]=i[k]}if(!e[c])(d=this.modificationSymbol(b,a))&&(e[c]=[d,a,b]); return e},modificationSymbol:function(a,b){if(this.objectType(b)=="null")return"+";if(this.objectType(a)=="null")return"-";if(a!=b)return"~"},objectType:function(a){return a==null||a==void 0?"null":typeof a=="object"?Object.prototype.toString.call(a)=="[object Array]"?"array":"object":typeof a},eq:function(){var a,b;a=arguments[0];for(b=1;b<arguments.length;b++){var c=arguments[b],d=this.objectType(a);if(d!=this.objectType(c))return false;if(d=="array"){if(c.length!=a.length)return false;for(d=0;d< c.length;d++)if(!this.eq(c[d],a[d]))return false}else if(d=="object"){if(Object.keys(c).length!=Object.keys(a).length)return false;for(var e in c)if(!this.eq(c[e],a[e]))return false}else if(c!=a)return false;a=c}return true},hashKeys:function(a){return Object.keys(a).sort()},hashValues:function(a){var b=[],c;for(c in a)b.push(a[c]);return b},mathGte:function(a,b){return this.mathCompare(a,b,function(a,b){return a>=b})},mathGt:function(a,b){return this.mathCompare(a,b,function(a,b){return a>b})},mathLte:function(a, b){return this.mathCompare(a,b,function(a,b){return a<=b})},mathLt:function(a,b){return this.mathCompare(a,b,function(a,b){return a<b})},mathCompare:function(a,b,c){var d=this.objectType(a),e=this.objectType(b);return d==e&&(d=="number"||d=="string")?c.apply(this,[a,b]):false},eqRough:function(a,b){var c=this.objectType(a),d=this.objectType(b);if(c!=d)return false;switch(c){case "string":return this.eqStringRough(a,b);case "number":return this.eqNumberRough(a,b);case "array":return this.eqArrayRough(a, b);case "object":return this.eqHashRough(a,b);case "boolean":return this.eqBooleanRough(a,b);default:return false}},eqStringRough:function(a,b){return a.match(RegExp(b,"g"))},eqNumberRough:function(a,b){return Math.floor(a)==Math.floor(b)},eqArrayRough:function(a,b){return this.jointSet(a,b)},eqHashRough:function(a,b){for(var c in a)if(b[c]&&this.eq(a[c],b[c]))return true;return false},eqBooleanRough:function(a,b){return a&&b||!a&&!b},eqSetStrict:function(a,b){if(a.length!=b.length)return false;for(var c= [],d=0;d<a.length;d++)for(var e=a[d],f=0;f<b.length;f++)this.eq(e,b[f])&&c.indexOf(f)<0&&c.push(f);return c.length==a.length},eqSetRough:function(a,b){return this.jointSetWithCallback(a,b,function(a,b){return this.eqRough(a,b)})},jointSet:function(a,b){return this.jointSetWithCallback(a,b,function(a,b){return this.eq(a,b)})},gteSet:function(a,b){return this.jointSetWithCallback(a,b,function(a,b){return this.mathGte(a,b)})},lteSet:function(a,b){return this.jointSetWithCallback(a,b,function(a,b){return this.mathLte(a, b)})},gtSet:function(a,b){return this.jointSetWithCallback(a,b,function(a,b){return this.mathGt(a,b)})},ltSet:function(a,b){return this.jointSetWithCallback(a,b,function(a,b){return this.mathLt(a,b)})},jointSetWithCallback:function(a,b,c){for(var d=0;d<b.length;d++)for(var e=0;e<a.length;e++)if(c.apply(this,[a[e],b[d]]))return true;return false},superSet:function(a,b){var c=[],d=0;for(;d<b.length;d++){var e=b[d],f=0;b:for(;f<a.length;f++){var g=a[f];if(c.indexOf(f)==-1&&this.eq(e,g)){c.push(f);break b}}}return b.length== c.length},truthySet:function(a){for(var b=0;b<a.length;b++)if(a[b])return true;return false},coerceKeyForObject:function(a,b){var c=this.objectType(b);if(c=="array"){c=parseInt(a);return isNaN(c)?null:c}if(c=="object"){c=a.toString();return c.match(/^\s*$/)?null:c}return null},deepClone:function(a){var b=this.objectType(a);if(b=="array"||b=="object"){var b=b=="array"?[]:{},c;for(c in a)b[c]=this.deepClone(a[c]);return b}return a}}); SpahQL_classCreate("SpahQL.Strategiser",{},{init:function(){this.strategies=[];this.categories={}},count:function(a){return this.getStrategies(a).length},addStrategy:function(a,b,c){a=this.commoniseStrategy(a,b,c);this.strategies.push(a);this.categories[a.category]=this.categories[a.category]||[];this.categories[a.category].push(a);return a},removeStrategy:function(a){var b=this.strategies.indexOf(a);if(b>=0){this.strategies.splice(b,1);if(b=this.categories[a.category]){a=b.indexOf(a);a>=0&&b.splice(a, 1)}return true}return false},commoniseStrategy:function(a,b,c){if(a._commonised)return a;if(typeof b=="function"){c=b;b=null}var d=a.paths||a.path;typeof d=="string"&&(d=[d]);var e=a["if"]?true:false,f=(e?a["if"]:a.unless)||null,c=a.action||c,b=b||a.category||"*";return{paths:d,expectation:e,condition:f,action:c,category:b,_commonised:true}},getStrategies:function(a){if(!a)return this.strategies;var a=typeof a=="string"?[a]:a,b=[],c;for(c in this.strategies){var d=this.strategies[c],e=d.category; (e=="*"||a.indexOf(e)>=0)&&b.push(d)}return b},run:function(a,b,c,d){b=this.getStrategies(b);this.locked=true;this.runStrategyLoop(0,b,a,c,d)},runStrategyLoop:function(a,b,c,d,e){function f(){return h.runStrategyLoop(a+1,b,c,d,e)}if(a>=b.length)return this.completed(c,d,e);var g=b[a],h=this;if(g.condition&&c.assert(g.condition)!=g.expectation)return f();this.runStrategyQueryLoop(0,g,c,d,f)},runStrategyQueryLoop:function(a,b,c,d,e){function f(){return g.runStrategyQueryLoop(a+1,b,c,d,e)}if(a>=b.paths.length)return e(); var g=this,h={done:f},i=c.select(b.paths[a]),j=b.action;return i.length>0?j(i,c,d,h):f()},completed:function(a,b,c){c(a,b)}}); SpahQL_classCreate("SpahQL.Token",{parseAt:function(a,b){return SpahQL.Token.ComparisonOperator.parseAt(a,b)||SpahQL.Token.String.parseAt(a,b)||SpahQL.Token.Numeric.parseAt(a,b)||SpahQL.Token.Boolean.parseAt(a,b)||SpahQL.Token.Set.parseAt(a,b)||SpahQL.Token.SelectionQuery.parseAt(a,b)||null},throwParseErrorAt:function(a,b,c){throw Error("Parse error: '"+(c||"failure")+"' at index "+a+" in query '"+b+"'.");}}); SpahQL_classCreate("SpahQL.Token.Base",{parseAt:function(){throw"I should have been overridden. Something is disastrously wrong.";}},{init:function(){},throwRuntimeError:function(a,b){throw Error("Parse error: '"+(b||"failure to execute")+"' in token "+a+".");}});SpahQL_classExtend("SpahQL.Token.Simple",SpahQL.Token.Base,{},{init:function(a){this.value=typeof a!="undefined"?a:null},toSet:function(){return new SpahQL.Token.Set([this])},evaluate:function(){return[SpahQL.result(null,this.value)]}}); SpahQL_classExtend("SpahQL.Token.String",SpahQL.Token.Simple,{ATOM_QUOTE_SINGLE:"'",ATOM_QUOTE_DOUBLE:'"',ATOM_ESCAPE:"\\",parseAt:function(a,b){var c=b.charAt(a);if(c==this.ATOM_QUOTE_SINGLE||c==this.ATOM_QUOTE_DOUBLE){for(var d=0,e="";;){d++;if(b.length<a+d)this.throwParseErrorAt(a,b,"Encountered EOL when expecting "+(c==this.ATOM_QUOTE_SINGLE?"ATOM_QUOTE_SINGLE":"ATOM_QUOTE_DOUBLE"));else if(b.charAt(a+d)==c){d++;break}else if(b.charAt(a+d)==this.ATOM_ESCAPE){e=e+b.charAt(a+d+1);d++}else e=e+b.charAt(a+ d)}return[a+d,new this(e)]}return null}},{}); SpahQL_classExtend("SpahQL.Token.Numeric",SpahQL.Token.Simple,{ATOM_NUMERIC_POINT:".",ATOM_NUMERIC_NEGATIVE:"-",parseAt:function(a,b){var c=b.charAt(a),d=/\d/;if(c.match(d)||c==this.ATOM_NUMERIC_NEGATIVE&&b.charAt(a+1).match(d)){for(var e,f=0;;){f++;if(b.length<a+f)break;else if(b.charAt(a+f)==this.ATOM_NUMERIC_POINT)if(e){f--;break}else{e=true;c=c+b.charAt(a+f)}else if(b.charAt(a+f).match(d))c=c+b.charAt(a+f);else break}return[a+f,new this(e?parseFloat(c):parseInt(c,10))]}return null}}); SpahQL_classExtend("SpahQL.Token.Boolean",SpahQL.Token.Simple,{ATOM_BOOLEAN_TRUE:"true",ATOM_BOOLEAN_FALSE:"false",parseAt:function(a,b){return b.substr(a,this.ATOM_BOOLEAN_TRUE.length)==this.ATOM_BOOLEAN_TRUE?[a+this.ATOM_BOOLEAN_TRUE.length,new this(true)]:b.substr(a,this.ATOM_BOOLEAN_FALSE.length)==this.ATOM_BOOLEAN_FALSE?[a+this.ATOM_BOOLEAN_FALSE.length,new this(false)]:null}}); SpahQL_classExtend("SpahQL.Token.Set",SpahQL.Token.Base,{ATOM_SET_START:"{",ATOM_SET_END:"}",ATOM_SET_ARRAY_DELIMITER:",",ATOM_SET_RANGE_DELIMITER:"..",parseAt:function(a,b){if(b.charAt(a)==this.ATOM_SET_START){var c=a+1,d=[],e=false,f=false,g;if(b.charAt(c)==this.ATOM_SET_END)return[c+1,new this];for(;g=SpahQL.Token.parseAt(c,b);){var h=g[1],i=[SpahQL.Token.Numeric,SpahQL.Token.String,SpahQL.Token.Boolean,SpahQL.Token.SelectionQuery],j=false;for(a in i)if(h instanceof i[a]){j=true;break}if(j){c= g[0];d.push(h);if(b.charAt(c)==this.ATOM_SET_ARRAY_DELIMITER){f&&this.throwParseErrorAt(c,b,"Found unexpected ATOM_SET_ARRAY_DELIMITER in set literal that already used the range delimiter.");e=true;c++}else if(b.substr(c,this.ATOM_SET_RANGE_DELIMITER.length)==this.ATOM_SET_RANGE_DELIMITER){e&&this.throwParseErrorAt(c,b,"Found unexpected ATOM_SET_RANGE_DELIMITER in set literal that already used the array delimiter.");f=true;c=c+this.ATOM_SET_RANGE_DELIMITER.length}else if(b.charAt(c)==this.ATOM_SET_END){c++; break}else this.throwParseErrorAt(c,b,"Found unexpected character '"+b.charAt(c)+"' in set literal, expecting one of ATOM_SET_ARRAY_DELIMITER, ATOM_SET_RANGE_DELIMITER, ATOM_SET_END.")}else this.throwParseErrorAt(c,b,"Found unexpected token in set literal. Set literals may only contain string, numeric, boolean and selection query values.")}return[c,new this(d,f)]}return null}},{init:function(a,b){this.tokens=a||[];this.isRange=b||false},evaluate:function(a,b,c){var d=[];if(this.isRange){this.tokens.length!= 2&&this.throwRuntimeError(this,"Tried to evaluate range with "+this.tokens.length+" tokens, expected 2 tokens. Tokens: "+this.tokens.join(", "));var e=this.tokens[0].evaluate(a,b,c),b=this.tokens[1].evaluate(a,b,c);if(e.length==0||b.length==0)return d;a=e[0].value;b=b[0].value;c=SpahQL.DataHelper.objectType(a);e=SpahQL.DataHelper.objectType(b);if(c==e)c=="number"?d=d.concat(this.evalNumericRange(a,b)):c=="string"?d=d.concat(this.evalStringRange(a,b)):new SpahQL.Errors.SpahQLRunTimeError("Unsupported type used in range. Ranges support only strings and numbers."); else throw new SpahQL.Errors.SpahQLRunTimeError("Illegal range with start type '"+c+"' and end type '"+e+"'. Ranges must use the same type at each end.");}else for(e in this.tokens)d=d.concat(this.tokens[e].evaluate(a,b,c));return d},evalNumericRange:function(a,b){var c=[];if(b<a)for(var d=a;d>=b;d--)c.push(SpahQL.result(null,d));else for(d=a;d<=b;d++)c.push(SpahQL.result(null,d));return c},evalStringRange:function(a,b){var c=[];if(a==b)return[SpahQL.result(null,a)];if(a>b||a.length!=b.length)return c; for(var d=[],e=true,f=0;f<a.length;f++){var g=a.charCodeAt(f);d[f]=g>=48&&g<=57||g>=65&&g<=90||g>=97&&g<=122?false:true;(e=d[f]==true&&e==true)&&f==a.length-1&&(d[f]=false)}e=function(a){for(a=a-1;a>-2;a--)if(d[a]==false)return a};f=a+"";a:for(;;){c.push(SpahQL.result(null,f));if(f==b)break a;var g=e(a.length),h="";b:for(;;){h=function(a){var b=false,a=a.charCodeAt(0);if(a==57){b=true;a=48}else if(a==90){b=true;a=65}else if(a==122){b=true;a=97}else a==127?b=true:a=a+1;return[String.fromCharCode(a), b]}(f.charAt(g));f=f.split("");f.splice(g,1,h[0]);f=f.join("");if(h[1]==true){g=e(g);if(g<0)break a}else break b}}return c}}); SpahQL_classExtend("SpahQL.Token.ComparisonOperator",SpahQL.Token.Simple,{COMPARISON_OPERATORS:"== =~ > < >= <= != }~{ }>{ }<{ }!{".split(" "),COMPARISON_STRICT_EQUALITY:"==",COMPARISON_ROUGH_EQUALITY:"=~",COMPARISON_INEQUALITY:"!=",COMPARISON_LT:"<",COMPARISON_GT:">",COMPARISON_LTE:"<=",COMPARISON_GTE:">=",COMPARISON_JOINT_SET:"}~{",COMPARISON_SUPERSET:"}>{",COMPARISON_SUBSET:"}<{",COMPARISON_DISJOINT_SET:"}!{",parseAt:function(a,b){return this.COMPARISON_OPERATORS.indexOf(b.substr(a,3))>=0?[a+3, new this(b.substr(a,3))]:this.COMPARISON_OPERATORS.indexOf(b.substr(a,2))>=0?[a+2,new this(b.substr(a,2))]:this.COMPARISON_OPERATORS.indexOf(b.substr(a,1))>=0?[a+1,new this(b.substr(a,1))]:null}}); SpahQL_classExtend("SpahQL.Token.FilterQuery",SpahQL.Token.Simple,{ATOM_FILTER_QUERY_START:"[",ATOM_FILTER_QUERY_END:"]",parseAt:function(a,b){if(b.charAt(a)==this.ATOM_FILTER_QUERY_START){for(var c=a+1,d=1,e="",f;d>0;){var g=b.charAt(c);if(g==this.ATOM_FILTER_QUERY_START){d++;e=e+g;c++}else if(g==this.ATOM_FILTER_QUERY_END){d--;c++;if(d==0)break;e=e+g}else if(f=SpahQL.Token.String.parseAt(c,b)){e=e+b.substring(c,f[0]);c=f[0]}else{e=e+g;c++}}if(e.length>0)return[c,new this(SpahQL.QueryParser.parseQuery(e))]; this.throwParseErrorAt(c,b,"Found unexpected ATOM_FILTER_QUERY_END, expected TOKEN_SELECTION_QUERY or TOKEN_ASSERTION_QUERY. Looked like those brackets were empty - make sure they have a query in them.")}return null}},{evaluate:function(a,b){return SpahQL.QueryRunner.assert(this.value,a,b)}}); SpahQL_classExtend("SpahQL.Token.PathComponent",SpahQL.Token.Base,{ATOM_PATH_DELIMITER:"/",ATOM_PROPERTY_IDENTIFIER:".",ATOM_PATH_WILDCARD:"*",parseAt:function(a,b){if(b.charAt(a)==this.ATOM_PATH_DELIMITER){var c=a+1,d=new this,e=false;if(b.charAt(c)==this.ATOM_PATH_DELIMITER){d.recursive=true;c++}if(b.charAt(c)==this.ATOM_PATH_WILDCARD){d.key=this.ATOM_PATH_WILDCARD;c++}else{if(b.charAt(c)==this.ATOM_PROPERTY_IDENTIFIER){e=true;c++}else b.charAt(c)==this.ATOM_PATH_DELIMITER&&this.throwParseErrorAt(c, b,"3 path delimiters found in a row. Maximum legal count is 2.");var f=SpahQL.Token.KeyName.parseAt(c,b);if(!f&&e)this.throwParseError(c,b,"Found unexpected character '"+b.charAt(c)+"' when expecting TOKEN_PROPERTY");else if(f){e?d.property=f[1]:d.key=f[1];c=f[0]}}for(;e=SpahQL.Token.FilterQuery.parseAt(c,b);){d.filterQueries.push(e[1]);c=e[0]}return[c,d]}return null}},{PROPERTY_TYPE:"type",PROPERTY_SIZE:"size",PROPERTY_EXPLODE:"explode",init:function(a,b,c,d){this.key=a||null;this.property=b||null; this.recursive=c||false;this.filterQueries=d||[]},evaluate:function(a,b,c){var d,e=!c||c=="/"?"":c;this.key==null&&this.property==null?d=[SpahQL.result(c,b,a)]:this.key!=null?d=this.fetchResultsFromObjectByKey(this.key.value,a,b,e,this.recursive):this.property!=null&&(d=this.fetchResultsFromObjectByProperty(this.property.value,a,b,e,this.recursive));if(d.length>0&&this.filterQueries.length>0)for(b=0;b<this.filterQueries.length;b++){for(var e=this.filterQueries[b],f=[],c=0;c<d.length;c++){var g=d[c]; e.evaluate(a,g.value)&&f.indexOf(g)<0&&f.push(g)}d=f}return d},fetchResultsFromObjectByKey:function(a,b,c,d,e){var f=SpahQL.DataHelper.objectType(c),g=[];if(f=="array"||f=="object")for(var h in c){var f=c[h],i=SpahQL.DataHelper.objectType(f),j=d+"/"+h;(a==SpahQL.QueryParser.ATOM_PATH_WILDCARD||a.toString()==h.toString())&&g.push(SpahQL.result(j,f,b));if(e&&(i=="array"||i=="object"))g=g.concat(this.fetchResultsFromObjectByKey(a,b,f,j,e))}return g},fetchResultsFromObjectByProperty:function(a,b,c,d, e){var f=SpahQL.DataHelper.objectType(c),g=d+"/."+a,h=[];switch(a){case this.PROPERTY_SIZE:switch(f){case "array":case "string":h.push(SpahQL.result(g,c.length,b));break;case "object":h.push(SpahQL.result(g,SpahQL.DataHelper.hashKeys(c).length,b))}break;case this.PROPERTY_TYPE:h.push(SpahQL.result(g,f,b));break;case this.PROPERTY_EXPLODE:if(f=="string")for(g=0;g<c.length;g++)h.push(SpahQL.result(d+"/"+g,c.charAt(g),b));break;default:throw new SpahQL.Errors.SpahQLRunTimeError("Unrecognised property token '"+ a+"'.");}if(e&&(f=="array"||f=="object"))for(var i in c)h=h.concat(this.fetchResultsFromObjectByProperty(a,b,c[i],d+"/"+i,e));return h}}); SpahQL_classExtend("SpahQL.Token.SelectionQuery",SpahQL.Token.Base,{ATOM_PATH_ROOT:"$",parseAt:function(a,b){var c=b.charAt(a),d=SpahQL.Token.PathComponent.parseAt(a,b);if(c==this.ATOM_PATH_ROOT||d){var e=new this,f=a;if(c==this.ATOM_PATH_ROOT){(d=SpahQL.Token.PathComponent.parseAt(f+1,b))||this.throwParseErrorAt(f+1,b,"Found unexpected character '"+b.charAt(f+1)+"', expected TOKEN_PATH_COMPONENT");e.useRoot=true}f=d[0];for(e.pathComponents.push(d[1]);c=SpahQL.Token.PathComponent.parseAt(f,b);){e.pathComponents.push(c[1]); f=c[0]}return[f,e]}return null}},{init:function(a,b){this.pathComponents=a||[];this.useRoot=b||false},evaluate:function(a,b,c){b=[SpahQL.result((this.useRoot?null:c)||"/",this.useRoot?a:b)];for(c=0;c<this.pathComponents.length;c++){for(var d=this.pathComponents[c],e=[],f=0;f<b.length;f++)e=e.concat(d.evaluate(a,b[f].value,b[f].path));b=e;if(b.length==0)break}return b}}); SpahQL_classExtend("SpahQL.Token.KeyName",SpahQL.Token.Simple,{parseAt:function(a,b){for(var c=/[\w\d_-]/,d=a,e="",f;f=b.charAt(d).match(c);){e=e+f[0];d++}return e.length>0?[d,new this(e)]:null}});