r99055 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r99054‎ | r99055 | r99056 >
Date:21:25, 5 October 2011
Author:tparscal
Status:deferred
Tags:
Comment:
Added new transaction processing code (based on es/es.BlockTranscation)
Modified paths:
  • /trunk/parsers/wikidom/lib/hype/models/es.DocumentModel.js (modified) (history)

Diff [purge]

Index: trunk/parsers/wikidom/lib/hype/models/es.DocumentModel.js
@@ -67,6 +67,168 @@
6868 */
6969 es.DocumentModel.nodeModels = {};
7070
 71+/**
 72+ * Mapping of operation types to pure functions.
 73+ *
 74+ * Each function is called in the context of a state, and takes an operation object as a parameter.
 75+ */
 76+es.DocumentModel.operations = ( function() {
 77+ function retain( op ) {
 78+ annotate.call( this, this.cursor + op.length );
 79+ this.cursor += op.length;
 80+ };
 81+
 82+ function insert( op ) {
 83+ // Splice content into document in 1024 element chunks, as to not overflow max allowed
 84+ // arguments, which apply is limited by
 85+ var index = 0;
 86+ while ( index < op.data.length ) {
 87+ this.data.splice.apply(
 88+ this.data, [this.cursor, 0].concat( op.data.slice( index, index + 1024 ) )
 89+ );
 90+ index += 1024;
 91+ }
 92+ annotate.call( this, this.cursor + op.data.length );
 93+ this.cursor += op.data.length;
 94+ };
 95+
 96+ function remove( op ) {
 97+ this.data.splice( this.cursor, op.data.length );
 98+ };
 99+
 100+ function indexOfAnnotation( character, annotation ) {
 101+ if ( $.isArray( character ) ) {
 102+ // Find the index of a comparable annotation (checking for same value, not reference)
 103+ var index;
 104+ for ( var i = 0; i < target.length; i++ ) {
 105+ if ( es.compareObjects( target[i], op.annotation ) ) {
 106+ return index;
 107+ }
 108+ }
 109+ }
 110+ return -1;
 111+ }
 112+
 113+ function attribute( op, invert ) {
 114+ var element = this.data[this.cursor];
 115+ if ( element.type === undefined ) {
 116+ throw 'Invalid element error. Can not set attributes on non-element data.';
 117+ }
 118+ if ( op.method === 'set' || ( op.method === 'clear' && invert ) ) {
 119+ // Automatically initialize attributes object
 120+ if ( !element.attributes ) {
 121+ element.attributes = {};
 122+ }
 123+ element.attributes[op.name] = op.value;
 124+ } else if ( op.method === 'clear' || ( op.method === 'set' && invert ) ) {
 125+ if ( element.attributes ) {
 126+ delete element.attributes[op.name];
 127+ }
 128+ // Automatically clean up attributes object
 129+ var empty = true;
 130+ for ( key in element.attributes ) {
 131+ empty = false;
 132+ break;
 133+ }
 134+ if ( empty ) {
 135+ delete element.attributes;
 136+ }
 137+ } else {
 138+ throw 'Invalid method error. Can not operate attributes this way: ' + method;
 139+ }
 140+ };
 141+
 142+ function annotate( to ) {
 143+ // Handle annotations
 144+ if ( this.set.length ) {
 145+ for ( var i = 0, length = this.set.length; i < length; i++ ) {
 146+ var annotation = this.set[i];
 147+ for ( var j = this.cursor; j < to; j++ ) {
 148+ if ( $.isArray( this.data[j] ) ) {
 149+ this.data[j].push( annotation );
 150+ } else {
 151+ this.data[j] = [this.data[j], annotation];
 152+ }
 153+ }
 154+ }
 155+ }
 156+ if ( this.clear.length ) {
 157+ for ( var i = 0, length = this.clear.length; i < length; i++ ) {
 158+ var annotation = this.clear[i];
 159+ for ( var j = this.cursor; j < to; j++ ) {
 160+ var index = indexOfAnnotation( this.data[j], annotation );
 161+ if ( index !== -1 ) {
 162+ this.data[j].splice( index, 1 );
 163+ }
 164+ }
 165+ }
 166+ }
 167+ }
 168+
 169+ function mark( op, invert ) {
 170+ var target;
 171+ if ( op.method === 'set' || ( op.method === 'clear' && invert ) ) {
 172+ target = this.set;
 173+ } else if ( op.method === 'clear' || ( op.method === 'set' && invert ) ) {
 174+ target = this.clear;
 175+ } else {
 176+ throw 'Invalid method error. Can not operate attributes this way: ' + method;
 177+ }
 178+ if ( op.bias === 'start' ) {
 179+ target.push( op.annotation );
 180+ } else if ( op.bias === 'end' ) {
 181+ // Find the index of a comparable annotation (checking for same value, not reference)
 182+ var index;
 183+ for ( var i = 0; i < target.length; i++ ) {
 184+ if ( es.compareObjects( target[i], op.annotation ) ) {
 185+ index = i;
 186+ break;
 187+ }
 188+ }
 189+ if ( index === undefined ) {
 190+ throw 'Annotation stack error. Annotation is missing.';
 191+ }
 192+ target.splice( index, 1 );
 193+ }
 194+ };
 195+
 196+ return {
 197+ // Retain
 198+ 'retain': {
 199+ 'commit': retain,
 200+ 'rollback': retain
 201+ },
 202+ // Insert
 203+ 'insert': {
 204+ 'commit': insert,
 205+ 'rollback': remove
 206+ },
 207+ // Remove
 208+ 'remove': {
 209+ 'commit': remove,
 210+ 'rollback': insert
 211+ },
 212+ // Change element attributes
 213+ 'attribute': {
 214+ 'commit': function( op ) {
 215+ attribute( op, false );
 216+ },
 217+ 'rollback': function( op ) {
 218+ attribute( op, true );
 219+ }
 220+ },
 221+ // Change content annotations
 222+ 'annotate': {
 223+ 'commit': function( op ) {
 224+ mark( op, false );
 225+ },
 226+ 'rollback': function( op ) {
 227+ mark( op, true );
 228+ }
 229+ }
 230+ };
 231+} )();
 232+
