Ohm-Management - Projektarbeit B-ME
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

change.js 5.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
  2. var assert = require('assert-plus');
  3. var Attribute = require('./attribute');
  4. var Protocol = require('./protocol');
  5. ///--- API
  6. function Change(options) {
  7. if (options) {
  8. assert.object(options);
  9. assert.optionalString(options.operation);
  10. } else {
  11. options = {};
  12. }
  13. this._modification = false;
  14. this.operation = options.operation || options.type || 'add';
  15. this.modification = options.modification || {};
  16. }
  17. Object.defineProperties(Change.prototype, {
  18. operation: {
  19. get: function getOperation() {
  20. switch (this._operation) {
  21. case 0x00: return 'add';
  22. case 0x01: return 'delete';
  23. case 0x02: return 'replace';
  24. default:
  25. throw new Error('0x' + this._operation.toString(16) + ' is invalid');
  26. }
  27. },
  28. set: function setOperation(val) {
  29. assert.string(val);
  30. switch (val.toLowerCase()) {
  31. case 'add':
  32. this._operation = 0x00;
  33. break;
  34. case 'delete':
  35. this._operation = 0x01;
  36. break;
  37. case 'replace':
  38. this._operation = 0x02;
  39. break;
  40. default:
  41. throw new Error('Invalid operation type: 0x' + val.toString(16));
  42. }
  43. },
  44. configurable: false
  45. },
  46. modification: {
  47. get: function getModification() {
  48. return this._modification;
  49. },
  50. set: function setModification(val) {
  51. if (Attribute.isAttribute(val)) {
  52. this._modification = val;
  53. return;
  54. }
  55. // Does it have an attribute-like structure
  56. if (Object.keys(val).length == 2 &&
  57. typeof (val.type) === 'string' &&
  58. Array.isArray(val.vals)) {
  59. this._modification = new Attribute({
  60. type: val.type,
  61. vals: val.vals
  62. });
  63. return;
  64. }
  65. var keys = Object.keys(val);
  66. if (keys.length > 1) {
  67. throw new Error('Only one attribute per Change allowed');
  68. } else if (keys.length === 0) {
  69. return;
  70. }
  71. var k = keys[0];
  72. var _attr = new Attribute({type: k});
  73. if (Array.isArray(val[k])) {
  74. val[k].forEach(function (v) {
  75. _attr.addValue(v.toString());
  76. });
  77. } else {
  78. _attr.addValue(val[k].toString());
  79. }
  80. this._modification = _attr;
  81. },
  82. configurable: false
  83. },
  84. json: {
  85. get: function getJSON() {
  86. return {
  87. operation: this.operation,
  88. modification: this._modification ? this._modification.json : {}
  89. };
  90. },
  91. configurable: false
  92. }
  93. });
  94. Change.isChange = function isChange(change) {
  95. if (!change || typeof (change) !== 'object') {
  96. return false;
  97. }
  98. if ((change instanceof Change) ||
  99. ((typeof (change.toBer) === 'function') &&
  100. (change.modification !== undefined) &&
  101. (change.operation !== undefined))) {
  102. return true;
  103. }
  104. return false;
  105. };
  106. Change.compare = function (a, b) {
  107. if (!Change.isChange(a) || !Change.isChange(b))
  108. throw new TypeError('can only compare Changes');
  109. if (a.operation < b.operation)
  110. return -1;
  111. if (a.operation > b.operation)
  112. return 1;
  113. return Attribute.compare(a.modification, b.modification);
  114. };
  115. /**
  116. * Apply a Change to properties of an object.
  117. *
  118. * @param {Object} change the change to apply.
  119. * @param {Object} obj the object to apply it to.
  120. * @param {Boolean} scalar convert single-item arrays to scalars. Default: false
  121. */
  122. Change.apply = function apply(change, obj, scalar) {
  123. assert.string(change.operation);
  124. assert.string(change.modification.type);
  125. assert.ok(Array.isArray(change.modification.vals));
  126. assert.object(obj);
  127. var type = change.modification.type;
  128. var vals = change.modification.vals;
  129. var data = obj[type];
  130. if (data !== undefined) {
  131. if (!Array.isArray(data)) {
  132. data = [data];
  133. }
  134. } else {
  135. data = [];
  136. }
  137. switch (change.operation) {
  138. case 'replace':
  139. if (vals.length === 0) {
  140. // replace empty is a delete
  141. delete obj[type];
  142. return obj;
  143. } else {
  144. data = vals;
  145. }
  146. break;
  147. case 'add':
  148. // add only new unique entries
  149. var newValues = vals.filter(function (entry) {
  150. return (data.indexOf(entry) === -1);
  151. });
  152. data = data.concat(newValues);
  153. break;
  154. case 'delete':
  155. data = data.filter(function (entry) {
  156. return (vals.indexOf(entry) === -1);
  157. });
  158. if (data.length === 0) {
  159. // Erase the attribute if empty
  160. delete obj[type];
  161. return obj;
  162. }
  163. break;
  164. default:
  165. break;
  166. }
  167. if (scalar && data.length === 1) {
  168. // store single-value outputs as scalars, if requested
  169. obj[type] = data[0];
  170. } else {
  171. obj[type] = data;
  172. }
  173. return obj;
  174. };
  175. Change.prototype.parse = function (ber) {
  176. assert.ok(ber);
  177. ber.readSequence();
  178. this._operation = ber.readEnumeration();
  179. this._modification = new Attribute();
  180. this._modification.parse(ber);
  181. return true;
  182. };
  183. Change.prototype.toBer = function (ber) {
  184. assert.ok(ber);
  185. ber.startSequence();
  186. ber.writeEnumeration(this._operation);
  187. ber = this._modification.toBer(ber);
  188. ber.endSequence();
  189. return ber;
  190. };
  191. ///--- Exports
  192. module.exports = Change;