Operation can now save static content/Operations

This commit is contained in:
Kevin Jahns 2015-04-19 18:54:03 +02:00
parent b02662c36e
commit 2a78cdba48
14 changed files with 1243 additions and 1025 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -7,7 +7,8 @@ module.exports = function() {
ops = {}; ops = {};
execution_listener = []; execution_listener = [];
ops.Operation = (function() { ops.Operation = (function() {
function Operation(custom_type, uid) { function Operation(custom_type, uid, content, content_operations) {
var name, op;
if (custom_type != null) { if (custom_type != null) {
this.custom_type = custom_type; this.custom_type = custom_type;
} }
@ -17,10 +18,61 @@ module.exports = function() {
if (uid != null) { if (uid != null) {
this.uid = uid; this.uid = uid;
} }
if (content === void 0) {
} else if ((content != null) && (content.creator != null)) {
this.saveOperation('content', content);
} else {
this.content = content;
}
if (content_operations != null) {
this.content_operations = {};
for (name in content_operations) {
op = content_operations[name];
this.saveOperation(name, op, 'content_operations');
}
}
} }
Operation.prototype.type = "Operation"; Operation.prototype.type = "Operation";
Operation.prototype.getContent = function(name) {
var content, n, ref, ref1, v;
if (this.content != null) {
if (this.content.getCustomType != null) {
return this.content.getCustomType();
} else if (this.content.constructor === Object) {
if (name != null) {
if (this.content[name] != null) {
return this.content[name];
} else {
return this.content_operations[name].getCustomType();
}
} else {
content = {};
ref = this.content;
for (n in ref) {
v = ref[n];
content[n] = v;
}
if (this.content_operations != null) {
ref1 = this.content_operations;
for (n in ref1) {
v = ref1[n];
v = v.getCustomType();
content[n] = v;
}
}
return content;
}
} else {
return this.content;
}
} else {
return this.content;
}
};
Operation.prototype.retrieveSub = function() { Operation.prototype.retrieveSub = function() {
throw new Error("sub properties are not enable on this operation type!"); throw new Error("sub properties are not enable on this operation type!");
}; };
@ -124,34 +176,22 @@ module.exports = function() {
Operation.prototype.execute = function() { Operation.prototype.execute = function() {
var j, l, len; var j, l, len;
this.is_executed = true; if (this.validateSavedOperations()) {
if (this.uid == null) { this.is_executed = true;
this.uid = this.HB.getNextOperationIdentifier(); if (this.uid == null) {
} this.uid = this.HB.getNextOperationIdentifier();
if (this.uid.noOperation == null) {
this.HB.addOperation(this);
for (j = 0, len = execution_listener.length; j < len; j++) {
l = execution_listener[j];
l(this._encode());
} }
} if (this.uid.noOperation == null) {
return this; this.HB.addOperation(this);
}; for (j = 0, len = execution_listener.length; j < len; j++) {
l = execution_listener[j];
Operation.prototype._encode = function(json) { l(this._encode());
if (json == null) { }
json = {};
}
json.type = this.type;
json.uid = this.getUid();
if (this.custom_type != null) {
if (this.custom_type.constructor === String) {
json.custom_type = this.custom_type;
} else {
json.custom_type = this.custom_type._name;
} }
return this;
} else {
return false;
} }
return json;
}; };
Operation.prototype.saveOperation = function(name, op, base) { Operation.prototype.saveOperation = function(name, op, base) {
@ -159,6 +199,9 @@ module.exports = function() {
if (base == null) { if (base == null) {
base = "this"; base = "this";
} }
if ((op != null) && (op._getModel != null)) {
op = op._getModel(this.custom_types, this.operations);
}
if (op == null) { if (op == null) {
} else if ((op.execute != null) || !((op.op_number != null) && (op.creator != null))) { } else if ((op.execute != null) || !((op.op_number != null) && (op.creator != null))) {
@ -188,7 +231,7 @@ module.exports = function() {
Operation.prototype.validateSavedOperations = function() { Operation.prototype.validateSavedOperations = function() {
var base, base_name, dest, j, last_path, len, name, op, op_uid, path, paths, ref, success, uninstantiated; var base, base_name, dest, j, last_path, len, name, op, op_uid, path, paths, ref, success, uninstantiated;
uninstantiated = {}; uninstantiated = {};
success = this; success = true;
ref = this.unchecked; ref = this.unchecked;
for (base_name in ref) { for (base_name in ref) {
base = ref[base_name]; base = ref[base_name];
@ -217,11 +260,13 @@ module.exports = function() {
} }
} }
} }
delete this.unchecked;
if (!success) { if (!success) {
this.unchecked = uninstantiated; this.unchecked = uninstantiated;
return false;
} else {
delete this.unchecked;
return this;
} }
return success;
}; };
Operation.prototype.getCustomType = function() { Operation.prototype.getCustomType = function() {
@ -243,6 +288,40 @@ module.exports = function() {
} }
}; };
Operation.prototype._encode = function(json) {
var n, o, operations, ref, ref1;
if (json == null) {
json = {};
}
json.type = this.type;
json.uid = this.getUid();
if (this.custom_type != null) {
if (this.custom_type.constructor === String) {
json.custom_type = this.custom_type;
} else {
json.custom_type = this.custom_type._name;
}
}
if (((ref = this.content) != null ? ref.getUid : void 0) != null) {
json.content = this.content.getUid();
} else {
json.content = this.content;
}
if (this.content_operations != null) {
operations = {};
ref1 = this.content_operations;
for (n in ref1) {
o = ref1[n];
if (o._getModel != null) {
o = o._getModel(this.custom_types, this.operations);
}
operations[n] = o.getUid();
}
json.content_operations = operations;
}
return json;
};
return Operation; return Operation;
})(); })();
@ -289,21 +368,6 @@ module.exports = function() {
extend(Insert, superClass); extend(Insert, superClass);
function Insert(custom_type, content, content_operations, parent, uid, prev_cl, next_cl, origin) { function Insert(custom_type, content, content_operations, parent, uid, prev_cl, next_cl, origin) {
var name, op;
if (content === void 0) {
} else if ((content != null) && (content.creator != null)) {
this.saveOperation('content', content);
} else {
this.content = content;
}
if (content_operations != null) {
this.content_operations = {};
for (name in content_operations) {
op = content_operations[name];
this.saveOperation(name, op, 'content_operations');
}
}
this.saveOperation('parent', parent); this.saveOperation('parent', parent);
this.saveOperation('prev_cl', prev_cl); this.saveOperation('prev_cl', prev_cl);
this.saveOperation('next_cl', next_cl); this.saveOperation('next_cl', next_cl);
@ -312,37 +376,13 @@ module.exports = function() {
} else { } else {
this.saveOperation('origin', prev_cl); this.saveOperation('origin', prev_cl);
} }
Insert.__super__.constructor.call(this, custom_type, uid); Insert.__super__.constructor.call(this, custom_type, uid, content, content_operations);
} }
Insert.prototype.type = "Insert"; Insert.prototype.type = "Insert";
Insert.prototype.val = function() { Insert.prototype.val = function() {
var content, n, ref, ref1, v; return this.getContent();
if (this.content != null) {
if (this.content.getCustomType != null) {
return this.content.getCustomType();
} else if (this.content.constructor === Object) {
content = {};
ref = this.content;
for (n in ref) {
v = ref[n];
content[n] = v;
}
if (this.content_operations != null) {
ref1 = this.content_operations;
for (n in ref1) {
v = ref1[n];
content[n] = v;
}
}
return content;
} else {
return this.content;
}
} else {
return this.content;
}
}; };
Insert.prototype.getNext = function(i) { Insert.prototype.getNext = function(i) {
@ -524,7 +564,6 @@ module.exports = function() {
}; };
Insert.prototype._encode = function(json) { Insert.prototype._encode = function(json) {
var n, o, operations, ref, ref1;
if (json == null) { if (json == null) {
json = {}; json = {};
} }
@ -536,20 +575,6 @@ module.exports = function() {
json.origin = this.origin.getUid(); json.origin = this.origin.getUid();
} }
json.parent = this.parent.getUid(); json.parent = this.parent.getUid();
if (((ref = this.content) != null ? ref.getUid : void 0) != null) {
json.content = this.content.getUid();
} else {
json.content = JSON.stringify(this.content);
}
if (this.content_operations != null) {
operations = {};
ref1 = this.content_operations;
for (n in ref1) {
o = ref1[n];
operations[n] = o.getUid();
}
json.content_operations = operations;
}
return Insert.__super__._encode.call(this, json); return Insert.__super__._encode.call(this, json);
}; };
@ -559,9 +584,6 @@ module.exports = function() {
ops.Insert.parse = function(json) { ops.Insert.parse = function(json) {
var content, content_operations, next, origin, parent, prev, uid; var content, content_operations, next, origin, parent, prev, uid;
content = json['content'], content_operations = json['content_operations'], uid = json['uid'], prev = json['prev'], next = json['next'], origin = json['origin'], parent = json['parent']; content = json['content'], content_operations = json['content_operations'], uid = json['uid'], prev = json['prev'], next = json['next'], origin = json['origin'], parent = json['parent'];
if (typeof content === "string") {
content = JSON.parse(content);
}
return new this(null, content, content_operations, parent, uid, prev, next, origin); return new this(null, content, content_operations, parent, uid, prev, next, origin);
}; };
ops.Delimiter = (function(superClass) { ops.Delimiter = (function(superClass) {

View File

@ -11,9 +11,11 @@ module.exports = function() {
ops.MapManager = (function(superClass) { ops.MapManager = (function(superClass) {
extend(MapManager, superClass); extend(MapManager, superClass);
function MapManager(custom_type, uid) { function MapManager(custom_type, uid, content, content_operations) {
this._map = {}; this._map = {};
MapManager.__super__.constructor.call(this, custom_type, uid); console.log("delete this ...");
this.constructed_with = [custom_type, content, content_operations];
MapManager.__super__.constructor.call(this, custom_type, uid, content, content_operations);
} }
MapManager.prototype.type = "MapManager"; MapManager.prototype.type = "MapManager";
@ -109,20 +111,20 @@ module.exports = function() {
})(ops.Operation); })(ops.Operation);
ops.MapManager.parse = function(json) { ops.MapManager.parse = function(json) {
var custom_type, uid; var content, content_operations, custom_type, uid;
uid = json['uid'], custom_type = json['custom_type']; uid = json['uid'], custom_type = json['custom_type'], content = json['content'], content_operations = json['content_operations'];
return new this(custom_type, uid); return new this(custom_type, uid, content, content_operations);
}; };
ops.ListManager = (function(superClass) { ops.ListManager = (function(superClass) {
extend(ListManager, superClass); extend(ListManager, superClass);
function ListManager(custom_type, uid) { function ListManager(custom_type, uid, content, content_operations) {
this.beginning = new ops.Delimiter(void 0, void 0); this.beginning = new ops.Delimiter(void 0, void 0);
this.end = new ops.Delimiter(this.beginning, void 0); this.end = new ops.Delimiter(this.beginning, void 0);
this.beginning.next_cl = this.end; this.beginning.next_cl = this.end;
this.beginning.execute(); this.beginning.execute();
this.end.execute(); this.end.execute();
ListManager.__super__.constructor.call(this, custom_type, uid); ListManager.__super__.constructor.call(this, custom_type, uid, content, content_operations);
} }
ListManager.prototype.type = "ListManager"; ListManager.prototype.type = "ListManager";
@ -359,9 +361,9 @@ module.exports = function() {
})(ops.Operation); })(ops.Operation);
ops.ListManager.parse = function(json) { ops.ListManager.parse = function(json) {
var custom_type, uid; var content, content_operations, custom_type, uid;
uid = json['uid'], custom_type = json['custom_type']; uid = json['uid'], custom_type = json['custom_type'], content = json['content'], content_operations = json['content_operations'];
return new this(custom_type, uid); return new this(custom_type, uid, content, content_operations);
}; };
ops.Composition = (function(superClass) { ops.Composition = (function(superClass) {
extend(Composition, superClass); extend(Composition, superClass);
@ -369,8 +371,6 @@ module.exports = function() {
function Composition(custom_type, _composition_value, composition_value_operations, uid, tmp_composition_ref) { function Composition(custom_type, _composition_value, composition_value_operations, uid, tmp_composition_ref) {
var n, o; var n, o;
this._composition_value = _composition_value; this._composition_value = _composition_value;
console.log("delete this ...");
this.constructed_with = [custom_type, this._composition_value, composition_value_operations, uid, tmp_composition_ref];
Composition.__super__.constructor.call(this, custom_type, uid); Composition.__super__.constructor.call(this, custom_type, uid);
if (tmp_composition_ref != null) { if (tmp_composition_ref != null) {
this.tmp_composition_ref = tmp_composition_ref; this.tmp_composition_ref = tmp_composition_ref;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -22,7 +22,7 @@ module.exports = ()->
# @param {Object} uid A unique identifier. # @param {Object} uid A unique identifier.
# If uid is undefined, a new uid will be created before at the end of the execution sequence # If uid is undefined, a new uid will be created before at the end of the execution sequence
# #
constructor: (custom_type, uid)-> constructor: (custom_type, uid, content, content_operations)->
if custom_type? if custom_type?
@custom_type = custom_type @custom_type = custom_type
@is_deleted = false @is_deleted = false
@ -31,8 +31,44 @@ module.exports = ()->
if uid? if uid?
@uid = uid @uid = uid
# see encode to see, why we are doing it this way
if content is undefined
# nop
else if content? and content.creator?
@saveOperation 'content', content
else
@content = content
if content_operations?
@content_operations = {}
for name, op of content_operations
@saveOperation name, op, 'content_operations'
type: "Operation" type: "Operation"
getContent: (name)->
if @content?
if @content.getCustomType?
@content.getCustomType()
else if @content.constructor is Object
if name?
if @content[name]?
@content[name]
else
@content_operations[name].getCustomType()
else
content = {}
for n,v of @content
content[n] = v
if @content_operations?
for n,v of @content_operations
v = v.getCustomType()
content[n] = v
content
else
@content
else
@content
retrieveSub: ()-> retrieveSub: ()->
throw new Error "sub properties are not enable on this operation type!" throw new Error "sub properties are not enable on this operation type!"
@ -137,32 +173,20 @@ module.exports = ()->
# Notify the all the listeners. # Notify the all the listeners.
# #
execute: ()-> execute: ()->
@is_executed = true if @validateSavedOperations()
if not @uid? @is_executed = true
# When this operation was created without a uid, then set it here. if not @uid?
# There is only one other place, where this can be done - before an Insertion # When this operation was created without a uid, then set it here.
# is executed (because we need the creator_id) # There is only one other place, where this can be done - before an Insertion
@uid = @HB.getNextOperationIdentifier() # is executed (because we need the creator_id)
if not @uid.noOperation? @uid = @HB.getNextOperationIdentifier()
@HB.addOperation @ if not @uid.noOperation?
for l in execution_listener @HB.addOperation @
l @_encode() for l in execution_listener
@ l @_encode()
@
# else
# @private false
# Encode this operation in such a way that it can be parsed by remote peers.
#
_encode: (json = {})->
json.type = @type
json.uid = @getUid()
if @custom_type?
if @custom_type.constructor is String
json.custom_type = @custom_type
else
json.custom_type = @custom_type._name
json
# #
# @private # @private
@ -183,7 +207,8 @@ module.exports = ()->
# @param {Operation} op An Operation object # @param {Operation} op An Operation object
# #
saveOperation: (name, op, base = "this")-> saveOperation: (name, op, base = "this")->
if op? and op._getModel?
op = op._getModel(@custom_types, @operations)
# #
# Every instance of $Operation must have an $execute function. # Every instance of $Operation must have an $execute function.
# We use duck-typing to check if op is instantiated since there # We use duck-typing to check if op is instantiated since there
@ -218,7 +243,7 @@ module.exports = ()->
# #
validateSavedOperations: ()-> validateSavedOperations: ()->
uninstantiated = {} uninstantiated = {}
success = @ success = true
for base_name, base of @unchecked for base_name, base of @unchecked
for name, op_uid of base for name, op_uid of base
op = @HB.getOperation op_uid op = @HB.getOperation op_uid
@ -236,10 +261,12 @@ module.exports = ()->
uninstantiated[base_name] ?= {} uninstantiated[base_name] ?= {}
uninstantiated[base_name][name] = op_uid uninstantiated[base_name][name] = op_uid
success = false success = false
delete @unchecked
if not success if not success
@unchecked = uninstantiated @unchecked = uninstantiated
success return false
else
delete @unchecked
return @
getCustomType: ()-> getCustomType: ()->
if not @custom_type? if not @custom_type?
@ -255,6 +282,31 @@ module.exports = ()->
@custom_type._setModel @ @custom_type._setModel @
@custom_type @custom_type
#
# @private
# Encode this operation in such a way that it can be parsed by remote peers.
#
_encode: (json = {})->
json.type = @type
json.uid = @getUid()
if @custom_type?
if @custom_type.constructor is String
json.custom_type = @custom_type
else
json.custom_type = @custom_type._name
if @content?.getUid?
json.content = @content.getUid()
else
json.content = @content
if @content_operations?
operations = {}
for n,o of @content_operations
if o._getModel?
o = o._getModel(@custom_types, @operations)
operations[n] = o.getUid()
json.content_operations = operations
json
# #
# @nodoc # @nodoc
@ -325,17 +377,6 @@ module.exports = ()->
# @param {Operation} next_cl The successor of this operation in the complete-list (cl) # @param {Operation} next_cl The successor of this operation in the complete-list (cl)
# #
constructor: (custom_type, content, content_operations, parent, uid, prev_cl, next_cl, origin)-> constructor: (custom_type, content, content_operations, parent, uid, prev_cl, next_cl, origin)->
# see encode to see, why we are doing it this way
if content is undefined
# nop
else if content? and content.creator?
@saveOperation 'content', content
else
@content = content
if content_operations?
@content_operations = {}
for name, op of content_operations
@saveOperation name, op, 'content_operations'
@saveOperation 'parent', parent @saveOperation 'parent', parent
@saveOperation 'prev_cl', prev_cl @saveOperation 'prev_cl', prev_cl
@saveOperation 'next_cl', next_cl @saveOperation 'next_cl', next_cl
@ -343,26 +384,12 @@ module.exports = ()->
@saveOperation 'origin', origin @saveOperation 'origin', origin
else else
@saveOperation 'origin', prev_cl @saveOperation 'origin', prev_cl
super custom_type, uid super custom_type, uid, content, content_operations
type: "Insert" type: "Insert"
val: ()-> val: ()->
if @content? @getContent()
if @content.getCustomType?
@content.getCustomType()
else if @content.constructor is Object
content = {}
for n,v of @content
content[n] = v
if @content_operations?
for n,v of @content_operations
content[n] = v
content
else
@content
else
@content
getNext: (i=1)-> getNext: (i=1)->
n = @ n = @
@ -551,15 +578,6 @@ module.exports = ()->
# if not (json.prev? and json.next?) # if not (json.prev? and json.next?)
json.parent = @parent.getUid() json.parent = @parent.getUid()
if @content?.getUid?
json.content = @content.getUid()
else
json.content = JSON.stringify @content
if @content_operations?
operations = {}
for n,o of @content_operations
operations[n] = o.getUid()
json.content_operations = operations
super json super json
ops.Insert.parse = (json)-> ops.Insert.parse = (json)->
@ -572,8 +590,6 @@ module.exports = ()->
'origin' : origin 'origin' : origin
'parent' : parent 'parent' : parent
} = json } = json
if typeof content is "string"
content = JSON.parse(content)
new this null, content, content_operations, parent, uid, prev, next, origin new this null, content, content_operations, parent, uid, prev, next, origin
# #

View File

@ -13,9 +13,11 @@ module.exports = ()->
# #
# @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created. # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.
# #
constructor: (custom_type, uid)-> constructor: (custom_type, uid, content, content_operations)->
@_map = {} @_map = {}
super custom_type, uid console.log("delete this ...")
this.constructed_with = [custom_type, content, content_operations] # debug!
super custom_type, uid, content, content_operations
type: "MapManager" type: "MapManager"
@ -83,8 +85,10 @@ module.exports = ()->
{ {
'uid' : uid 'uid' : uid
'custom_type' : custom_type 'custom_type' : custom_type
'content' : content
'content_operations' : content_operations
} = json } = json
new this(custom_type, uid) new this(custom_type, uid, content, content_operations)
@ -99,13 +103,13 @@ module.exports = ()->
# @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created. # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.
# @param {Delimiter} beginning Reference or Object. # @param {Delimiter} beginning Reference or Object.
# @param {Delimiter} end Reference or Object. # @param {Delimiter} end Reference or Object.
constructor: (custom_type, uid)-> constructor: (custom_type, uid, content, content_operations)->
@beginning = new ops.Delimiter undefined, undefined @beginning = new ops.Delimiter undefined, undefined
@end = new ops.Delimiter @beginning, undefined @end = new ops.Delimiter @beginning, undefined
@beginning.next_cl = @end @beginning.next_cl = @end
@beginning.execute() @beginning.execute()
@end.execute() @end.execute()
super custom_type, uid super custom_type, uid, content, content_operations
type: "ListManager" type: "ListManager"
@ -307,12 +311,10 @@ module.exports = ()->
{ {
'uid' : uid 'uid' : uid
'custom_type': custom_type 'custom_type': custom_type
'content' : content
'content_operations' : content_operations
} = json } = json
new this(custom_type, uid) new this(custom_type, uid, content, content_operations)
class ops.Composition extends ops.ListManager class ops.Composition extends ops.ListManager
@ -320,8 +322,6 @@ module.exports = ()->
# we can't use @seveOperation 'composition_ref', tmp_composition_ref here, # we can't use @seveOperation 'composition_ref', tmp_composition_ref here,
# because then there is a "loop" (insertion refers to parant, refers to insertion..) # because then there is a "loop" (insertion refers to parant, refers to insertion..)
# This is why we have to check in @callOperationSpecificInsertEvents until we find it # This is why we have to check in @callOperationSpecificInsertEvents until we find it
console.log("delete this ...")
this.constructed_with = [custom_type, @_composition_value, composition_value_operations, uid, tmp_composition_ref] # debug!
super custom_type, uid super custom_type, uid
if tmp_composition_ref? if tmp_composition_ref?
@tmp_composition_ref = tmp_composition_ref @tmp_composition_ref = tmp_composition_ref

File diff suppressed because one or more lines are too long

4
y.js

File diff suppressed because one or more lines are too long