diff --git a/node/MessageHandler.js b/node/MessageHandler.js index 7fd27308..f17e9062 100644 --- a/node/MessageHandler.js +++ b/node/MessageHandler.js @@ -251,11 +251,11 @@ function handleUserChanges(client, message) //ex. adoptChangesetAttribs //Afaik, it copies the new attributes from the changeset, to the global Attribute Pool - changeset = Changeset.moveOpsToNewPool(changeset, wireApool, pad.pool()); + changeset = Changeset.moveOpsToNewPool(changeset, wireApool, pad.pool); //ex. applyUserChanges - var apool = pad.pool(); + var apool = pad.pool; var r = baseRev; while (r < pad.getHeadRevisionNumber()) { @@ -274,7 +274,7 @@ function handleUserChanges(client, message) pad.appendRevision(changeset, thisAuthor); - var correctionChangeset = _correctMarkersInPad(pad.atext(), pad.pool()); + var correctionChangeset = _correctMarkersInPad(pad.atext, pad.pool); if (correctionChangeset) { pad.appendRevision(correctionChangeset); } @@ -303,7 +303,7 @@ function handleUserChanges(client, message) } else { - var forWire = Changeset.prepareForWire(pad.getRevisionChangeset(r), pad.pool()); + var forWire = Changeset.prepareForWire(pad.getRevisionChangeset(r), pad.pool); var wireMsg = {"type":"COLLABROOM","data":{type:"NEW_CHANGES", newRev:r, changeset: forWire.translated, apool: forWire.pool, @@ -421,8 +421,8 @@ function handleClientReady(client, message) var pad = padManager.getPad(message.padId, false); //prepare all values for the wire - atext = pad.atext(); - var attribsForWire = Changeset.prepareForWire(atext.attribs, pad.pool()); + atext = pad.atext; + var attribsForWire = Changeset.prepareForWire(atext.attribs, pad.pool); var apool = attribsForWire.pool.toJsonable(); atext.attribs = attribsForWire.translated; diff --git a/node/Models/Pad.js b/node/Models/Pad.js new file mode 100644 index 00000000..3277157e --- /dev/null +++ b/node/Models/Pad.js @@ -0,0 +1,145 @@ +var Changeset = require("../Changeset"); +var AttributePoolFactory = require("../AttributePoolFactory"); + +exports.startText = "Welcome to Etherpad Lite. This pad text is synchronized as you type, so that everyone viewing this page sees the same text."; + +/** + * Copied from the Etherpad source code, don't know what its good for + * @param txt + */ +exports.cleanText = function (txt) { + return txt.replace(/\r\n/g,'\n').replace(/\r/g,'\n').replace(/\t/g, ' ').replace(/\xa0/g, ' '); +} + +Class('Pad', { + + // these are the properties + has : { + + atext : { + is : 'rw', // readwrite + init : function() { return Changeset.makeAText("\n"); } // first value + }, // atext + + pool : { + is: 'rw', + init : function() { return AttributePoolFactory.createAttributePool(); }, + getterName : 'apool' // legacy + }, // pool + + rev : { + is : 'rw', + init : [] + }, // rev + + head : { + is : 'rw', + init : -1, + getterName : 'getHeadRevisionNumber' + }, // head + + authors : { + is : 'rw', + init : [] + }, + + id : { is : 'rw' } + }, + + methods : { + + BUILD : function (id) + { + return { + 'id' : id, + } + }, + + appendRevision : function(aChangeset, author) + { + + if(!author) + author = ''; + + var newAText = Changeset.applyToAText(aChangeset, this.atext, this.pool); + Changeset.copyAText(newAText, this.atext); + + var newRev = ++this.head; + this.rev[newRev] = {}; + this.rev[newRev].changeset = aChangeset; + this.rev[newRev].meta = {}; + this.rev[newRev].meta.author = author; + this.rev[newRev].meta.timestamp = new Date().getTime(); + + //ex. getNumForAuthor + if(author != '') + this.pool.putAttrib(['author', author || '']); + + if(newRev % 100 == 0) + { + this.rev[newRev].meta.atext = this.atext; + } + + }, //appendRevision + + getRevisionChangeset : function(revNum) + { + + if(revNum < this.rev.length) + { + return this.rev[revNum].changeset; + } else { + throw 'this revision does not exist! : ' + revNum; + return null; + } + + }, // getRevisionChangeset + + getRevisionAuthor : function(revNum) + { + if(revNum < this.rev.length) + { + return this.rev[revNum].meta.author; + } else { + throw 'this revision author does not exist! : ' + revNum; + return null; + } + + }, // getRevisionAuthor + + getAllAuthors : function() + { + var authors = []; + + for(key in this.pool.numToAttrib) + { + if(this.pool.numToAttrib[key][0] == "author" && this.pool.numToAttrib[key][1] != "") + { + authors.push(this.pool.numToAttrib[key][1]); + } + } + + return authors; + }, + + text : function() + { + return this.atext.text; + } + + }, // methods + + + after : { + + initialize : function (props) + { + this.id = props.id; + + var firstChangeset = Changeset.makeSplice("\n", 0, 0, exports.cleanText(exports.startText)); + + this.appendRevision(firstChangeset, ''); + } + + } +}); diff --git a/node/PadManager.js b/node/PadManager.js index a87c19ca..3b257f25 100644 --- a/node/PadManager.js +++ b/node/PadManager.js @@ -19,13 +19,7 @@ The Pad Module trys to simulate the pad object from EtherPad. You can find the o see https://github.com/ether/pad/blob/master/etherpad/src/etherpad/pad/model.js */ -var Changeset = require("./Changeset"); -var AttributePoolFactory = require("./AttributePoolFactory"); - -/** - * The initial Text of a Pad - */ -exports.startText = "Welcome to Etherpad Lite. This pad text is synchronized as you type, so that everyone viewing this page sees the same text."; +var Changeset = require("./Models/Pad"); /** * A Array with all known Pads @@ -39,29 +33,20 @@ globalPads = []; */ exports.getPad = function(id, createIfNotExist) { - if(!globalPads[id] && createIfNotExist == true) + var pad = globalPads[id]; + + if(!pad && createIfNotExist == true) { - createPad(id); + pad = new Pad(id); + globalPads[id] = pad; + console.log(pad); } - if(!globalPads[id]) - return null; + if(!pad) return null; - globalPads[id].timestamp = new Date().getTime(); + //globalPads[id].timestamp = new Date().getTime(); - var functionWrapper = {}; - - functionWrapper.id = id; - functionWrapper.appendRevision = function (theChangeset, author) {return appendRevision(id, theChangeset, author)}; - functionWrapper.text = function () {return text(id)}; - functionWrapper.atext = function () {return atext(id)}; - functionWrapper.pool = function () {return pool(id)}; - functionWrapper.getHeadRevisionNumber = function () {return getHeadRevisionNumber(id)}; - functionWrapper.getRevisionChangeset = function (revNum) {return getRevisionChangeset(id, revNum)}; - functionWrapper.getRevisionAuthor = function (revNum) {return getRevisionAuthor(id, revNum)}; - functionWrapper.getAllAuthors = function () {return getAllAuthors(id)}; - - return functionWrapper; + return pad; } /** @@ -72,194 +57,6 @@ exports.ensurePadExists = function(id) { if(!globalPads[id]) { - createPad(id); + exports.getPad(id, true); } -} - -/** - * Creates an empty pad - * @param id The Pad id - */ -function createPad(id) -{ - var pad = {}; - globalPads[id] = pad; - - pad.id = id; - pad.rev = []; - pad.head = -1; - pad.atext = Changeset.makeAText("\n"); - pad.apool = AttributePoolFactory.createAttributePool(); - pad.authors = []; - - var firstChangeset = Changeset.makeSplice("\n", 0, 0, - exports.cleanText(exports.startText)); - appendRevision(id, firstChangeset, ''); -} - -/** - * Append a changeset to a pad - * @param id The Pad id - * @param theChangeset the changeset which should apply to the text - * @param The author of the revision, can be null - */ -function appendRevision(id, theChangeset, author) -{ - throwExceptionIfPadDontExist(id); - - if(!author) - author = ''; - - var atext = globalPads[id].atext; - var apool = globalPads[id].apool; - var newAText = Changeset.applyToAText(theChangeset, atext, apool); - Changeset.copyAText(newAText, atext); - - var newRev = ++globalPads[id].head; - globalPads[id].rev[newRev] = {}; - globalPads[id].rev[newRev].changeset = theChangeset; - globalPads[id].rev[newRev].meta = {}; - globalPads[id].rev[newRev].meta.author = author; - globalPads[id].rev[newRev].meta.timestamp = new Date().getTime(); - - //ex. getNumForAuthor - if(author != '') - apool.putAttrib(['author',author||'']); - - if(newRev%100==0) - { - globalPads[id].rev[newRev].meta.atext=atext; - } -} - -/** - * Returns all Authors of a Pad - * @param id The Pad id - */ -function getAllAuthors(id) -{ - var authors = []; - - for(key in globalPads[id].apool.numToAttrib) - { - if(globalPads[id].apool.numToAttrib[key][0] == "author" && globalPads[id].apool.numToAttrib[key][1] != "") - { - authors.push(globalPads[id].apool.numToAttrib[key][1]); - } - } - - return authors; -} - -/** - * Returns the plain text of a pad - * @param id The Pad id - */ - -function text(id) -{ - throwExceptionIfPadDontExist(id); - - return globalPads[id].atext.text; -} - -/** - * Returns the Attributed Text of a pad - * @param id The Pad id - */ -function atext(id) -{ - throwExceptionIfPadDontExist(id); - - return globalPads[id].atext; -} - -/** - * Returns the Attribute Pool whichs the Pad is using - * @param id The Pad id - */ -function pool(id) -{ - throwExceptionIfPadDontExist(id); - - return globalPads[id].apool; -} - -/** - * Returns the latest Revision Number of the Pad - * @param id The Pad id - */ -function getHeadRevisionNumber(id) -{ - throwExceptionIfPadDontExist(id); - - return globalPads[id].head; -} - -/** - * Returns the changeset of a specific revision - * @param id The Pad id - * @param revNum The Revision Number - */ -function getRevisionChangeset(id, revNum) -{ - throwExceptionIfPadDontExist(id); - throwExceptionIfRevDontExist(id, revNum); - - return globalPads[id].rev[revNum].changeset; -} - -/** - * Returns the author of a specific revision - * @param id The Pad id - * @param revNum The Revision Number - */ -function getRevisionAuthor(id, revNum) -{ - throwExceptionIfPadDontExist(id); - throwExceptionIfRevDontExist(id, revNum); - - return globalPads[id].rev[revNum].meta.author; -} - -/** - * Check if the ID is a valid Pad ID and trows an Exeption if not - * @param id The Pad id - */ -function throwExceptionIfPadDontExist(id) -{ - if(id == null) - { - throw "Padname is null!"; - } - if(!globalPads[id]) - { - throw "Pad don't exist!'"; - } -} - -/** - * Check if the Revision of a Pad is valid and throws an Exeption if not - * @param id The Pad id - */ -function throwExceptionIfRevDontExist(id, revNum) -{ - if(revNum == null) - throw "revNum is null"; - - if((typeof revNum) != "number") - throw revNum + " is no Number"; - - if(revNum < 0 || revNum > globalPads[id].head) - throw "The Revision " + revNum + " don't exist'"; -} - -/** - * Copied from the Etherpad source code, don't know what its good for - * @param txt - */ -exports.cleanText = function (txt) { - return txt.replace(/\r\n/g,'\n').replace(/\r/g,'\n').replace(/\t/g, ' ').replace(/\xa0/g, ' '); -} - - +} \ No newline at end of file diff --git a/node/server.js b/node/server.js index 1787cd64..14e35d9f 100644 --- a/node/server.js +++ b/node/server.js @@ -23,6 +23,8 @@ var http = require('http') , db = require('./db') , async = require('async'); +require('joose'); + async.waterfall([ function (callback) { diff --git a/tests/PadManager_tests.js b/tests/PadManager_tests.js index 76f65ea6..791af421 100644 --- a/tests/PadManager_tests.js +++ b/tests/PadManager_tests.js @@ -16,11 +16,11 @@ exports.createAPad = function(test) test.equal(pad.id, "test", "The PadManager gave a pad with a other id than expeted"); //Test if the startText is correct set - var atext = pad.atext(); + var atext = pad.atext; test.equal(atext.text, padManager.startText + "\n", "The Starttext of a Pad is wrong set"); //Test if the atext().text and text() is the same - test.equal(atext.text, pad.text(), "pad.atext().text is not pad.text()"); + test.equal(atext.text, pad.text(), "pad.atext.text is not pad.text()"); //Test if the Revision Number is Zero var head = pad.getHeadRevisionNumber();