FieldPath.js 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  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 fieldNames = typeof path === "object" && typeof path.length === "number" ? path : path.split(".");
  16. if (fieldNames.length === 0)
  17. throw new Error("FieldPath cannot be constructed from an empty vector (String or Array).; massert code 16409");
  18. this.fieldNames = [];
  19. for (var i = 0, n = fieldNames.length; i < n; ++i) {
  20. this._pushFieldName(fieldNames[i]);
  21. }
  22. }, klass = FieldPath, base = Object, proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
  23. klass.PREFIX = "$";
  24. /**
  25. * Get the full path.
  26. * @method getPath
  27. * @param fieldPrefix whether or not to include the field prefix
  28. * @returns the complete field path
  29. */
  30. proto.getPath = function getPath(fieldPrefix) {
  31. return (!!fieldPrefix ? FieldPath.PREFIX : "") + this.fieldNames.join(".");
  32. };
  33. //SKIPPED: writePath - merged into getPath
  34. /**
  35. * A FieldPath like this but missing the first element (useful for recursion). Precondition getPathLength() > 1.
  36. * @method tail
  37. */
  38. proto.tail = function tail() {
  39. return new FieldPath(this.fieldNames.slice(1));
  40. };
  41. /**
  42. * Get a particular path element from the path.
  43. * @method getFieldName
  44. * @param i the zero based index of the path element.
  45. * @returns the path element
  46. */
  47. proto.getFieldName = function getFieldName(i) { //TODO: eventually replace this with just using .fieldNames[i] directly
  48. return this.fieldNames[i];
  49. };
  50. klass._uassertValidFieldName = function _uassertValidFieldName(fieldName) {
  51. if (fieldName.length === 0) throw new Error("FieldPath field names may not be empty strings; code 15998");
  52. if (fieldName[0] === "$") throw new Error("FieldPath field names may not start with '$'; code 16410");
  53. if (fieldName.indexOf("\0") !== -1) throw new Error("FieldPath field names may not contain '\\0'; code 16411");
  54. if (fieldName.indexOf(".") !== -1) throw new Error("FieldPath field names may not contain '.'; code 16412");
  55. };
  56. proto._pushFieldName = function _pushFieldName(fieldName) {
  57. klass._uassertValidFieldName(fieldName);
  58. this.fieldNames.push(fieldName);
  59. };
  60. /**
  61. * Get the number of path elements in the field path.
  62. * @method getPathLength
  63. * @returns the number of path elements
  64. */
  65. proto.getPathLength = function getPathLength() {
  66. return this.fieldNames.length;
  67. };