FieldPath.js 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. "use strict";
  2. /**
  3. * Constructor for field paths.
  4. *
  5. * The constructed object will have getPathLength() > 0.
  6. * Uassert if any component field names do not pass validation.
  7. *
  8. * @class FieldPath
  9. * @namespace mungedb-aggregate.pipeline
  10. * @module mungedb-aggregate
  11. * @constructor
  12. * @param fieldPath the dotted field path string or non empty pre-split vector.
  13. **/
  14. var FieldPath = module.exports = function FieldPath(path) {
  15. var fields = typeof path === "object" && typeof path.length === "number" ? path : path.split(".");
  16. if(fields.length === 0) throw new Error("FieldPath cannot be constructed from an empty vector (String or Array).; code 16409");
  17. for(var i = 0, n = fields.length; i < n; ++i){
  18. var field = fields[i];
  19. if(field.length === 0) throw new Error("FieldPath field names may not be empty strings; code 15998");
  20. if(field[0] == "$") throw new Error("FieldPath field names may not start with '$'; code 16410");
  21. if(field.indexOf("\0") != -1) throw new Error("FieldPath field names may not contain '\\0'; code 16411");
  22. if(field.indexOf(".") != -1) throw new Error("FieldPath field names may not contain '.'; code 16412");
  23. }
  24. this.path = path;
  25. this.fields = fields;
  26. }, klass = FieldPath, base = Object, proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
  27. // STATIC MEMBERS
  28. klass.PREFIX = "$";
  29. // PROTOTYPE MEMBERS
  30. /**
  31. * Get the full path.
  32. *
  33. * @method getPath
  34. * @param fieldPrefix whether or not to include the field prefix
  35. * @returns the complete field path
  36. **/
  37. proto.getPath = function getPath(withPrefix) {
  38. return ( !! withPrefix ? FieldPath.PREFIX : "") + this.fields.join(".");
  39. };
  40. /**
  41. * A FieldPath like this but missing the first element (useful for recursion). Precondition getPathLength() > 1.
  42. *
  43. * @method tail
  44. **/
  45. proto.tail = function tail() {
  46. return new FieldPath(this.fields.slice(1));
  47. };
  48. /**
  49. * Get a particular path element from the path.
  50. *
  51. * @method getFieldName
  52. * @param i the zero based index of the path element.
  53. * @returns the path element
  54. **/
  55. proto.getFieldName = function getFieldName(i){ //TODO: eventually replace this with just using .fields[i] directly
  56. return this.fields[i];
  57. };
  58. /**
  59. * Get the number of path elements in the field path.
  60. *
  61. * @method getPathLength
  62. * @returns the number of path elements
  63. **/
  64. proto.getPathLength = function getPathLength() {
  65. return this.fields.length;
  66. };