UNPKG

spahql

Version:

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

116 lines (100 loc) 4.14 kB
/** * class SpahQL.Token.SelectionQuery < SpahQL.Token.Base * * A token describing any selection query, comprised of an optional root flag followed by one or more * path components. **/ SpahQL_classExtend("SpahQL.Token.SelectionQuery", SpahQL.Token.Base, { // Singleton // -------------------------- // Atom configuration: paths ATOM_PATH_ROOT: "$", /** * SpahQL.Token.SelectionQuery.parseAt(index, queryString) -> Array result or null * * Reads the given queryString starting at the given index and attempts to identify and parse * a selection query token. If found, the token will be returned in a tuple \[resumeIndex, foundToken\]. * Returns null if nothing is found. **/ "parseAt": function(i, query) { var ch = query.charAt(i); var firstComponent = SpahQL.Token.PathComponent.parseAt(i, query); if(ch == this.ATOM_PATH_ROOT || firstComponent) { // Query as a whole may have: root flag, set of path fragments var pq = new this(); var j = i; if(ch == this.ATOM_PATH_ROOT) { firstComponent = SpahQL.Token.PathComponent.parseAt(j+1, query); if(!firstComponent) { this.throwParseErrorAt(j+1, query, "Found unexpected character '"+query.charAt(j+1)+"', expected TOKEN_PATH_COMPONENT"); } // Valid root path, wind ahead and start chunking queries pq.useRoot = true; } j = firstComponent[0]; pq.pathComponents.push(firstComponent[1]); // Start chunking into path segments var pathComponent; while(pathComponent = SpahQL.Token.PathComponent.parseAt(j, query)) { pq.pathComponents.push(pathComponent[1]); j = pathComponent[0]; } return [j, pq]; } return null; } }, { // Instance // -------------------- /** * SpahQL.Token.SelectionQuery#pathComponents -> Array Token.PathComponent * * Contains all path components that comprise this selection query, in the order in which they * were encountered during parsing. **/ /** * SpahQL.Token.SelectionQuery#useRoot -> Boolean * * A flag indicating whether or not this query is locked to the root data context. **/ /** * new SpahQL.Token.SelectionQuery(pathComponents, useRoot) * * Instantiate a new selection query token with blank-slate values. **/ "init": function(pathComponents, useRoot) { this.pathComponents = pathComponents || []; this.useRoot = useRoot || false; }, /** * SpahQL.Token.SelectionQuery#evaluate(rootData, scopeData, scopePath) -> Array * - rootData (Object): The entire root-level data structure being queried * - scopeData (Object): The data for the scope at which this query is being executed. * - scopePath (String): The string path for the root of the scopeData argument. * * Evaluates all the path components in the given query in turn. **/ "evaluate": function(rootData, scopeData, scopePath) { // Start off with a simulated result using the data required by the query var results = [ SpahQL.result( ((this.useRoot)? null : scopePath) || "/", ((this.useRoot)? rootData : scopeData) ) ]; // Loop path components and pass reduced data for(var i=0; i< this.pathComponents.length; i++) { var pc = this.pathComponents[i]; var pcResults = []; // The results, flattened, for this path component for(var j=0; j < results.length; j++) { // Run each result from the previous iteration through the path component evaluator. // Resultset for initial run is defined at top of this method. pcResults = pcResults.concat(pc.evaluate(rootData, results[j].value, results[j].path)); } results = pcResults; // only continue if there are results to work with if(results.length == 0) break; } return results; } });