"use strict"; var FieldRef = require('./FieldRef'); // Autogenerated by cport.py on 2013-09-17 14:37 var ElementPath = module.exports = function ElementPath(){ this._fieldRef = new FieldRef(); this._shouldTraverseLeafArray = false; }, klass = ElementPath, base = Object , proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}}); // File: path.h lines: 41-41 // FieldRef _fieldRef; proto._fieldRef = undefined; // File: path.h lines: 42-42 // bool _shouldTraverseLeafArray; proto._shouldTraverseLeafArray = undefined; /** * getFieldDottedOrArray * * @method getFieldDottedArray * @param doc * @param path * @param idxPathObj This is an object with a pathID element. This allows for pass by ref in calling function. * */ klass.getFieldDottedOrArray = function getFieldDottedOrArray(doc, path, idxPathObj){ // File path_internal.cpp lines 31-72 if (path.numParts() === 0 ) { return doc; } var res,curr = doc, stop = false, partNum = 0; while (partNum < path.numParts() && !stop) { res = curr[path.getPart( partNum)]; if(res == {}){ stop = true; } else if (res instanceof Object) { curr = res; partNum++; } else if (res instanceof Array) { stop = true; } else { if (partNum + 1 < path.numParts() ) { res = {}; } stop = true; } } //idxPathObj.pathID = partNum; return res; }; /** * isAllDigits does what it says on the tin. * * @method isAllDigits * @param str */ klass.isAllDigits = function isAllDigits ( str ){ // File path_internal.cpp lines 23-29 var digitCheck = /\D/g; if (digitCheck.exec(str) === null){ return true; } return false; }; /** * * return the internal fieldRef object * @method fieldRef * @param * */ proto.fieldRef = function fieldRef( /* */ ){ // File: path.h lines: 37-36 return this._fieldRef; }; /** * * Initialize necessary items on this instance * @method init * @param path * */ proto.init = function init( path ){ // const StringData& path // File: path.cpp lines: 26-29 this._shouldTraverseLeafArray = true; this._fieldRef.parse( path ); return {'code':'OK'}; }; /** * * Set whether paths should traverse leaves inside arrays * @method setTraverseLeafArray * @param * */ proto.setTraverseLeafArray = function setTraverseLeafArray( b ){ // bool b // File: path.h lines: 35-34 this._shouldTraverseLeafArray = b; }; /** * * Return whether arrays should traverse leaf arrays * @method shouldTraverseLeafArray * @param * */ proto.shouldTraverseLeafArray = function shouldTraverseLeafArray( /* */ ){ // File: path.h lines: 38-37 return this._shouldTraverseLeafArray; }; proto.objAtPath = function objAtPath(doc) { return klass.objAtPath(doc, this._fieldRef._path); }; klass.objAtPath = function objAtPath(doc, path) { if(path.length === 0) { return doc; } if (path.length > 0 && Object.keys(doc).length === 0){ return {}; } if (doc === null || doc === undefined) { return doc; } var tpath = path.split('.'); return klass.objAtPath(doc[tpath[0]],tpath.slice(1).join('.')); }; /** * * Helper to wrap our path into the static method * @method _matches * @param doc * @param details * @param function checker this function is used to check for a valid item at the end of the path * */ proto._matches = function _matches(doc, details, checker) { return klass._matches(doc, this._fieldRef._array, this._shouldTraverseLeafArray, details, checker); }; /** * * _matches exists because we don't have pathIterators, so we need a recursive function call * through the path pieces * @method _matches * @param doc * @param path * @param details * @param function checker this function is used to check for a valid item at the end of the path * */ klass._matches = function _matches(doc, path, shouldTraverseLeafArray, details, checker){ // File: expression_array.cpp lines: 34-53 var k, result, ii, il, curr = doc, item = doc; for (k = 0; k < path.length; k++) { if((curr instanceof Object) && (path[k] in curr)) { item = curr[path[k]]; } if(path[k].length === 0) continue; item = curr[path[k]]; if (item instanceof Object && item.constructor === Object) { if (!(isNaN(parseInt(path[k], 10)))) { result = checker(item[path[k]]); if (result) { if (details && details.needRecord()) details.setElemMatchKey(ii.toString()); return result; } } curr = item; continue; } else if (item instanceof Object && item.constructor === Array) { if (k == path.length-1) { if ((shouldTraverseLeafArray) && (isNaN(parseInt(path[k], 10)))) { for (ii = 0, il = item.length; ii < il; ii++) { result = checker(item[ii]); if (result) { if (details && details.needRecord()) details.setElemMatchKey(ii.toString()); return result; } } if(item.length === 0) return checker({}); } curr = item; break; // this is the end of the path, so check this array } else if (!(isNaN(parseInt(path[k+1], 10)))) { curr = item; continue; // the *next* path section is an item in the array so we don't check this whole array } // otherwise, check each item in the array against the rest of the path for(ii = 0, il = item.length; ii < il; ii++){ var subitem = item[ii]; if (subitem.constructor !== Object) continue; // can't look for a subfield in a non-object value. if (this._matches(subitem, path.slice(k), shouldTraverseLeafArray, null, checker)) { // check the item against the rest of the path if (details && details.needRecord()) details.setElemMatchKey(ii.toString()); return true; } } return false; // checked all items in the array and found no matches } } return checker(item); };