refs, complex saveOperation' and validateSavedOperations`
This commit is contained in:
@@ -182,7 +182,7 @@ module.exports = ()->
|
||||
# @param {String} name The name of the operation. After calling this function op is accessible via this[name].
|
||||
# @param {Operation} op An Operation object
|
||||
#
|
||||
saveOperation: (name, op)->
|
||||
saveOperation: (name, op, base = "this")->
|
||||
|
||||
#
|
||||
# Every instance of $Operation must have an $execute function.
|
||||
@@ -194,11 +194,20 @@ module.exports = ()->
|
||||
else if op.execute? or not (op.op_number? and op.creator?)
|
||||
# is instantiated, or op is string. Currently "Delimiter" is saved as string
|
||||
# (in combination with @parent you can retrieve the delimiter..)
|
||||
@[name] = op
|
||||
if base is "this"
|
||||
@[name] = op
|
||||
else
|
||||
dest = @[base]
|
||||
paths = name.split("/")
|
||||
last_path = paths.pop()
|
||||
for path in paths
|
||||
dest = dest[path]
|
||||
dest[last_path] = op
|
||||
else
|
||||
# not initialized. Do it when calling $validateSavedOperations()
|
||||
@unchecked ?= {}
|
||||
@unchecked[name] = op
|
||||
@unchecked[base] ?= {}
|
||||
@unchecked[base][name] = op
|
||||
|
||||
#
|
||||
# @private
|
||||
@@ -210,13 +219,23 @@ module.exports = ()->
|
||||
validateSavedOperations: ()->
|
||||
uninstantiated = {}
|
||||
success = @
|
||||
for name, op_uid of @unchecked
|
||||
op = @HB.getOperation op_uid
|
||||
if op
|
||||
@[name] = op
|
||||
else
|
||||
uninstantiated[name] = op_uid
|
||||
success = false
|
||||
for base_name, base of @unchecked
|
||||
for name, op_uid of base
|
||||
op = @HB.getOperation op_uid
|
||||
if op
|
||||
if base_name is "this"
|
||||
@[name] = op
|
||||
else
|
||||
dest = @[base_name]
|
||||
paths = name.split("/")
|
||||
last_path = paths.pop()
|
||||
for path in paths
|
||||
dest = dest[path]
|
||||
dest[last_path] = op
|
||||
else
|
||||
uninstantiated[base_name] ?= {}
|
||||
uninstantiated[base_name][name] = op_uid
|
||||
success = false
|
||||
delete @unchecked
|
||||
if not success
|
||||
@unchecked = uninstantiated
|
||||
@@ -305,7 +324,7 @@ module.exports = ()->
|
||||
# @param {Operation} prev_cl The predecessor 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, 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
|
||||
@@ -313,6 +332,10 @@ module.exports = ()->
|
||||
@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 'prev_cl', prev_cl
|
||||
@saveOperation 'next_cl', next_cl
|
||||
@@ -325,8 +348,19 @@ module.exports = ()->
|
||||
type: "Insert"
|
||||
|
||||
val: ()->
|
||||
if @content? and @content.getCustomType?
|
||||
@content.getCustomType()
|
||||
if @content?
|
||||
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
|
||||
|
||||
@@ -518,14 +552,20 @@ module.exports = ()->
|
||||
json.parent = @parent.getUid()
|
||||
|
||||
if @content?.getUid?
|
||||
json['content'] = @content.getUid()
|
||||
json.content = @content.getUid()
|
||||
else
|
||||
json['content'] = JSON.stringify @content
|
||||
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
|
||||
|
||||
ops.Insert.parse = (json)->
|
||||
{
|
||||
'content' : content
|
||||
'content_operations' : content_operations
|
||||
'uid' : uid
|
||||
'prev': prev
|
||||
'next': next
|
||||
@@ -534,7 +574,7 @@ module.exports = ()->
|
||||
} = json
|
||||
if typeof content is "string"
|
||||
content = JSON.parse(content)
|
||||
new this null, content, parent, uid, prev, next, origin
|
||||
new this null, content, content_operations, parent, uid, prev, next, origin
|
||||
|
||||
#
|
||||
# @nodoc
|
||||
|
||||
@@ -238,12 +238,12 @@ module.exports = ()->
|
||||
|
||||
# TODO: always expect an array as content. Then you can combine this with the other option (else)
|
||||
if contents instanceof ops.Operation
|
||||
(new ops.Insert null, content, undefined, undefined, left, right).execute()
|
||||
(new ops.Insert null, content, null, undefined, undefined, left, right).execute()
|
||||
else
|
||||
for c in contents
|
||||
if c? and c._name? and c._getModel?
|
||||
c = c._getModel(@custom_types, @operations)
|
||||
tmp = (new ops.Insert null, c, undefined, undefined, left, right).execute()
|
||||
tmp = (new ops.Insert null, c, null, undefined, undefined, left, right).execute()
|
||||
left = tmp
|
||||
@
|
||||
|
||||
@@ -290,7 +290,7 @@ module.exports = ()->
|
||||
position: op.getPosition()
|
||||
object: @getCustomType()
|
||||
changedBy: op.uid.creator
|
||||
value: getContentType op.content
|
||||
value: getContentType op.val()
|
||||
]
|
||||
|
||||
callOperationSpecificDeleteEvents: (op, del_op)->
|
||||
@@ -316,31 +316,60 @@ module.exports = ()->
|
||||
|
||||
class ops.Composition extends ops.ListManager
|
||||
|
||||
constructor: (custom_type, @composition_value, uid, composition_ref)->
|
||||
constructor: (custom_type, @_composition_value, composition_value_operations, uid, tmp_composition_ref)->
|
||||
# we can't use @seveOperation 'composition_ref', tmp_composition_ref here,
|
||||
# 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
|
||||
console.log("delete this ...")
|
||||
this.constructed_with = [custom_type, @_composition_value, composition_value_operations, uid, tmp_composition_ref] # debug!
|
||||
super custom_type, uid
|
||||
if composition_ref
|
||||
@saveOperation 'composition_ref', composition_ref
|
||||
if tmp_composition_ref?
|
||||
@tmp_composition_ref = tmp_composition_ref
|
||||
else
|
||||
@composition_ref = @beginning
|
||||
@composition_ref = @end.prev_cl
|
||||
if composition_value_operations?
|
||||
@composition_value_operations = {}
|
||||
for n,o of composition_value_operations
|
||||
@saveOperation n, o, '_composition_value'
|
||||
|
||||
type: "Composition"
|
||||
|
||||
val: ()->
|
||||
@composition_value
|
||||
#
|
||||
# @private
|
||||
# @see Operation.execute
|
||||
#
|
||||
execute: ()->
|
||||
if @validateSavedOperations()
|
||||
@getCustomType()._setCompositionValue @_composition_value
|
||||
delete @_composition_value
|
||||
super
|
||||
else
|
||||
false
|
||||
|
||||
#
|
||||
# This is called, when the Insert-operation was successfully executed.
|
||||
#
|
||||
callOperationSpecificInsertEvents: (op)->
|
||||
if @tmp_composition_ref?
|
||||
if op.uid.creator is @tmp_composition_ref.creator and op.uid.op_number is @tmp_composition_ref.op_number
|
||||
@composition_ref = op
|
||||
delete @tmp_composition_ref
|
||||
o = op.next_cl
|
||||
while o.next_cl?
|
||||
if not o.isDeleted()
|
||||
@callOperationSpecificInsertEvents o
|
||||
o = o.next_cl
|
||||
return
|
||||
|
||||
if @composition_ref.next_cl is op
|
||||
op.undo_delta = @getCustomType()._apply op.content
|
||||
op.undo_delta = @getCustomType()._apply op.val()
|
||||
else
|
||||
o = @end.prev_cl
|
||||
while o isnt op
|
||||
@getCustomType()._unapply o.undo_delta
|
||||
o = o.prev_cl
|
||||
while o isnt @end
|
||||
o.undo_delta = @getCustomType()._apply o.content
|
||||
o.undo_delta = @getCustomType()._apply o.val()
|
||||
o = o.next_cl
|
||||
@composition_ref = @end.prev_cl
|
||||
|
||||
@@ -361,16 +390,24 @@ module.exports = ()->
|
||||
#
|
||||
# @param delta The delta that is applied to the composition_value
|
||||
#
|
||||
applyDelta: (delta)->
|
||||
(new ops.Insert null, delta, @, null, @end.prev_cl, @end).execute()
|
||||
applyDelta: (delta, operations)->
|
||||
(new ops.Insert null, delta, operations, @, null, @end.prev_cl, @end).execute()
|
||||
undefined
|
||||
|
||||
#
|
||||
# Encode this operation in such a way that it can be parsed by remote peers.
|
||||
#
|
||||
_encode: (json = {})->
|
||||
json.composition_value = JSON.stringify @composition_value
|
||||
json.composition_ref = @composition_ref.getUid()
|
||||
custom = @getCustomType()._getCompositionValue()
|
||||
json.composition_value = custom.composition_value
|
||||
if custom.composition_value_operations?
|
||||
json.composition_value_operations = {}
|
||||
for n,o of custom.composition_value_operations
|
||||
json.composition_value_operations[n] = o.getUid()
|
||||
if @composition_ref?
|
||||
json.composition_ref = @composition_ref.getUid()
|
||||
else
|
||||
json.composition_ref = @tmp_composition_ref
|
||||
super json
|
||||
|
||||
ops.Composition.parse = (json)->
|
||||
@@ -378,9 +415,10 @@ module.exports = ()->
|
||||
'uid' : uid
|
||||
'custom_type': custom_type
|
||||
'composition_value' : composition_value
|
||||
'composition_value_operations' : composition_value_operations
|
||||
'composition_ref' : composition_ref
|
||||
} = json
|
||||
new this(custom_type, JSON.parse(composition_value), uid, composition_ref)
|
||||
new this(custom_type, composition_value, composition_value_operations, uid, composition_ref)
|
||||
|
||||
|
||||
#
|
||||
@@ -465,7 +503,7 @@ module.exports = ()->
|
||||
#
|
||||
replace: (content, replaceable_uid)->
|
||||
o = @getLastOperation()
|
||||
relp = (new ops.Insert null, content, @, replaceable_uid, o, o.next_cl).execute()
|
||||
relp = (new ops.Insert null, content, null, @, replaceable_uid, o, o.next_cl).execute()
|
||||
# TODO: delete repl (for debugging)
|
||||
undefined
|
||||
|
||||
|
||||
Reference in New Issue
Block a user