2011-08-04 20:32:01 +00:00
|
|
|
// Copyright 2011 Mark Cavage, Inc. All rights reserved.
|
|
|
|
|
|
|
|
var assert = require('assert');
|
|
|
|
|
|
|
|
var Attribute = require('./attribute');
|
|
|
|
var Protocol = require('./protocol');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///--- API
|
|
|
|
|
|
|
|
function Change(options) {
|
|
|
|
if (options) {
|
2012-02-18 08:15:52 +00:00
|
|
|
if (typeof (options) !== 'object')
|
2011-08-04 20:32:01 +00:00
|
|
|
throw new TypeError('options must be an object');
|
2012-02-18 08:15:52 +00:00
|
|
|
if (options.operation && typeof (options.operation) !== 'string')
|
2011-08-04 20:32:01 +00:00
|
|
|
throw new TypeError('options.operation must be a string');
|
|
|
|
} else {
|
|
|
|
options = {};
|
|
|
|
}
|
|
|
|
|
|
|
|
var self = this;
|
2012-02-18 08:15:52 +00:00
|
|
|
this._modification = false;
|
|
|
|
|
|
|
|
this.__defineGetter__('operation', function () {
|
2011-08-04 20:32:01 +00:00
|
|
|
switch (self._operation) {
|
2011-08-12 23:37:47 +00:00
|
|
|
case 0x00: return 'add';
|
|
|
|
case 0x01: return 'delete';
|
|
|
|
case 0x02: return 'replace';
|
|
|
|
default:
|
|
|
|
throw new Error('0x' + self._operation.toString(16) + ' is invalid');
|
2011-08-04 20:32:01 +00:00
|
|
|
}
|
|
|
|
});
|
2012-02-18 08:15:52 +00:00
|
|
|
this.__defineSetter__('operation', function (val) {
|
|
|
|
if (typeof (val) !== 'string')
|
2011-08-04 20:32:01 +00:00
|
|
|
throw new TypeError('operation must be a string');
|
|
|
|
|
|
|
|
switch (val.toLowerCase()) {
|
|
|
|
case 'add':
|
|
|
|
self._operation = 0x00;
|
|
|
|
break;
|
|
|
|
case 'delete':
|
|
|
|
self._operation = 0x01;
|
|
|
|
break;
|
|
|
|
case 'replace':
|
|
|
|
self._operation = 0x02;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
throw new Error('Invalid operation type: 0x' + val.toString(16));
|
|
|
|
}
|
|
|
|
});
|
2012-02-18 08:15:52 +00:00
|
|
|
this.__defineGetter__('modification', function () {
|
2011-08-04 21:25:12 +00:00
|
|
|
return self._modification;
|
|
|
|
});
|
2012-02-18 08:15:52 +00:00
|
|
|
|
|
|
|
this.__defineSetter__('modification', function (attr) {
|
2011-08-06 20:44:26 +00:00
|
|
|
if (Attribute.isAttribute(attr)) {
|
2011-08-04 21:25:12 +00:00
|
|
|
self._modification = attr;
|
2011-08-06 20:44:26 +00:00
|
|
|
return;
|
|
|
|
}
|
2011-11-08 21:31:00 +00:00
|
|
|
var keys = Object.keys(attr);
|
|
|
|
if (keys.length > 1)
|
|
|
|
throw new Error('Only one attribute per Change allowed');
|
|
|
|
|
2012-02-18 08:15:52 +00:00
|
|
|
keys.forEach(function (k) {
|
2011-08-04 21:25:12 +00:00
|
|
|
var _attr = new Attribute({type: k});
|
|
|
|
if (Array.isArray(attr[k])) {
|
2012-02-18 08:15:52 +00:00
|
|
|
attr[k].forEach(function (v) {
|
2011-08-04 21:25:12 +00:00
|
|
|
_attr.addValue(v.toString());
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
_attr.addValue(attr[k].toString());
|
|
|
|
}
|
|
|
|
self._modification = _attr;
|
|
|
|
});
|
|
|
|
});
|
2012-02-18 08:15:52 +00:00
|
|
|
this.__defineGetter__('json', function () {
|
2011-08-04 20:32:01 +00:00
|
|
|
return {
|
|
|
|
operation: self.operation,
|
2011-08-06 20:44:26 +00:00
|
|
|
modification: self._modification ? self._modification.json : {}
|
2011-08-04 20:32:01 +00:00
|
|
|
};
|
|
|
|
});
|
|
|
|
|
2011-09-23 15:48:17 +00:00
|
|
|
this.operation = options.operation || options.type || 'add';
|
2011-08-04 21:25:12 +00:00
|
|
|
this.modification = options.modification || {};
|
2011-08-04 20:32:01 +00:00
|
|
|
}
|
|
|
|
module.exports = Change;
|
|
|
|
|
2014-06-24 19:14:17 +00:00
|
|
|
Change.isChange = function isChange(change) {
|
|
|
|
if (!change || typeof (change) !== 'object') {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if ((change instanceof Change) ||
|
|
|
|
((typeof (change.toBer) === 'function') &&
|
|
|
|
(change.modification !== undefined) &&
|
|
|
|
(change.operation !== undefined))) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
};
|
2011-08-04 20:32:01 +00:00
|
|
|
|
2012-02-18 08:15:52 +00:00
|
|
|
Change.compare = function (a, b) {
|
2014-06-24 19:14:17 +00:00
|
|
|
if (!Change.isChange(a) || !Change.isChange(b))
|
2011-08-08 15:03:00 +00:00
|
|
|
throw new TypeError('can only compare Changes');
|
|
|
|
|
2012-02-18 08:15:52 +00:00
|
|
|
if (a.operation < b.operation)
|
|
|
|
return -1;
|
|
|
|
if (a.operation > b.operation)
|
|
|
|
return 1;
|
2011-08-08 15:03:00 +00:00
|
|
|
|
|
|
|
return Attribute.compare(a.modification, b.modification);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2012-02-18 08:15:52 +00:00
|
|
|
Change.prototype.parse = function (ber) {
|
2011-08-04 20:32:01 +00:00
|
|
|
assert.ok(ber);
|
|
|
|
|
|
|
|
ber.readSequence();
|
|
|
|
this._operation = ber.readEnumeration();
|
2011-08-04 21:25:12 +00:00
|
|
|
this._modification = new Attribute();
|
|
|
|
this._modification.parse(ber);
|
2011-08-04 20:32:01 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2012-02-18 08:15:52 +00:00
|
|
|
Change.prototype.toBer = function (ber) {
|
2011-08-04 20:32:01 +00:00
|
|
|
assert.ok(ber);
|
|
|
|
|
|
|
|
ber.startSequence();
|
|
|
|
ber.writeEnumeration(this._operation);
|
2011-08-04 21:25:12 +00:00
|
|
|
ber = this._modification.toBer(ber);
|
2011-08-04 20:32:01 +00:00
|
|
|
ber.endSequence();
|
|
|
|
|
|
|
|
return ber;
|
|
|
|
};
|