71233 /* Static Methods */
72234
73235 /**
@@ -367,7 +529,20 @@
368530 * @param {es.Transaction}
369531 */
370532 es.DocumentModel.prototype.commit = function( transaction ) {
371 - //
 533+ var state = {
 534+ 'data': this.data,
 535+ 'cursor': 0,
 536+ 'set': [],
 537+ 'clear': []
 538+ };
 539+ for ( var i = 0, length = this.operations.length; i < length; i++ ) {
 540+ var op = this.operations[i];
 541+ if ( op.type in this.operations ) {
 542+ this.operations[op.type].commit.call( state, op );
 543+ } else {
 544+ throw 'Invalid operation error. Operation type is not supported: ' + op.type;
 545+ }
 546+ }
372547 };
373548
374549 /**
@@ -377,7 +552,20 @@
378553 * @param {es.Transaction}
379554 */
380555 es.DocumentModel.prototype.rollback = function( transaction ) {
381 - //
 556+ var state = {
 557+ 'data': this.data,
 558+ 'cursor': 0,
 559+ 'set': [],
 560+ 'clear': []
 561+ };
 562+ for ( var i = 0, length = this.operations.length; i < length; i++ ) {
 563+ var op = this.operations[i];
 564+ if ( op.type in this.operations ) {
 565+ this.operations[op.type].rollback.call( state, op );
 566+ } else {
 567+ throw 'Invalid operation error. Operation type is not supported: ' + op.type;
 568+ }
 569+ }
382570 };
383571
384572 /* Inheritance */

Status & tagging log