Commit 39836f9f authored by Tristan Cavelier's avatar Tristan Cavelier Committed by Sebastien Robin

We can give a parameter to Jio to not store job queue in localStorage.

New class on jio.js, it permit to make easier storage development.
Add one test.
parent e74f4914
...@@ -2,19 +2,42 @@ ...@@ -2,19 +2,42 @@
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>JIO QUnit/Sinon Test</title> <title>Test</title>
<link rel="stylesheet" href="qunit/qunit-1.5.0.css" /> <link rel="stylesheet" href="qunit/qunit-1.5.0.css" />
</head> </head>
<body> <body>
<div id="qunit"></div>
<script type="text/javascript" src="js/jquery/jquery.js"></script> <script type="text/javascript" src="js/jquery/jquery.js"></script>
<script type="text/javascript" src="unhosted/localorcookiestorage.js"></script> <script type="text/javascript" src="unhosted/localorcookiestorage.js"></script>
<script type="text/javascript" src="unhosted/jio.js"></script> <script type="text/javascript" src="unhosted/jio.js"></script>
<!-- <script type="text/javascript" src="unhosted/base64.js"></script> --> <script type="text/javascript" src="unhosted/base64.js"></script>
<script type="text/javascript" src="unhosted/jio.storage.js"></script> <script type="text/javascript" src="unhosted/jio.storage.js"></script>
<script type="text/javascript"> <script type="text/javascript">
<!-- <!--
var j = JIO.createNew(); var mammal = function (description) {
this.caracteristics = description;
};
mammal.prototype = {
createMammal: function () {
// c'est un chat alors
var mycat = new cat(this.caracteristics);
var t = this;
mycat.say = function () { return t.caracteristics.say; };
mycat.name = function () { return t.caracteristics.name; };
return mycat;
}
};
var cat = function (detaileddescription) {
// (...)
};
cat.prototype = {
talk: function () {
alert('My name is ' + this.name() + ', ' + this.say());
}
};
var mam = new mammal({'say':'meow','name':'nyancat'});
var mycat = mam.createMammal();
mycat.talk();
//--> //-->
</script> </script>
</body> </body>
......
...@@ -21,89 +21,63 @@ ...@@ -21,89 +21,63 @@
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// Dummy Storage 1 : all ok // Dummy Storage 1 : all ok
var DummyStorageAllOk = function ( options ) { var DummyStorageAllOk = function ( args ) {
this.job = args.job;
}; };
DummyStorageAllOk.prototype = { DummyStorageAllOk.prototype = {
checkNameAvailability: function ( job , jobendcallback) { checkNameAvailability: function () {
// The [job.userName] IS available. // The [job.userName] IS available.
// job: the job object
// job.userName: the name we want to check.
// jobendcallback : the function called at the end of the job.
// returns {'status':string,'message':string,'isAvailable':boolean} var t = this;
// in the jobendcallback arguments.
// wait a little in order to simulate asynchronous operation // wait a little in order to simulate asynchronous operation
setTimeout(function () { setTimeout(function () {
job.status = 'done'; t.done(true);
jobendcallback(job);
job.callback({'status':'done',
'message':''+job.userName+' is available.',
'isAvailable':true});
}, 100); }, 100);
}, // end userNameAvailable }, // end userNameAvailable
saveDocument: function ( job, jobendcallback ) { saveDocument: function () {
// Tells us that the document is saved. // Tells us that the document is saved.
// job : the job object
// job.options : the save options object
// jobendcallback : the function called at the end of the job.
// returns {'status':string,'message':string,'isSaved':boolean} var t = this;
// in the jobendcallback arguments.
// wait a little in order to simulate asynchronous saving // wait a little in order to simulate asynchronous saving
setTimeout (function () { setTimeout (function () {
var res = {}; t.done();
res.status = job.status = 'done';
res.message = 'Document saved.';
res.isSaved = true;
jobendcallback(job);
job.callback(res);
}, 100); }, 100);
}, // end saveDocument }, // end saveDocument
loadDocument: function ( job, jobendcallback ) { loadDocument: function () {
// Returns a document object containing all information of the // Returns a document object containing all information of the
// document and its content. // document and its content.
// job : the job object
// job.fileName : the document name we want to load.
// jobendcallback : the function called at the end of the job.
// returns {'status':string,'message':string,'document':object}
// in the jobendcallback arguments.
// document object is {'fileName':string,'fileContent':string, // document object is {'fileName':string,'fileContent':string,
// 'creationDate':date,'lastModified':date} // 'creationDate':date,'lastModified':date}
var t = this;
// wait a little in order to simulate asynchronous operation // wait a little in order to simulate asynchronous operation
setTimeout(function () { setTimeout(function () {
var res = {}; var doc = {
res.status = job.status = 'done';
res.message = 'Document loaded.';
res.document = {
'fileContent': 'content', 'fileContent': 'content',
'fileName': 'file', 'fileName': 'file',
'creationDate': 10000, 'creationDate': 10000,
'lastModified': 15000}; 'lastModified': 15000};
jobendcallback(job); t.done(doc);
job.callback(res);
}, 100); }, 100);
}, // end loadDocument }, // end loadDocument
getDocumentList: function ( job, jobendcallback) { getDocumentList: function () {
// It returns a document array containing all the user documents // It returns a document array containing all the user documents
// informations, but not their content. // informations, but not their content.
// job : the job object
// jobendcallback : the function called at the end of the job.
// returns {'status':string,'message':string,'list':array}
// in the jobendcallback arguments.
// the list is [object,object] -> object = {'fileName':string, // the list is [object,object] -> object = {'fileName':string,
// 'lastModified':date,'creationDate':date} // 'lastModified':date,'creationDate':date}
var t = this;
setTimeout(function () { setTimeout(function () {
var res = {}; var list = [
res.list = [
{'fileName':'file', {'fileName':'file',
'creationDate':10000, 'creationDate':10000,
'lastModified':15000}, 'lastModified':15000},
...@@ -111,28 +85,17 @@ ...@@ -111,28 +85,17 @@
'creationDate':20000, 'creationDate':20000,
'lastModified':25000 'lastModified':25000
}]; }];
res.status = job.status = 'done'; t.done(list);
res.message = 'List received.';
jobendcallback(job);
job.callback(res);
}, 100); }, 100);
}, // end getDocumentList }, // end getDocumentList
removeDocument: function ( job, jobendcallback ) { removeDocument: function () {
// Remove a document from the storage. // Remove a document from the storage.
// job : the job object
// jobendcallback : the function called at the end of the job.
// returns {'status':string,'message':string,'isRemoved':boolean} var t = this;
// in the jobendcallback arguments.
setTimeout (function () { setTimeout (function () {
var res = {}; t.done();
res.status = job.status = 'done';
res.message = 'Document removed.';
res.isRemoved = true;
jobendcallback(job);
job.callback(res);
}, 100); }, 100);
} }
}; };
...@@ -141,113 +104,74 @@ ...@@ -141,113 +104,74 @@
Jio.addStorageType('dummyallok', function (options) { Jio.addStorageType('dummyallok', function (options) {
return new DummyStorageAllOk(options); return new DummyStorageAllOk(options);
}); });
// end Dummy Storage All Ok // end Dummy Storage All Ok
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// Dummy Storage 2 : all fail // Dummy Storage 2 : all fail
var DummyStorageAllFail = function ( options ) { var DummyStorageAllFail = function ( args ) {
this.job = args.job;
}; };
DummyStorageAllFail.prototype = { DummyStorageAllFail.prototype = {
checkNameAvailability: function ( job , jobendcallback) { checkNameAvailability: function () {
// Fails to check [job.userName]. // Fails to check [job.userName].
// job: the job object
// job.userName: the name we want to check.
// jobendcallback : the function called at the end of the job.
// returns {'status':string,'message':string,'isAvailable':boolean} var t = this;
// in the jobendcallback arguments.
// wait a little in order to simulate asynchronous operation // wait a little in order to simulate asynchronous operation
setTimeout(function () { setTimeout(function () {
job.status = 'fail'; t.fail('Cannot check name availability.',0);
jobendcallback(job);
job.callback({'status':'fail',
'message':'Cannot check name availability',
'isAvailable':false});
}, 100); }, 100);
}, // end userNameAvailable }, // end userNameAvailable
saveDocument: function ( job, jobendcallback ) { saveDocument: function () {
// Tells us that the document is not saved. // Tells us that the document is not saved.
// job : the job object
// job.options : the save options object
// jobendcallback : the function called at the end of the job.
// returns {'status':string,'message':string,'isSaved':boolean} var t = this;
// in the jobendcallback arguments.
// wait a little in order to simulate asynchronous saving // wait a little in order to simulate asynchronous saving
setTimeout (function () { setTimeout (function () {
var res = {}; t.fail('Unable to save document.',0);
res.status = job.status = 'fail';
res.message = 'Unable to save document.';
res.errno = 0;
res.isSaved = false;
jobendcallback(job);
job.callback(res);
}, 100); }, 100);
}, // end saveDocument }, // end saveDocument
loadDocument: function ( job, jobendcallback ) { loadDocument: function () {
// Returns a document object containing nothing. // Returns a document object containing nothing.
// job : the job object
// job.fileName : the document name we want to load.
// jobendcallback : the function called at the end of the job.
// returns {'status':string,'message':string,'document':object}
// in the jobendcallback arguments.
// document object is {'fileName':string,'fileContent':string, // document object is {'fileName':string,'fileContent':string,
// 'creationDate':date,'lastModified':date} // 'creationDate':date,'lastModified':date}
var t = this;
// wait a little in order to simulate asynchronous operation // wait a little in order to simulate asynchronous operation
setTimeout(function () { setTimeout(function () {
var res = {}; t.fail('Unable to load document.',0);
res.status = job.status = 'fail';
res.message = 'Unable to load document.';
res.errno = 0;
res.document = {};
jobendcallback(job);
job.callback(res);
}, 100); }, 100);
}, // end loadDocument }, // end loadDocument
getDocumentList: function ( job, jobendcallback) { getDocumentList: function () {
// It returns nothing. // It returns nothing.
// job : the job object
// jobendcallback : the function called at the end of the job.
// returns {'status':string,'message':string,'list':array}
// in the jobendcallback arguments.
// the list is [object,object] -> object = {'fileName':string, // the list is [object,object] -> object = {'fileName':string,
// 'lastModified':date,'creationDate':date} // 'lastModified':date,'creationDate':date}
var t = this;
setTimeout(function () { setTimeout(function () {
var res = {}; t.fail('Cannot get document list.',0);
res.status = job.status = 'fail';
res.message = 'Cannot get document list.';
res.errno = 0;
jobendcallback(job);
job.callback(res);
}, 100); }, 100);
}, // end getDocumentList }, // end getDocumentList
removeDocument: function ( job, jobendcallback ) { removeDocument: function ( job, jobendcallback ) {
// Remove a document from the storage. // Remove a document from the storage.
// job : the job object
// jobendcallback : the function called at the end of the job.
// returns {'status':string,'message':string,'isRemoved':boolean} // returns {'status':string,'message':string,'isRemoved':boolean}
// in the jobendcallback arguments. // in the jobendcallback arguments.
var t = this;
setTimeout (function () { setTimeout (function () {
var res = {}; t.fail('Unable to remove anything.',0);
res.status = job.status = 'fail';
res.message = 'Unable to remove anything.';
res.isRemoved = false;
jobendcallback(job);
job.callback(res);
}, 100); }, 100);
} }
}; };
...@@ -262,106 +186,69 @@ ...@@ -262,106 +186,69 @@
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// Dummy Storage 3 : all not found // Dummy Storage 3 : all not found
var DummyStorageAllNotFound = function ( options ) { var DummyStorageAllNotFound = function ( args ) {
this.job = args.job;
}; };
DummyStorageAllNotFound.prototype = { DummyStorageAllNotFound.prototype = {
checkNameAvailability: function ( job , jobendcallback) { checkNameAvailability: function () {
// [job.userName] not found, so the name is available. // [job.userName] not found, so the name is available.
// job: the job object
// job.userName: the name we want to check.
// jobendcallback : the function called at the end of the job.
// returns {'status':string,'message':string,'isAvailable':boolean} var t = this;
// in the jobendcallback arguments.
// wait a little in order to simulate asynchronous operation // wait a little in order to simulate asynchronous operation
setTimeout(function () { setTimeout(function () {
job.status = 'done'; t.done(true);
jobendcallback(job);
job.callback({'status':'done',
'message':''+job.userName+' is available.',
'isAvailable':true});
}, 100); }, 100);
}, // end userNameAvailable }, // end userNameAvailable
saveDocument: function ( job, jobendcallback ) { saveDocument: function () {
// Document does not exists yet, create it. // Document does not exists yet, create it.
// job : the job object
// job.options : the save options object
// jobendcallback : the function called at the end of the job.
// returns {'status':string,'message':string,'isSaved':boolean} var t = this;
// in the jobendcallback arguments.
// wait a little in order to simulate asynchronous saving // wait a little in order to simulate asynchronous saving
setTimeout (function () { setTimeout (function () {
var res = {}; t.done();
res.status = job.status = 'done';
res.message = 'Document saved.';
res.isSaved = true;
jobendcallback(job);
job.callback(res);
}, 100); }, 100);
}, // end saveDocument }, // end saveDocument
loadDocument: function ( job, jobendcallback ) { loadDocument: function ( job, jobendcallback ) {
// Returns a document object containing nothing. // Returns a document object containing nothing.
// job : the job object
// job.fileName : the document name we want to load.
// jobendcallback : the function called at the end of the job.
// returns {'status':string,'message':string,'document':object}
// in the jobendcallback arguments.
// document object is {'fileName':string,'fileContent':string, // document object is {'fileName':string,'fileContent':string,
// 'creationDate':date,'lastModified':date} // 'creationDate':date,'lastModified':date}
var t = this;
// wait a little in order to simulate asynchronous operation // wait a little in order to simulate asynchronous operation
setTimeout(function () { setTimeout(function () {
var res = {}; t.fail('Document not found.',404);
res.status = job.status = 'fail';
res.message = 'Document not found.';
res.errno = 404;
res.document = {};
jobendcallback(job);
job.callback(res);
}, 100); }, 100);
}, // end loadDocument }, // end loadDocument
getDocumentList: function ( job, jobendcallback) { getDocumentList: function ( job, jobendcallback) {
// It returns nothing. // It returns nothing.
// job : the job object
// jobendcallback : the function called at the end of the job.
// returns {'status':string,'message':string,'list':array}
// in the jobendcallback arguments.
// the list is [object,object] -> object = {'fileName':string, // the list is [object,object] -> object = {'fileName':string,
// 'lastModified':date,'creationDate':date} // 'lastModified':date,'creationDate':date}
var t = this;
setTimeout(function () { setTimeout(function () {
var res = {}; t.fail('User collection not found.',404);
res.status = job.status = 'fail';
res.message = 'User collection not found.';
res.errno = 404;
jobendcallback(job);
job.callback(res);
}, 100); }, 100);
}, // end getDocumentList }, // end getDocumentList
removeDocument: function ( job, jobendcallback ) { removeDocument: function ( job, jobendcallback ) {
// Remove a document from the storage. // Remove a document from the storage.
// job : the job object
// jobendcallback : the function called at the end of the job.
// returns {'status':string,'message':string,'isRemoved':boolean} // returns {'status':string,'message':string,'isRemoved':boolean}
// in the jobendcallback arguments. // in the jobendcallback arguments.
var t = this;
setTimeout (function () { setTimeout (function () {
var res = {}; t.done();
res.status = job.status = 'done';
res.message = 'Document already removed.';
res.isRemoved = true;
jobendcallback(job);
job.callback(res);
}, 100); }, 100);
} }
}; };
...@@ -374,4 +261,81 @@ ...@@ -374,4 +261,81 @@
// end Dummy Storage All Not Found // end Dummy Storage All Not Found
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
// Dummy Storage 4 : all 3 tries
var DummyStorageAll3Tries = function ( args ) {
this.job = args.job;
};
DummyStorageAllNotFound.prototype = {
checkNameAvailability: function () {
// [job.userName] not found, so the name is available.
var t = this;
// wait a little in order to simulate asynchronous operation
setTimeout(function () {
t.done(true);
}, 100);
}, // end userNameAvailable
saveDocument: function () {
// Document does not exists yet, create it.
var t = this;
// wait a little in order to simulate asynchronous saving
setTimeout (function () {
t.done();
}, 100);
}, // end saveDocument
loadDocument: function () {
// Returns a document object containing nothing.
// document object is {'fileName':string,'fileContent':string,
// 'creationDate':date,'lastModified':date}
var t = this;
// wait a little in order to simulate asynchronous operation
setTimeout(function () {
t.fail('Document not found.',404);
}, 100);
}, // end loadDocument
getDocumentList: function () {
// It returns nothing.
// the list is [object,object] -> object = {'fileName':string,
// 'lastModified':date,'creationDate':date}
var t = this;
setTimeout(function () {
t.fail('User collection not found.',404);
}, 100);
}, // end getDocumentList
removeDocument: function () {
// Remove a document from the storage.
// returns {'status':string,'message':string,'isRemoved':boolean}
// in the jobendcallback arguments.
var t = this;
setTimeout (function () {
t.done();
}, 100);
}
};
// add key to storageObjectType of global jio
Jio.addStorageType('dummyall3tries', function (options) {
return new DummyStorageAll3Tries(options);
});
// end Dummy Storage All 3 Tries
////////////////////////////////////////////////////////////////////////////
})( JIO ); })( JIO );
...@@ -87,7 +87,8 @@ test ('All tests', function () { ...@@ -87,7 +87,8 @@ test ('All tests', function () {
deepEqual (result[retmethod],value,message);}; deepEqual (result[retmethod],value,message);};
t.spy(o,'f'); t.spy(o,'f');
o.jio[method]({'userName':'Dummy','fileName':'file', o.jio[method]({'userName':'Dummy','fileName':'file',
'fileContent':'content','callback':o.f}); 'fileContent':'content','callback':o.f,
'maxtries':1});
clock.tick(510); clock.tick(510);
if (!o.f.calledOnce) if (!o.f.calledOnce)
ok(false, 'no response / too much results'); ok(false, 'no response / too much results');
...@@ -114,7 +115,7 @@ test ('All tests', function () { ...@@ -114,7 +115,7 @@ test ('All tests', function () {
'isAvailable',false); 'isAvailable',false);
mytest('save document FAIL','saveDocument','isSaved',false); mytest('save document FAIL','saveDocument','isSaved',false);
mytest('load document FAIL','loadDocument','document',{}); mytest('load document FAIL','loadDocument','document',{});
mytest('get document list FAIL','getDocumentList','list',undefined); mytest('get document list FAIL','getDocumentList','list',[]);
mytest('remove document FAIL','removeDocument','isRemoved',false); mytest('remove document FAIL','removeDocument','isRemoved',false);
o.jio.stop(); o.jio.stop();
...@@ -125,7 +126,7 @@ test ('All tests', function () { ...@@ -125,7 +126,7 @@ test ('All tests', function () {
'isAvailable',true); 'isAvailable',true);
mytest('save document NOT FOUND','saveDocument','isSaved',true); mytest('save document NOT FOUND','saveDocument','isSaved',true);
mytest('load document NOT FOUND','loadDocument','document',{}); mytest('load document NOT FOUND','loadDocument','document',{});
mytest('get document list NOT FOUND','getDocumentList','list',undefined); mytest('get document list NOT FOUND','getDocumentList','list',[]);
mytest('remove document NOT FOUND','removeDocument','isRemoved',true); mytest('remove document NOT FOUND','removeDocument','isRemoved',true);
o.jio.stop(); o.jio.stop();
}); });
...@@ -140,35 +141,40 @@ test ('Simple Job Elimination', function () { ...@@ -140,35 +141,40 @@ test ('Simple Job Elimination', function () {
{'ID':'jiotests'}); {'ID':'jiotests'});
id = o.jio.id; id = o.jio.id;
o.jio.saveDocument({'fileName':'file','fileContent':'content', o.jio.saveDocument({'fileName':'file','fileContent':'content',
'callback':o.f1}); 'callback':o.f1,'maxtries':1});
ok(LocalOrCookieStorage.getItem('jio/jobObject/'+id)['1'], ok(LocalOrCookieStorage.getItem('jio/jobObject/'+id)['1'],
'job creation'); 'job creation');
clock.tick(10); clock.tick(10);
o.jio.removeDocument({'fileName':'file','fileContent':'content', o.jio.removeDocument({'fileName':'file','fileContent':'content',
'callback':o.f2}); 'callback':o.f2,'maxtries':1});
deepEqual(LocalOrCookieStorage.getItem('jio/jobObject/'+id)['1'], o.tmp = LocalOrCookieStorage.getItem('jio/jobObject/'+id)['1'];
undefined,'job elimination'); ok(!o.tmp || o.tmp.status === 'fail','job elimination');
}); });
test ('Simple Job Replacement', function () { test ('Simple Job Replacement', function () {
// Test if the second job write over the first one // Test if the second job write over the first one
var o = {}, clock = this.sandbox.useFakeTimers(), id = 0; var o = {}, clock = this.sandbox.useFakeTimers(), id = 0;
o.f1 = this.spy(); o.f2 = this.spy() o.f1 = function (result) {
o.status = result.status;
};
this.spy(o,'f1');
o.f2 = this.spy()
o.jio = JIO.createNew({'type':'dummyallok','userName':'dummy'}, o.jio = JIO.createNew({'type':'dummyallok','userName':'dummy'},
{'ID':'jiotests'}); {'ID':'jiotests'});
id = o.jio.id; id = o.jio.id;
o.jio.saveDocument({'fileName':'file','fileContent':'content', o.jio.saveDocument({'fileName':'file','fileContent':'content',
'callback':o.f1}); 'callback':o.f1,'maxtries':1});
clock.tick(10); clock.tick(10);
o.jio.saveDocument({'fileName':'file','fileContent':'content', o.jio.saveDocument({'fileName':'file','fileContent':'content',
'callback':o.f2}); 'callback':o.f2,'maxtries':1});
deepEqual(LocalOrCookieStorage.getItem( deepEqual(LocalOrCookieStorage.getItem(
'jio/jobObject/'+id)['1'].date,10, 'jio/jobObject/'+id)['1'].date,10,
'The first job date have to be equal to the second job date.'); 'The first job date have to be equal to the second job date.');
clock.tick(500); clock.tick(500);
ok(!o.f1.calledOnce,'no callback for the first save request'); deepEqual([o.f1.calledOnce,o.status],[true,'fail'],
'callback for the first save request -> result fail');
ok(o.f2.calledOnce,'second callback is called once'); ok(o.f2.calledOnce,'second callback is called once');
o.jio.stop(); o.jio.stop();
...@@ -184,10 +190,10 @@ test ('Simple Job Waiting', function () { ...@@ -184,10 +190,10 @@ test ('Simple Job Waiting', function () {
{'ID':'jiotests'}); {'ID':'jiotests'});
id = o.jio.id; id = o.jio.id;
o.jio.saveDocument({'fileName':'file','fileContent':'content', o.jio.saveDocument({'fileName':'file','fileContent':'content',
'callback':o.f3}); 'callback':o.f3,'maxtries':1});
clock.tick(200); clock.tick(200);
o.jio.saveDocument({'fileName':'file','fileContent':'content', o.jio.saveDocument({'fileName':'file','fileContent':'content',
'callback':o.f4}); 'callback':o.f4,'maxtries':1});
ok(LocalOrCookieStorage.getItem( ok(LocalOrCookieStorage.getItem(
'jio/jobObject/'+id)['2'] && 'jio/jobObject/'+id)['2'] &&
LocalOrCookieStorage.getItem( LocalOrCookieStorage.getItem(
...@@ -206,6 +212,27 @@ test ('Simple Job Waiting', function () { ...@@ -206,6 +212,27 @@ test ('Simple Job Waiting', function () {
o.jio.stop(); o.jio.stop();
}); });
test ('Simple Time Waiting' , function () {
// Test if the job that have fail wait until a certain moment to restart.
var o = {}, clock = this.sandbox.useFakeTimers(), id = 0;
o.f1 = this.spy();
o.jio = JIO.createNew({'type':'dummyallfail','userName':'dummy'},
{'ID':'jiotests'});
id = o.jio.id;
o.jio.saveDocument({'fileName':'file','fileContent':'content',
'callback':o.f1,'maxtries':2});
clock.tick(400);
o.tmp = LocalOrCookieStorage.getItem('jio/jobObject/'+id)['1'];
ok(o.tmp.status === 'wait' && o.tmp.waitingFor && o.tmp.waitingFor.time,
'is waiting for time');
clock.tick(1500);
o.tmp = LocalOrCookieStorage.getItem('jio/jobObject/'+id)['1'];
ok(o.tmp.status === 'fail','it restores itself after time');
console.log (localStorage);
o.jio.stop();
});
module ( 'Jio LocalStorage' ); module ( 'Jio LocalStorage' );
test ('Check name availability', function () { test ('Check name availability', function () {
...@@ -219,7 +246,7 @@ test ('Check name availability', function () { ...@@ -219,7 +246,7 @@ test ('Check name availability', function () {
deepEqual(result.isAvailable,value,'checking name availabality');}; deepEqual(result.isAvailable,value,'checking name availabality');};
t.spy(o,'f'); t.spy(o,'f');
o.jio.checkNameAvailability( o.jio.checkNameAvailability(
{'userName':'MrCheckName','callback': o.f}); {'userName':'MrCheckName','callback': o.f,'maxtries':1});
clock.tick(510); clock.tick(510);
if (!o.f.calledOnce) if (!o.f.calledOnce)
ok(false, 'no response / too much results'); ok(false, 'no response / too much results');
...@@ -245,23 +272,25 @@ test ('Document save', function () { ...@@ -245,23 +272,25 @@ test ('Document save', function () {
// We launch a saving to localstorage and we check if the file is // We launch a saving to localstorage and we check if the file is
// realy saved. Then save again and check if // realy saved. Then save again and check if
var o = {}, clock = this.sandbox.useFakeTimers(), t = this, var o = {}, clock = this.sandbox.useFakeTimers(), t = this, tmp,
mytest = function (message,value,lm,cd,tick){ mytest = function (message,value,lmcd){
var tmp;
o.f = function (result) { o.f = function (result) {
deepEqual(result.isSaved,value,message);}; deepEqual(result.isSaved,value,message);};
t.spy(o,'f'); t.spy(o,'f');
o.jio.saveDocument( o.jio.saveDocument(
{'fileName':'file','fileContent':'content','callback': o.f}); {'fileName':'file','fileContent':'content','callback': o.f,
if (tick === undefined) { clock.tick(510); } 'maxtries':1});
else { clock.tick(tick); } clock.tick(510);
if (!o.f.calledOnce) if (!o.f.calledOnce)
ok(false, 'no response / too much results'); ok(false, 'no response / too much results');
else { else {
// check content // check content
tmp = LocalOrCookieStorage.getItem ('jio/local/MrSaveName/jiotests/file'); tmp = LocalOrCookieStorage.getItem ('jio/local/MrSaveName/jiotests/file');
tmp.lmcd = lmcd(tmp.creationDate,tmp.lastModified);
delete tmp.lastModified;
delete tmp.creationDate;
deepEqual (tmp,{'fileName':'file','fileContent':'content', deepEqual (tmp,{'fileName':'file','fileContent':'content',
'lastModified':lm,'creationDate':cd},'check content'); 'lmcd':true},'check content');
} }
}; };
...@@ -270,16 +299,15 @@ test ('Document save', function () { ...@@ -270,16 +299,15 @@ test ('Document save', function () {
LocalOrCookieStorage.deleteItem ('jio/local/MrSaveName/jiotests/file'); LocalOrCookieStorage.deleteItem ('jio/local/MrSaveName/jiotests/file');
// save and check document existence // save and check document existence
clock.tick(200); clock.tick(200);
mytest('saving document',true,200,200); // value, lastmodified, creationdate // message, value, fun ( creationdate, lastmodified )
mytest('saving document',true,function(cd,lm){
return (cd === lm);
});
// re-save and check modification date // re-save and check modification date
// 710 = 200 + 510 ms (clock tick) mytest('saving again',true,function(cd,lm){
mytest('saving again',true,710,200); return (cd < lm);
});
// re-save and check modification date
// 1220 = 710 + 510 ms (clock tick)
clock.tick(-1000);
mytest('saving a older document',false,710,200,1510);
o.jio.stop(); o.jio.stop();
}); });
...@@ -296,7 +324,7 @@ test ('Document load', function () { ...@@ -296,7 +324,7 @@ test ('Document load', function () {
deepEqual(result[res],value,'loading document');}; deepEqual(result[res],value,'loading document');};
t.spy(o,'f'); t.spy(o,'f');
o.jio.loadDocument( o.jio.loadDocument(
{'fileName':'file','callback': o.f}); {'fileName':'file','callback': o.f,'maxtries':1});
clock.tick(510); clock.tick(510);
if (!o.f.calledOnce) if (!o.f.calledOnce)
ok(false, 'no response / too much results'); ok(false, 'no response / too much results');
...@@ -333,7 +361,7 @@ test ('Get document list', function () { ...@@ -333,7 +361,7 @@ test ('Get document list', function () {
objectifyDocumentArray(value),'getting list'); objectifyDocumentArray(value),'getting list');
}; };
t.spy(o,'f'); t.spy(o,'f');
o.jio.getDocumentList({'callback': o.f}); o.jio.getDocumentList({'callback': o.f,'maxtries':1});
clock.tick(510); clock.tick(510);
if (!o.f.calledOnce) if (!o.f.calledOnce)
ok(false, 'no response / too much results'); ok(false, 'no response / too much results');
...@@ -364,7 +392,7 @@ test ('Document remove', function () { ...@@ -364,7 +392,7 @@ test ('Document remove', function () {
deepEqual(result.isRemoved,true,'removing document');}; deepEqual(result.isRemoved,true,'removing document');};
t.spy(o,'f'); t.spy(o,'f');
o.jio.removeDocument( o.jio.removeDocument(
{'fileName':'file','callback': o.f}); {'fileName':'file','callback': o.f,'maxtries':1});
clock.tick(510); clock.tick(510);
if (!o.f.calledOnce) if (!o.f.calledOnce)
ok(false, 'no response / too much results'); ok(false, 'no response / too much results');
...@@ -398,7 +426,8 @@ test ('Check name availability', function () { ...@@ -398,7 +426,8 @@ test ('Check name availability', function () {
o.f = function (result) { o.f = function (result) {
deepEqual (result.isAvailable,value,'checking name availability');}; deepEqual (result.isAvailable,value,'checking name availability');};
t.spy(o,'f'); t.spy(o,'f');
o.jio.checkNameAvailability({'userName':'davcheck','callback':o.f}); o.jio.checkNameAvailability({'userName':'davcheck','callback':o.f,
'maxtries':1});
clock.tick(500); clock.tick(500);
server.respond(); server.respond();
if (!o.f.calledOnce) if (!o.f.calledOnce)
...@@ -436,7 +465,7 @@ test ('Document load', function () { ...@@ -436,7 +465,7 @@ test ('Document load', function () {
o.f = function (result) { o.f = function (result) {
deepEqual (result.document,doc,message);}; deepEqual (result.document,doc,message);};
t.spy(o,'f'); t.spy(o,'f');
o.jio.loadDocument({'fileName':'file','callback':o.f}); o.jio.loadDocument({'fileName':'file','callback':o.f,'maxtries':1});
clock.tick(500); clock.tick(500);
server.respond(); server.respond();
if (!o.f.calledOnce) if (!o.f.calledOnce)
...@@ -467,8 +496,7 @@ test ('Document save', function () { ...@@ -467,8 +496,7 @@ test ('Document save', function () {
var davsave = getXML('responsexml/davsave'), var davsave = getXML('responsexml/davsave'),
o = {}, clock = this.sandbox.useFakeTimers(), t = this, o = {}, clock = this.sandbox.useFakeTimers(), t = this,
mytest = function (message,value,errnoput,errnoprop, mytest = function (message,value,errnoput,errnoprop) {
overwrite,force,tick) {
var server = t.sandbox.useFakeServer(); var server = t.sandbox.useFakeServer();
server.respondWith ( server.respondWith (
// lastmodified = 7000, creationdate = 5000 // lastmodified = 7000, creationdate = 5000
...@@ -493,8 +521,7 @@ test ('Document save', function () { ...@@ -493,8 +521,7 @@ test ('Document save', function () {
deepEqual (result.isSaved,value,message);}; deepEqual (result.isSaved,value,message);};
t.spy(o,'f'); t.spy(o,'f');
o.jio.saveDocument({'fileName':'file','fileContent':'content', o.jio.saveDocument({'fileName':'file','fileContent':'content',
'options':{'force':force,'overwrite':overwrite}, 'callback':o.f,'maxtries':1});
'callback':o.f});
clock.tick(500); clock.tick(500);
server.respond(); server.respond();
if (!o.f.calledOnce) if (!o.f.calledOnce)
...@@ -516,21 +543,10 @@ test ('Document save', function () { ...@@ -516,21 +543,10 @@ test ('Document save', function () {
// true,201,404); // true,201,404);
// the document does not exist, we want to create it // the document does not exist, we want to create it
mytest('create document',true,201,404); mytest('create document',true,201,404);
// the document is already exists, it is younger than the one we want
// to save.
mytest('younger than the one we want to save',
false,204,207,true,false);
// the document is already exists, it is the youngest but we want to
// force overwriting
mytest('youngest but force overwrite',
true,204,207,true,true);
clock.tick(8000); clock.tick(8000);
// the document already exists, we want to overwrite it // the document already exists, we want to overwrite it
mytest('overwrite document', mytest('overwrite document',
true,204,207,true); true,204,207);
// the document already exists, we don't want to overwrite it
mytest('do not overwrite document',
false,204,207,false);
o.jio.stop(); o.jio.stop();
}); });
...@@ -555,7 +571,7 @@ test ('Get Document List', function () { ...@@ -555,7 +571,7 @@ test ('Get Document List', function () {
objectifyDocumentArray(value),message); objectifyDocumentArray(value),message);
}; };
t.spy(o,'f'); t.spy(o,'f');
o.jio.getDocumentList({'callback':o.f}); o.jio.getDocumentList({'callback':o.f,'maxtries':1});
clock.tick(500); clock.tick(500);
server.respond(); server.respond();
if (!o.f.calledOnce) if (!o.f.calledOnce)
...@@ -585,7 +601,7 @@ test ('Remove document', function () { ...@@ -585,7 +601,7 @@ test ('Remove document', function () {
o.f = function (result) { o.f = function (result) {
deepEqual (result.isRemoved,value,message);}; deepEqual (result.isRemoved,value,message);};
t.spy(o,'f'); t.spy(o,'f');
o.jio.removeDocument({'fileName':'file','callback':o.f}); o.jio.removeDocument({'fileName':'file','callback':o.f,'maxtries':1});
clock.tick(500); clock.tick(500);
server.respond(); server.respond();
if (!o.f.calledOnce) if (!o.f.calledOnce)
...@@ -614,7 +630,8 @@ test ('Check name availability', function () { ...@@ -614,7 +630,8 @@ test ('Check name availability', function () {
o.f = function (result) { o.f = function (result) {
deepEqual (result.isAvailable,value,message)}; deepEqual (result.isAvailable,value,message)};
t.spy(o,'f'); t.spy(o,'f');
o.jio.checkNameAvailability({'userName':'Dummy','callback':o.f}); o.jio.checkNameAvailability({'userName':'Dummy','callback':o.f,
'maxtries':1});
clock.tick(1000); clock.tick(1000);
if (!o.f.calledOnce) if (!o.f.calledOnce)
ok(false,'no respose / too much results'); ok(false,'no respose / too much results');
......
...@@ -32,8 +32,76 @@ ...@@ -32,8 +32,76 @@
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// jio globals // jio globals
jioGlobalObj = { jioGlobalObj = {
// For more information, see documentation
'jobManagingMethod':{ 'jobManagingMethod':{
/*
LEGEND:
- s: storage
- a: applicant
- m: method
- n: fileName
- c: fileContent
- o: options
- =: are equal
- !: are not equal
select ALL s= a= n=
removefailordone fail|done
/ elim repl nacc wait
Remove !ongoing Save 1 x x x
Save !ongoing Remove 1 x x x
GetList !ongoing GetList 0 1 x x
Check !ongoing Check 0 1 x x
Remove !ongoing Remove 0 1 x x
Load !ongoing Load 0 1 x x
Save c= !ongoing Save 0 1 x x
Save c! !ongoing Save 0 1 x x
GetList ongoing GetList 0 0 1 x
Check ongoing Check 0 0 1 x
Remove ongoing Remove 0 0 1 x
Remove ongoing Load 0 0 1 x
Remove !ongoing Load 0 0 1 x
Load ongoing Load 0 0 1 x
Save c= ongoing Save 0 0 1 x
Remove ongoing Save 0 0 0 1
Load ongoing Remove 0 0 0 1
Load ongoing Save 0 0 0 1
Load !ongoing Remove 0 0 0 1
Load !ongoing Save 0 0 0 1
Save ongoing Remove 0 0 0 1
Save ongoing Load 0 0 0 1
Save c! ongoing Save 0 0 0 1
Save !ongoing Load 0 0 0 1
GetList ongoing Check 0 0 0 0
GetList ongoing Remove 0 0 0 0
GetList ongoing Load 0 0 0 0
GetList ongoing Save 0 0 0 0
GetList !ongoing Check 0 0 0 0
GetList !ongoing Remove 0 0 0 0
GetList !ongoing Load 0 0 0 0
GetList !ongoing Save 0 0 0 0
Check ongoing GetList 0 0 0 0
Check ongoing Remove 0 0 0 0
Check ongoing Load 0 0 0 0
Check ongoing Save 0 0 0 0
Check !ongoing GetList 0 0 0 0
Check !ongoing Remove 0 0 0 0
Check !ongoing Load 0 0 0 0
Check !ongoing Save 0 0 0 0
Remove ongoing GetList 0 0 0 0
Remove ongoing Check 0 0 0 0
Remove !ongoing GetList 0 0 0 0
Remove !ongoing Check 0 0 0 0
Load ongoing GetList 0 0 0 0
Load ongoing Check 0 0 0 0
Load !ongoing GetList 0 0 0 0
Load !ongoing Check 0 0 0 0
Save ongoing GetList 0 0 0 0
Save ongoing Check 0 0 0 0
Save !ongoing GetList 0 0 0 0
Save !ongoing Check 0 0 0 0
For more information, see documentation
*/
'canSelect':function (job1,job2) { 'canSelect':function (job1,job2) {
if (JSON.stringify (job1.storage) === if (JSON.stringify (job1.storage) ===
JSON.stringify (job2.storage) && JSON.stringify (job2.storage) &&
...@@ -45,9 +113,8 @@ ...@@ -45,9 +113,8 @@
return false; return false;
}, },
'canRemoveFailOrDone':function (job1,job2) { 'canRemoveFailOrDone':function (job1,job2) {
if (job1.method === job2.method && if (job1.status === 'fail' ||
(job1.status === 'fail' || job1.status === 'done') {
job1.status === 'done')) {
return true; return true;
} }
return false; return false;
...@@ -63,10 +130,8 @@ ...@@ -63,10 +130,8 @@
}, },
'canReplace':function (job1,job2) { 'canReplace':function (job1,job2) {
if (job1.status !== 'ongoing' && if (job1.status !== 'ongoing' &&
job1.method === job2.method && job1.method === job2.method &&
JSON.stringify (job1.options) === job1.date < job2.date) {
JSON.stringify (job2.options) &&
job1.fileContent === job2.fileContent) {
return true; return true;
} }
return false; return false;
...@@ -77,26 +142,32 @@ ...@@ -77,26 +142,32 @@
job2.method === 'loadDocument') { job2.method === 'loadDocument') {
return true; return true;
} }
} else { } else { // ongoing
if (job1.method === 'loadDocument') { if (job1.method === job2.method === 'loadDocument') {
if (job2.method === 'loadDocument') { return true;
return true; } else if (job1.method === 'removeDocument' &&
} (job2.method === 'loadDocument' ||
} else if (job1.method === 'removeDocument') { job2.method === 'removeDocument')) {
if (job2.method === 'loadDocument' || return true;
job2.method === 'removeDocument') {
return true;
}
} else if (job1.method === job2.method === 'saveDocument' && } else if (job1.method === job2.method === 'saveDocument' &&
job1.fileContent === job2.fileContent && job1.fileContent === job2.fileContent) {
JSON.stringify (job1.options) === return true;
JSON.stringify (job2.options)) { } else if (job1.method === job2.method ===
'getDocumentList' ||
job1.method === job2.method ===
'checkNameAvailability') {
return true; return true;
} }
} }
return false; return false;
}, },
'mustWait':function (job1,job2) { 'mustWait':function (job1,job2) {
if (job1.method === 'getDocumentList' ||
job1.method === 'checkNameAvailability' ||
job2.method === 'getDocumentList' ||
job2.method === 'checkNameAvailability' ) {
return false;
}
return true; return true;
} }
}, },
...@@ -123,14 +194,6 @@ ...@@ -123,14 +194,6 @@
catch (e) { err('LocalOrCookieStorage'); } catch (e) { err('LocalOrCookieStorage'); }
return retval; return retval;
}, },
createStorageObject = function ( options ) {
// Create a storage thanks to storages types set with 'addStorageType'.
if (!jioGlobalObj.storageTypeObject[ options.storage.type ])
return null; // error!
return jioGlobalObj.storageTypeObject[
options.storage.type ](options);
},
getNewQueueID = function () { getNewQueueID = function () {
// Returns a new queueID // Returns a new queueID
var localStor = jioGlobalObj.localStorage.getAll(), k = 'key', var localStor = jioGlobalObj.localStorage.getAll(), k = 'key',
...@@ -156,7 +219,7 @@ ...@@ -156,7 +219,7 @@
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// Classes // Classes
PubSub,Job,JobQueue,JobListener,ActivityUpdater,JioCons,Jio; PubSub,Job,JobQueue,JobListener,ActivityUpdater,BaseStorage,JioCons,Jio;
// end Classes // end Classes
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
...@@ -213,11 +276,14 @@ ...@@ -213,11 +276,14 @@
return job; return job;
}; };
JobQueue = function ( publisher ) { JobQueue = function ( publisher, options ) {
// JobQueue is a queue of jobs. It will regulary copy this queue // JobQueue is a queue of jobs. It will regulary copy this queue
// into localStorage to resume undone tasks. // into localStorage to resume undone tasks.
// pubsub: the publisher to use to send event // publisher: the publisher to use to send event
// options.useLocalStorage: if true, save jobs into localStorage,
// else only save on memory.
this.useLocalStorage = options.useLocalStorage;
this.publisher = publisher; this.publisher = publisher;
this.jobid = 1; this.jobid = 1;
this.jioID = 0; this.jioID = 0;
...@@ -265,20 +331,27 @@ ...@@ -265,20 +331,27 @@
}, },
copyJobQueueToLocalStorage: function () { copyJobQueueToLocalStorage: function () {
// Copy job queue into localStorage. // Copy job queue into localStorage.
return jioGlobalObj.localStorage.setItem( if (this.useLocalStorage) {
this.jobObjectName,this.jobObject); return jioGlobalObj.localStorage.setItem(
this.jobObjectName,this.jobObject);
} else {
return false;
}
}, },
createJob: function ( options ) { createJob: function ( options ) {
return this.addJob ( new Job ( options ) ); return this.addJob ( new Job ( options ) );
}, },
addJob: function ( job ) { addJob: function ( job ) {
// Add a job to the queue TODO DocString // Add a job to the queue, browsing all jobs
// and check if the new job can eliminate older ones,
// can replace older one, can be accepted, or must wait
// for older ones.
// It also clean fail or done jobs.
// job : the job object // job : the job object
var res = {'newone':true,'elimArray':[],'waitArray':[], var res = {'newone':true,'elimArray':[],'waitArray':[],
'removeArray':[]}, 'removeArray':[]}, basestorage = null, id=0;
id=0;
//// browsing current jobs //// browsing current jobs
for (id in this.jobObject) { for (id in this.jobObject) {
...@@ -287,6 +360,7 @@ ...@@ -287,6 +360,7 @@
if (jioGlobalObj.jobManagingMethod.canRemoveFailOrDone( if (jioGlobalObj.jobManagingMethod.canRemoveFailOrDone(
this.jobObject[id],job)) { this.jobObject[id],job)) {
res.removeArray.push(id); res.removeArray.push(id);
continue;
} }
if (jioGlobalObj.jobManagingMethod.canEliminate( if (jioGlobalObj.jobManagingMethod.canEliminate(
this.jobObject[id],job)) { this.jobObject[id],job)) {
...@@ -299,21 +373,21 @@ ...@@ -299,21 +373,21 @@
this.jobObject[id],job)) { this.jobObject[id],job)) {
console.log ('Replaced: ' + console.log ('Replaced: ' +
JSON.stringify (this.jobObject[id])); JSON.stringify (this.jobObject[id]));
this.jobObject[id].date = job.date; basestorage = new BaseStorage(
// no need to copy fileContent or userName {'queue':this,'job':this.jobObject[id]});
this.jobObject[id].callback = job.callback; basestorage.replace(job);
res.newone = false; res.newone = false;
break; break;
} }
if (jioGlobalObj.jobManagingMethod.cannotAccept( if (jioGlobalObj.jobManagingMethod.cannotAccept(
this.jobObject[id],job)) { this.jobObject[id],job)) {
console.log ('Make not accepted: ' + console.log ('Not accepted: ' + JSON.stringify (job) + '\nby: ' +
JSON.stringify (this.jobObject[id])); JSON.stringify (this.jobObject[id]));
// Job not accepted // Job not accepted
return false; return false;
} }
if (jioGlobalObj.jobManagingMethod.mustWait( if (jioGlobalObj.jobManagingMethod.mustWait(
this.jobObject[id].job)) { this.jobObject[id],job)) {
console.log ('Waited: ' + console.log ('Waited: ' +
JSON.stringify (this.jobObject[id]) + JSON.stringify (this.jobObject[id]) +
'\nby : ' + JSON.stringify (job)); '\nby : ' + JSON.stringify (job));
...@@ -330,13 +404,17 @@ ...@@ -330,13 +404,17 @@
// if it is a new job, we can eliminate deprecated jobs and // if it is a new job, we can eliminate deprecated jobs and
// set this job dependencies. // set this job dependencies.
for (id in res.elimArray) { for (id in res.elimArray) {
this.removeJob(this.jobObject[res.elimArray[id]]); basestorage = new BaseStorage(
{'queue':this,'job':this.jobObject[res.elimArray[id]]});
basestorage.eliminate();
} }
if (res.waitArray.length > 0) { if (res.waitArray.length > 0) {
job.status = 'wait'; job.status = 'wait';
job.waitingFor = {'jobIdArray':res.waitArray}; job.waitingFor = {'jobIdArray':res.waitArray};
for (id in res.waitArray) { for (id in res.waitArray) {
this.jobObject[res.waitArray[id]].maxtries = 1; if (this.jobObject[res.waitArray[id]]) {
this.jobObject[res.waitArray[id]].maxtries = 1;
}
} }
} }
for (id in res.removeArray) { for (id in res.removeArray) {
...@@ -389,6 +467,8 @@ ...@@ -389,6 +467,8 @@
resetAll: function () { resetAll: function () {
// Reset all job to 'initial'. // Reset all job to 'initial'.
// TODO manage jobs ! All jobs are not 'initial'.
var id = 'id'; var id = 'id';
for (id in this.jobObject) { for (id in this.jobObject) {
this.jobObject[id].status = 'initial'; this.jobObject[id].status = 'initial';
...@@ -407,10 +487,10 @@ ...@@ -407,10 +487,10 @@
// invoke new job // invoke new job
this.invoke(this.jobObject[i]); this.invoke(this.jobObject[i]);
} else if (this.jobObject[i].status === 'wait') { } else if (this.jobObject[i].status === 'wait') {
ok = true;
// if status wait // if status wait
if (this.jobObject[i].waitingFor.jobIdArray) { if (this.jobObject[i].waitingFor.jobIdArray) {
// wait job // wait job
ok = true;
// browsing job id array // browsing job id array
for (j in this.jobObject[i].waitingFor.jobIdArray) { for (j in this.jobObject[i].waitingFor.jobIdArray) {
if (this.jobObject[this.jobObject[i]. if (this.jobObject[this.jobObject[i].
...@@ -420,18 +500,17 @@ ...@@ -420,18 +500,17 @@
break; break;
} }
} }
if (ok) { }
// invoke waiting job if (this.jobObject[i].waitingFor.time) {
this.invoke(this.jobObject[i]);
}
} else if (this.jobObject[i].waitingFor.time) {
// wait time // wait time
if (this.jobObject[i].waitingFor.time > Date.now()) { if (this.jobObject[i].waitingFor.time > Date.now()) {
// it is time to restore the job! // it is not time to restore the job!
this.invoke(this.jobObject[i]); ok = false;
} }
} else { }
// wait nothing // else wait nothing
if (ok) {
// invoke waiting job
this.invoke(this.jobObject[i]); this.invoke(this.jobObject[i]);
} }
} }
...@@ -443,7 +522,8 @@ ...@@ -443,7 +522,8 @@
invoke: function (job) { invoke: function (job) {
// Do a job invoking the good method in the good storage. // Do a job invoking the good method in the good storage.
var t = this; var t = this, basestorage,
userName = job.userName ? job.userName : job.storage.userName;
//// analysing job method //// analysing job method
// if the method does not exist, do nothing // if the method does not exist, do nothing
...@@ -462,13 +542,8 @@ ...@@ -462,13 +542,8 @@
job.status = 'ongoing'; job.status = 'ongoing';
} }
// Create a storage object and use it to save,load,...! // Create a storage object and use it to save,load,...!
createStorageObject( basestorage = new BaseStorage({'queue':this,'job':job});
{'queue':this, basestorage.execute();
'storage':job.storage,
'applicant':jioGlobalObj.applicant})[job.method](
job,function (endedjob){
t.ended(endedjob);
});
//// end method analyse //// end method analyse
}, },
...@@ -486,6 +561,8 @@ ...@@ -486,6 +561,8 @@
// save to local storage // save to local storage
this.copyJobQueueToLocalStorage (); this.copyJobQueueToLocalStorage ();
break; break;
case 'wait':
break;
default: default:
break; break;
} }
...@@ -497,7 +574,9 @@ ...@@ -497,7 +574,9 @@
// if there isn't some job to do, then send stop event // if there isn't some job to do, then send stop event
if (!this.isThereJobsWhere(function(testjob){ if (!this.isThereJobsWhere(function(testjob){
return (testjob.method === job.method && return (testjob.method === job.method &&
testjob.status !== 'fail'); // testjob.status === 'wait' || // TODO ?
testjob.status === 'ongoing' ||
testjob.status === 'initial');
})) { })) {
this.publisher.publish( this.publisher.publish(
jioConstObj.jobMethodObject[ jioConstObj.jobMethodObject[
...@@ -510,10 +589,11 @@ ...@@ -510,10 +589,11 @@
// Clean the job list, removing all jobs that have failed. // Clean the job list, removing all jobs that have failed.
// It also change the localStorage job queue // It also change the localStorage job queue
this.removeJob (undefined, this.removeJob (
{'where':function (job) { undefined,{
return (job.status === 'fail'); 'where':function (job) {
} }); return (job.status === 'fail');
} });
} }
}; };
// end Job & JobQueue // end Job & JobQueue
...@@ -606,15 +686,147 @@ ...@@ -606,15 +686,147 @@
// end ActivityUpdater // end ActivityUpdater
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
// BaseStorage
BaseStorage = function ( options ) {
// The base storage, will call the good method from the good storage,
// and will check and return the associated value.
this.job = options.job;
this.callback = options.job.callback;
this.queue = options.queue;
this.res = {'status':'done','message':''};
};
BaseStorage.prototype = {
createStorageObject: function ( options ) {
// Create a storage thanks to storages types set
// with 'addStorageType'.
if (!jioGlobalObj.storageTypeObject[ options.job.storage.type ])
return null; // error!
return jioGlobalObj.storageTypeObject[
options.job.storage.type ](options);
},
retryLater: function () {
// Change the job status to wait for time.
// The listener will invoke this job later.
this.job.status = 'wait';
this.job.waitingFor = {'time':Date.now() +
(this.job.tries*this.job.tries*1000)};
},
eliminate: function () {
this.job.maxtries = 0;
this.fail('Job Stopped!',0);
},
replace: function ( newjob ) {
// It replace the current job by the new one.
// Replacing only the date
this.job.tries = 0;
this.job.date = newjob.date;
this.job.callback = newjob.callback;
this.res.status = 'fail';
this.res.message = 'Job Stopped!';
this.res.errno = 0;
this['fail_'+this.job.method]();
this.callback(this.res);
},
fail: function ( message, errno ) {
// Called when a job has failed.
// It will retry the job from a certain moment or it will return
// a failure.
this.res.status = 'fail';
this.res.message = message;
this.res.errno = errno;
if (this.job.maxtries && this.job.tries < this.job.maxtries) {
this.retryLater();
} else {
this.job.status = 'fail';
this['fail_'+this.job.method]();
this.queue.ended(this.job);
this.callback(this.res);
}
},
done: function ( retvalue ) {
// Called when a job has terminated successfully.
// It will return the return value by the calling the callback
// function.
this.job.status = 'done';
this['done_'+this.job.method]( retvalue );
this.queue.ended(this.job);
this.callback(this.res);
},
execute: function () {
// Execute the good function from the good storage.
var t = this, stor = null;
if (!this.job.tries) {
this.job.tries = 0;
}
this.job.tries ++;
stor = this.createStorageObject (
{'job':this.job,'queue':this.queue}
);
stor.done = function (retval) { t.done(retval); };
stor.fail = function (mess,errno) { t.fail(mess,errno); };
stor[this.job.method]();
},
fail_checkNameAvailability: function () {
this.res.isAvailable = false;
},
done_checkNameAvailability: function ( isavailable ) {
this.res.message = this.job.userName + ' is ' +
(isavailable?'':'not ') + 'available.';
this.res.isAvailable = isavailable;
},
fail_saveDocument: function () {
this.res.isSaved = false;
},
done_saveDocument: function () {
this.res.message = 'Document saved.';
this.res.isSaved = true;
},
fail_loadDocument: function () {
this.res.document = {};
},
done_loadDocument: function ( returneddocument ) {
this.res.message = 'Document loaded.';
this.res.document = returneddocument;
},
fail_getDocumentList: function () {
this.res.list = [];
},
done_getDocumentList: function ( documentlist ) {
this.res.message = 'Document list received.';
this.res.list = documentlist;
},
fail_removeDocument: function () {
this.res.isRemoved = false;
},
done_removeDocument: function () {
this.res.message = 'Document removed.';
this.res.isRemoved = true;
}
};
// end BaseStorage
////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// JIO Constructor // JIO Constructor
JioCons = function ( storage , applicant ) { JioCons = function ( storage , applicant, options ) {
// JIO Constructor, create a new JIO object. // JIO Constructor, create a new JIO object.
// It just initializes values. // It just initializes values.
// storage : the storage that contains {type:..,[storageinfos]} // storage : the storage that contains {type:..,[storageinfos]}
// applicant : the applicant that contains {ID:...} // applicant : the applicant that contains {ID:...}
// these parameters are optional and may be 'string' or 'object' // these parameters are optional and may be 'string' or 'object'
var settings = $.extend({'useLocalStorage':true},options);
// objectify storage and applicant // objectify storage and applicant
if(typeof storage === 'string') if(typeof storage === 'string')
storage = JSON.parse(options.storage); storage = JSON.parse(options.storage);
...@@ -625,11 +837,15 @@ ...@@ -625,11 +837,15 @@
this['storage'] = storage; this['storage'] = storage;
this['applicant'] = applicant; this['applicant'] = applicant;
this['id'] = 0; this['id'] = 0;
this['pubsub'] = new PubSub(); this['pubsub'] = new PubSub(settings);
this['queue'] = new JobQueue(this.pubsub); this['queue'] = new JobQueue(this.pubsub,settings);
this['listener'] = new JobListener(this.queue); this['listener'] = new JobListener(this.queue,settings);
this['updater'] = new ActivityUpdater();
this['ready'] = false; this['ready'] = false;
if (settings.useLocalStorage) {
this['updater'] = new ActivityUpdater(settings);
} else {
this['updater'] = null;
}
// check storage type // check storage type
if (this.storage) if (this.storage)
...@@ -648,8 +864,10 @@ ...@@ -648,8 +864,10 @@
this.id = getNewQueueID(); this.id = getNewQueueID();
// initializing objects // initializing objects
this.queue.init({'jioID':this.id}); this.queue.init({'jioID':this.id});
// start touching // start activity updater
this.updater.start(this.id); if (this.updater){
this.updater.start(this.id);
}
// start listening // start listening
this.listener.start(); this.listener.start();
// is now ready // is now ready
...@@ -662,7 +880,9 @@ ...@@ -662,7 +880,9 @@
this.queue.close(); this.queue.close();
this.listener.stop(); this.listener.stop();
this.updater.stop(); if (this.updater) {
this.updater.stop();
}
this.ready = false; this.ready = false;
this.id = 0; this.id = 0;
return true; return true;
...@@ -673,7 +893,9 @@ ...@@ -673,7 +893,9 @@
this.queue.close(); this.queue.close();
this.listener.stop(); this.listener.stop();
this.updater.stop(); if (this.updater) {
this.updater.stop();
}
// TODO // TODO
this.ready = false; this.ready = false;
return true; return true;
...@@ -864,14 +1086,21 @@ ...@@ -864,14 +1086,21 @@
// this object permit to create jio object // this object permit to create jio object
}; };
Jio.prototype = { Jio.prototype = {
createNew: function ( storage, applicant) { createNew: function ( storage, applicant, options ) {
// return a new instance of JIO // Return a new instance of JIO
// storage: the storage object or json string
// applicant: the applicant object or json string
// options.useLocalStorage: if true, save job queue on localStorage.
var settings = $.extend({'useLocalStorage':true},options);
if (jioGlobalObj.localStorage===null) { if (jioGlobalObj.localStorage===null) {
jioGlobalObj.localStorage = LocalOrCookieStorage; jioGlobalObj.localStorage = LocalOrCookieStorage;
} }
return new JioCons(storage,applicant); return new JioCons(storage,applicant,settings);
},
getStoragePrototype: function () {
return new BaseStorage();
}, },
addStorageType: function ( type, constructor ) { addStorageType: function ( type, constructor ) {
// Add a storage type to jio. Jio must have keys/types which are // Add a storage type to jio. Jio must have keys/types which are
......
...@@ -38,26 +38,20 @@ ...@@ -38,26 +38,20 @@
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// Local Storage // Local Storage
LocalStorage = function ( options ) { LocalStorage = function ( args ) {
// LocalStorage constructor // LocalStorage constructor
// initializes the local storage for jio and create user if necessary.
this.job = args.job;
this.userName = options.storage.userName;
}; };
LocalStorage.prototype = { LocalStorage.prototype = {
checkNameAvailability: function ( job , jobendcallback) { checkNameAvailability: function () {
// checks the availability of the [job.userName]. // checks the availability of the [job.userName].
// if the name already exists, it is not available. // if the name already exists, it is not available.
// job: the job object // this.job.userName: the name we want to check.
// job.userName: the name we want to check.
// jobendcallback : the function called at the end of the job.
// returns {'status':string,'message':string,'isAvailable':boolean}
// in the jobendcallback arguments.
var available = true, localStor = null, var t = this, localStor = null,
k = 'key', splitk = ['splitedkey']; k = 'key', splitk = ['splitedkey'];
// wait a little in order to simulate asynchronous operation // wait a little in order to simulate asynchronous operation
setTimeout(function () { setTimeout(function () {
localStor = jioGlobalObj.localStorage.getAll(); localStor = jioGlobalObj.localStorage.getAll();
...@@ -65,221 +59,127 @@ ...@@ -65,221 +59,127 @@
splitk = k.split('/'); splitk = k.split('/');
if (splitk[0] === 'jio' && if (splitk[0] === 'jio' &&
splitk[1] === 'local' && splitk[1] === 'local' &&
splitk[2] === job.userName) { splitk[2] === t.job.userName) {
available = false; return t.done(false);
break;
} }
} }
if (!available) { return t.done(true);
job.status = 'done';
jobendcallback(job);
job.callback({'status':'done',
'message':''+job.userName+
' is not available.',
'isAvailable':false});
} else {
job.status = 'done';
jobendcallback(job);
job.callback({'status':'done',
'message':''+job.userName+
' is available.',
'isAvailable':true});
}
}, 100); }, 100);
}, // end userNameAvailable }, // end userNameAvailable
saveDocument: function ( job, jobendcallback ) { saveDocument: function () {
// Save a document in the local storage // Save a document in the local storage
// job : the job object // this.job.fileName: the document name.
// job.options : the save options object // this.job.fileContent: the document content.
// job.options.overwrite : true -> overwrite // this.job.storage: the storage information.
// job.options.force : true -> save even if jobdate < existingdate // this.job.storage.userName: the user name
// or overwrite: false // this.job.applicant.ID: the applicant id.
// jobendcallback : the function called at the end of the job.
var t = this, doc = null;
// returns {'status':string,'message':string,'isSaved':boolean}
// in the jobendcallback arguments.
var settings = $.extend({
'overwrite':true,'force':false},job.options),
res = {}, doc = null;
// wait a little in order to simulate asynchronous saving // wait a little in order to simulate asynchronous saving
setTimeout (function () { setTimeout (function () {
// reading // reading
doc = jioGlobalObj.localStorage.getItem( doc = jioGlobalObj.localStorage.getItem(
'jio/local/'+job.storage.userName+'/'+job.applicant.ID+'/'+ 'jio/local/'+t.job.storage.userName+'/'+
job.fileName); t.job.applicant.ID+'/'+
if (!doc) { // create document t.job.fileName);
if (!doc) {
// create document
doc = { doc = {
'fileName': job.fileName, 'fileName': t.job.fileName,
'fileContent': job.fileContent, 'fileContent': t.job.fileContent,
'creationDate': job.date, 'creationDate': Date.now(),
'lastModified': job.date 'lastModified': Date.now()
} }
// writing } else {
jioGlobalObj.localStorage.setItem(
'jio/local/'+job.storage.userName+'/'+job.applicant.ID+'/'+
job.fileName, doc);
// return
res.status = job.status = 'done';
res.message = 'Document saved.';
res.isSaved = true;
jobendcallback(job);
job.callback(res);
return;
}
if ( settings.overwrite || settings.force ) {
// if it doesn't force writing
// checking modification date
if ( ! settings.force &&
doc.lastModified >= job.date ) {
// date problem!
// return
res.status = job.status = 'fail';
res.message = 'Document is older than the'+
' existing one.';
res.isSaved = false;
jobendcallback(job);
job.callback(res);
return;
}
// overwriting // overwriting
doc.lastModified = job.date; doc.lastModified = Date.now();
doc.fileContent = job.fileContent; doc.fileContent = t.job.fileContent;
// writing
jioGlobalObj.localStorage.setItem(
'jio/local/'+job.storage.userName+'/'+job.applicant.ID+'/'+
job.fileName, doc);
// return
res.status = job.status = 'done';
res.message = 'Document saved';
res.isSaved = true;
jobendcallback(job);
job.callback(res);
return;
} }
// already exists jioGlobalObj.localStorage.setItem(
res.status = job.status = 'fail'; 'jio/local/'+t.job.storage.userName+'/'+
res.message = 'Document already exists.'; t.job.applicant.ID+'/'+
res.errno = 403; t.job.fileName, doc);
res.isSaved = false; return t.done();
jobendcallback(job);
job.callback(res);
return;
}, 100); }, 100);
}, // end saveDocument }, // end saveDocument
loadDocument: function ( job, jobendcallback ) { loadDocument: function () {
// Load a document from the storage. It returns a document object // Load a document from the storage. It returns a document object
// containing all information of the document and its content. // containing all information of the document and its content.
// job : the job object // this.job.fileName : the document name we want to load.
// job.fileName : the document name we want to load. // this.job.options.getContent: if true, also get the file content.
// jobendcallback : the function called at the end of the job.
// returns {'status':string,'message':string,'document':object}
// in the jobendcallback arguments.
// document object is {'fileName':string,'fileContent':string, // document object is {'fileName':string,'fileContent':string,
// 'creationDate':date,'lastModified':date} // 'creationDate':date,'lastModified':date}
var t = this, res = {}, doc = null; var t = this, doc = null, settings = $.extend(
{'getContent':true},this.job.options);
// wait a little in order to simulate asynchronous operation // wait a little in order to simulate asynchronous operation
setTimeout(function () { setTimeout(function () {
doc = jioGlobalObj.localStorage.getItem( doc = jioGlobalObj.localStorage.getItem(
'jio/local/'+job.storage.userName+'/'+job.applicant.ID+'/'+ 'jio/local/'+t.job.storage.userName+'/'+
job.fileName); t.job.applicant.ID+'/'+t.job.fileName);
if (!doc) { if (!doc) {
res.status = job.status = 'fail'; t.fail('Document not found.',404);
res.errno = 404;
res.message = 'Document not found.';
jobendcallback(job);
job.callback(res);
} else { } else {
res.status = job.status = 'done'; if (!settings.getContent) {
res.message = 'Document loaded.'; delete doc.fileContent;
res.document = { }
'fileContent': doc.fileContent, t.done(doc);
'fileName': doc.fileName,
'creationDate': doc.creationDate,
'lastModified': doc.lastModified};
jobendcallback(job);
job.callback(res);
} }
}, 100); }, 100);
}, // end loadDocument }, // end loadDocument
getDocumentList: function ( job, jobendcallback) { getDocumentList: function () {
// Get a document list from the storage. It returns a document // Get a document list from the storage. It returns a document
// array containing all the user documents informations, but not // array containing all the user documents informations, but not
// their content. // their content.
// job : the job object // this.job.storage: the storage informations.
// jobendcallback : the function called at the end of the job. // this.job.storage.userName: the userName.
// this.job.storage.applicant.ID: the applicant ID.
// returns {'status':string,'message':string,'list':array}
// in the jobendcallback arguments.
// the list is [object,object] -> object = {'fileName':string, // the list is [object,object] -> object = {'fileName':string,
// 'lastModified':date,'creationDate':date} // 'lastModified':date,'creationDate':date}
var t = this, res = {}, localStor = null, k = 'key', var t = this, list = [], localStor = null, k = 'key',
splitk = ['splitedkey']; splitk = ['splitedkey'];
setTimeout(function () { setTimeout(function () {
localStor = jioGlobalObj.localStorage.getAll(); localStor = jioGlobalObj.localStorage.getAll();
res.list = [];
for (k in localStor) { for (k in localStor) {
splitk = k.split('/'); splitk = k.split('/');
if (splitk[0] === 'jio' && if (splitk[0] === 'jio' &&
splitk[1] === 'local' && splitk[1] === 'local' &&
splitk[2] === job.storage.userName && splitk[2] === t.job.storage.userName &&
splitk[3] === job.applicant.ID) { splitk[3] === t.job.applicant.ID) {
fileObject = JSON.parse(localStor[k]); fileObject = JSON.parse(localStor[k]);
res.list.push ({ list.push ({
'fileName':fileObject.fileName, 'fileName':fileObject.fileName,
'creationDate':fileObject.creationDate, 'creationDate':fileObject.creationDate,
'lastModified':fileObject.lastModified}); 'lastModified':fileObject.lastModified});
} }
} }
res.status = job.status = 'done'; t.done(list);
res.message = 'List received.';
jobendcallback(job);
job.callback(res);
}, 100); }, 100);
}, // end getDocumentList }, // end getDocumentList
removeDocument: function ( job, jobendcallback ) { removeDocument: function () {
// Remove a document from the storage. // Remove a document from the storage.
// job : the job object // this.job.storage.userName: the userName.
// jobendcallback : the function called at the end of the job. // this.job.applicant.ID: the applicant ID.
// this.job.fileName: the document name.
// returns {'status':string,'message':string,'isRemoved':boolean}
// in the jobendcallback arguments.
var t = this, res = {}, doc = null; var t = this;
setTimeout (function () { setTimeout (function () {
doc = jioGlobalObj.localStorage.getItem(
'jio/local/'+job.storage.userName+'/'+job.applicant.ID+'/'+
job.fileName);
// already deleted
if (!doc) {
res.status = job.status = 'done';
res.message = 'Document already removed.';
res.isRemoved = true;
jobendcallback(job);
job.callback(res);
return;
}
// deleting // deleting
jioGlobalObj.localStorage.deleteItem( jioGlobalObj.localStorage.deleteItem(
'jio/local/'+ 'jio/local/'+
job.storage.userName+'/'+job.applicant.ID+'/'+ t.job.storage.userName+'/'+t.job.applicant.ID+
job.fileName); '/'+t.job.fileName);
res.status = job.status = 'done'; return t.done();
res.message = 'Document removed.';
res.isRemoved = true;
jobendcallback(job);
job.callback(res);
return;
}, 100); }, 100);
} }
}, },
...@@ -289,8 +189,8 @@ ...@@ -289,8 +189,8 @@
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// DAVStorage // DAVStorage
DAVStorage = function ( options ) { DAVStorage = function ( args ) {
this.job = args.job;
}; };
DAVStorage.prototype = { DAVStorage.prototype = {
mkcol: function ( options ) { mkcol: function ( options ) {
...@@ -354,274 +254,177 @@ ...@@ -354,274 +254,177 @@
} ); } );
} }
}, },
checkNameAvailability: function ( job, jobendcallback ) { checkNameAvailability: function () {
// checks the availability of the [job.userName]. // checks the availability of the [job.userName].
// if the name already exists, it is not available. // if the name already exists, it is not available.
// job: the job object. // this.job.storage: the storage informations.
// job.userName: the name we want to check. // this.job.storage.location: the dav storage location.
// jobendcallback: the function called at the end of the job. // this.job.userName: the name we want to check.
// this.job.storage.userName: the user name.
// this.job.storage.password: the user password.
// returns {'status':string,'message':string,'isAvailable':boolean} var t = this;
// in the jobendcallback arguments.
var res = {};
$.ajax ( { $.ajax ( {
url: job.storage.location + '/dav/' + job.storage.userName + '/', url: t.job.storage.location + '/dav/' + t.job.userName + '/',
async: true, async: true,
type: 'PROPFIND', type: 'PROPFIND',
dataType: 'xml', dataType: 'xml',
headers: {'Authorization': 'Basic '+Base64.encode( headers: {'Authorization': 'Basic '+Base64.encode(
job.storage.userName + ':' + t.job.storage.userName + ':' +
job.storage.password ), Depth: '1'}, t.job.storage.password ), Depth: '1'},
success: function (xmlData) { success: function (xmlData) {
res.status = job.status = 'done'; t.done(false);
res.message = job.userName + ' is not available.';
res.isAvailable = false;
jobendcallback(job);
job.callback(res);
}, },
error: function (type) { error: function (type) {
switch(type.status){ switch(type.status){
case 404: case 404:
res.status = job.status = 'done'; t.done(true);
res.message = job.userName + ' is available.';
res.isAvailable = true;
break; break;
default: default:
res.status = job.status = 'fail'; t.fail('Cannot check if ' + t.job.userName +
res.message = 'Cannot check if ' + job.userName + ' is available.',type.status);
' is available.';
res.isAvailable = false;
break; break;
} }
res.errno = type.status;
jobendcallback(job);
job.callback(res);
} }
} ); } );
}, },
saveDocument: function ( job, jobendcallback ) { saveDocument: function () {
// Save a document in a DAVStorage // Save a document in a DAVStorage
// job: the job object // this.job.storage: the storage informations.
// job.options: the save options object // this.job.storage.userName: the user name.
// job.options.overwrite: true -> overwrite // this.job.storage.password: the user password.
// job.options.force: true -> save even if jobdate < existingdate // this.job.applicant.ID: the applicant ID.
// or overwrite: false // this.job.fileName: the document name.
// jobendcallback: the function called at the end of the job. // this.job.fileContent: the document content.
// returns {'status':string,'message':string,'isSaved':boolean} var t = this;
// in the jobendcallback arguments.
var settings = $.extend ({
'overwrite':true,'force':false},job.options), res = {},
t = this, tmpjob = {},
// TODO if path of /dav/user/applic does not exists, it won't work! // TODO if path of /dav/user/applic does not exists, it won't work!
saveOnDav = function () { //// save on dav
//// save on dav $.ajax ( {
$.ajax ( { url: t.job.storage.location + '/dav/' +
url: job.storage.location + '/dav/' + t.job.storage.userName + '/' +
job.storage.userName + '/' + t.job.applicant.ID + '/' +
job.applicant.ID + '/' + t.job.fileName,
job.fileName, type: 'PUT',
type: 'PUT', data: t.job.fileContent,
data: job.fileContent, async: true,
async: true, dataType: 'text', // TODO is it necessary ?
dataType: 'text', // TODO is it necessary ? headers: {'Authorization':'Basic '+Base64.encode(
headers: {'Authorization':'Basic '+Base64.encode( t.job.storage.userName + ':' + t.job.storage.password )},
job.storage.userName + ':' + job.storage.password )}, // xhrFields: {withCredentials: 'true'}, // cross domain
// xhrFields: {withCredentials: 'true'}, // cross domain success: function () {
success: function () { t.done();
res.status = job.status = 'done'; },
res.message = 'Document saved.'; error: function (type) {
res.isSaved = true; t.fail('Cannot save document.',type.status);
jobendcallback(job);
job.callback(res);
},
error: function (type) {
res.status = job.status = 'fail';
res.message = 'Cannot save document.';
res.errno = type.status;
res.isSaved = false;
jobendcallback(job);
job.callback(res);
}
} );
//// end saving on dav
};
// if force, do not check anything, just save
if (settings.force) {
return saveOnDav();
}
//// start loading document
tmpjob = $.extend({},job);
tmpjob.callback = function(result) {
if(result.status === 'fail') {
switch (result.errno) {
case 404: // Document not found
// TODO MKCOL
// // we can save on it
// t.mkcol({ // create col if not exist
// userName:job.storage.userName,
// password:job.storage.password,
// location:job.storage.location,
// path:'/dav/'+job.storage.userName+'/'+
// job.applicant.ID,
// success:function(){
// // and finaly save document
// saveOnDav()
// },
// error:function(){
// res.status = job.status = 'fail';
// res.message = 'Cannot create document.';
// res.errno = type.status;
// res.isSaved = false;
// jobendcallback(job);
// job.callback(res);
// }});
saveOnDav();
break;
default:
res.status = job.status = 'fail';
res.message = 'Unknown error.';
res.errno = type.status;
res.isSaved = false;
jobendcallback(job);
job.callback(res);
break;
}
} else { // done
// TODO merge files
// Document already exists
if (settings.overwrite) { // overwrite
if (result.document.lastModified >= job.date) {
// date ploblem !
res.status = job.status = 'fail';
res.message = 'Document is older than the '+
'existing one.';
res.isSaved = false;
jobendcallback(job);
job.callback(res);
return;
}
return saveOnDav();
}
// do not overwrite
res.status = job.status = 'fail';
res.message = 'Document already exists.';
res.errno = 403;
res.isSaved = false;
jobendcallback(job);
job.callback(res);
} }
}; } );
this.loadDocument(tmpjob,function(){}); //// end saving on dav
//// end loading document
}, },
loadDocument: function ( job, jobendcallback ) { loadDocument: function () {
// Load a document from a DAVStorage. It returns a document object // Load a document from a DAVStorage. It returns a document object
// containing all information of the document and its content. // containing all information of the document and its content.
// job: the job object // this.job.fileName: the document name we want to load.
// job.fileName: the document name we want to load. // this.job.storage: the storage informations.
// jobendcallback: the function called at the end of the job. // this.job.storage.location: the dav storage location.
// this.job.storage.userName: the user name.
// this.job.storage.password: the user password.
// this.job.options.getContent: if true, also get the file content.
// returns {'status':string,'message':string,'document':object}
// in the jobendcallback arguments.
// document object is {'fileName':string,'fileContent':string, // document object is {'fileName':string,'fileContent':string,
// 'creationDate':date,'lastModified':date} // 'creationDate':date,'lastModified':date}
var t = this, doc = {},
settings = $.extend({'getContent':true},this.job.options),
// TODO check if job's features are good // TODO check if job's features are good
var res = {'document':{}},
getContent = function () { getContent = function () {
$.ajax ( { $.ajax ( {
url: job.storage.location + '/dav/' + url: t.job.storage.location + '/dav/' +
job.storage.userName + '/' + t.job.storage.userName + '/' +
job.applicant.ID + '/' + t.job.applicant.ID + '/' +
job.fileName, t.job.fileName,
type: "GET", type: "GET",
async: true, async: true,
dataType: 'text', // TODO is it necessary ? dataType: 'text', // TODO is it necessary ?
headers: {'Authorization':'Basic '+Base64.encode( headers: {'Authorization':'Basic '+Base64.encode(
job.storage.userName + ':' + t.job.storage.userName + ':' +
job.storage.password )}, t.job.storage.password )},
// xhrFields: {withCredentials: 'true'}, // cross domain // xhrFields: {withCredentials: 'true'}, // cross domain
success: function (content) { success: function (content) {
res.status = job.status = 'done'; doc.fileContent = content;
res.message = 'Document loaded.'; t.done(doc);
res.document.fileContent = content;
jobendcallback(job);
job.callback(res);
}, },
error: function (type) { error: function (type) {
var message;
switch (type.status) { switch (type.status) {
case 404: case 404:
res.message = 'Document not found.'; break; message = 'Document not found.'; break;
default: default:
res.message = 'Cannot load "' + job.fileName + '".'; message = 'Cannot load "' + job.fileName + '".';
break; break;
} }
res.status = job.status = 'fail'; t.fail(message,type.status);
res.errno = type.status;
jobendcallback(job);
job.callback(res);
} }
} ); } );
} }
// Get properties // Get properties
$.ajax ( { $.ajax ( {
url: job.storage.location + '/dav/' + url: t.job.storage.location + '/dav/' +
job.storage.userName + '/' + t.job.storage.userName + '/' +
job.applicant.ID + '/' + t.job.applicant.ID + '/' +
job.fileName, t.job.fileName,
type: "PROPFIND", type: "PROPFIND",
async: true, async: true,
dataType: 'xml', dataType: 'xml',
headers: {'Authorization':'Basic '+Base64.encode( headers: {'Authorization':'Basic '+Base64.encode(
job.storage.userName + ':' + t.job.storage.userName + ':' +
job.storage.password )}, t.job.storage.password )},
success: function (xmlData) { success: function (xmlData) {
res.document.lastModified = ( doc.lastModified = (
new Date($($("lp1\\:getlastmodified", new Date($($("lp1\\:getlastmodified",
xmlData).get(0)).text())).getTime(); xmlData).get(0)).text())).getTime();
res.document.creationDate = ( doc.creationDate = (
new Date($($("lp1\\:creationdate", new Date($($("lp1\\:creationdate",
xmlData).get(0)).text())).getTime(); xmlData).get(0)).text())).getTime();
res.document.fileName = job.fileName; doc.fileName = t.job.fileName;
getContent(); if (settings.getContent) {
getContent();
} else {
t.done(doc);
}
}, },
error: function (type) { error: function (type) {
res.status = job.status = 'fail'; t.fail('Cannot get document informations.',type.status);
res.message = 'Cannot get document informations.';
res.errno = type.status;
jobendcallback(job);
job.callback(res);
} }
} ); } );
}, },
getDocumentList: function ( job, jobendcallback ) { getDocumentList: function () {
// Get a document list from a DAVStorage. It returns a document // Get a document list from a DAVStorage. It returns a document
// array containing all the user documents informations, but their // array containing all the user documents informations, but their
// content. // content.
// job: the job object // this.job.storage: the storage informations.
// jobendcallback: the function called at the end of the job. // this.job.storage.location: the dav storage location.
// this.job.storage.userName: the user name.
// returns {'status':string,'message':string,'list':array} // this.job.storage.password: the user password.
// in the jobendcallback arguments. // this.job.applicant.ID: the applicant id.
// the list is [object,object] -> object = {'fileName':string, // the list is [object,object] -> object = {'fileName':string,
// 'lastModified':date,'creationDate':date} // 'lastModified':date,'creationDate':date}
var res = {}, documentArrayList = [], file = {}, pathArray = []; var t = this, documentArrayList = [], file = {}, pathArray = [];
$.ajax ( { $.ajax ( {
url: job.storage.location + '/dav/' + url: t.job.storage.location + '/dav/' +
job.storage.userName + '/' + job.applicant.ID + '/', t.job.storage.userName + '/' + t.job.applicant.ID + '/',
async: true, async: true,
type: 'PROPFIND', type: 'PROPFIND',
dataType: 'xml', dataType: 'xml',
headers: {'Authorization': 'Basic '+Base64.encode( headers: {'Authorization': 'Basic '+Base64.encode(
job.storage.userName + ':' + t.job.storage.userName + ':' +
job.storage.password ), Depth: '1'}, t.job.storage.password ), Depth: '1'},
success: function (xmlData) { success: function (xmlData) {
$("D\\:response",xmlData).each(function(i,data) { $("D\\:response",xmlData).each(function(i,data) {
if(i>0) { // exclude parent folder if(i>0) { // exclude parent folder
...@@ -642,101 +445,78 @@ ...@@ -642,101 +445,78 @@
documentArrayList.push (file); documentArrayList.push (file);
} }
}); });
res.status = job.status = 'done'; t.done(documentArrayList);
res.message = 'List received.';
res.list = documentArrayList;
jobendcallback(job);
job.callback(res);
}, },
error: function (type) { error: function (type) {
res.status = job.status = 'fail'; t.fail('Cannot get list.',type.status);
res.message = 'Cannot get list.';
res.errno = type.status;
jobendcallback(job);
job.callback(res);
} }
} ); } );
}, },
removeDocument: function ( job, jobendcallback ) { removeDocument: function ( job, jobendcallback ) {
// Remove a document from a DAVStorage. // Remove a document from a DAVStorage.
// job: the job object // this.job.fileName: the document name we want to remove.
// jobendcallback: the function called at the end of the job. // this.job.storage: the storage informations.
// this.job.storage.location: the dav storage location.
// this.job.storage.userName: the user name.
// this.job.storage.password: the user password.
// this.job.applicant.ID: the applicant id.
// returns {'status':string,'message':string,'isRemoved':boolean} var t = this;
// in the jobendcallback arguments.
var res = {};
$.ajax ( { $.ajax ( {
url: job.storage.location + '/dav/' + url: t.job.storage.location + '/dav/' +
job.storage.userName + '/' + t.job.storage.userName + '/' +
job.applicant.ID + '/' + t.job.applicant.ID + '/' +
job.fileName, t.job.fileName,
type: "DELETE", type: "DELETE",
async: true, async: true,
headers: {'Authorization':'Basic '+Base64.encode( headers: {'Authorization':'Basic '+Base64.encode(
job.storage.userName + ':' + t.job.storage.userName + ':' +
job.storage.password )}, t.job.storage.password )},
// xhrFields: {withCredentials: 'true'}, // cross domain // xhrFields: {withCredentials: 'true'}, // cross domain
success: function () { success: function () {
res.status = job.status = 'done'; t.done();
res.message = 'Document removed.';
res.isRemoved = true;
jobendcallback(job);
job.callback(res);
}, },
error: function (type) { error: function (type) {
switch (type.status) { switch (type.status) {
case 404: case 404:
res.stauts = job.status = 'done'; t.done();
res.message = 'Document already removed.';
res.errno = type.status;
res.isRemoved = true;
break; break;
default: default:
res.status = job.status = 'fail'; t.fail('Cannot remove "' + t.job.fileName + '".',type.status);
res.message = 'Cannot remove "' + job.fileName + '".';
res.isRemoved = false;
res.errno = type.status;
break; break;
} }
jobendcallback(job);
job.callback(res);
} }
} ); } );
} }
}, },
// end DAVStorage // end DAVStorage
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// ReplicateStorage // ReplicateStorage
ReplicateStorage = function ( options ) { ReplicateStorage = function ( args ) {
// TODO Add a tests that check if there is no duplicate storages. // TODO Add a tests that check if there is no duplicate storages.
this.queue = options.queue; this.queue = args.queue;
this.job = args.job;
this.id = null; this.id = null;
this.length = options.storage.storageArray.length; this.length = args.job.storage.storageArray.length;
this.returnsValuesArray = []; this.returnsValuesArray = [];
}; };
ReplicateStorage.prototype = { ReplicateStorage.prototype = {
checkNameAvailability: function ( job, jobendcallback ) { checkNameAvailability: function () {
// Checks the availability of the [job.userName]. // Checks the availability of the [job.userName].
// if the name already exists in a storage, it is not available. // if the name already exists in a storage, it is not available.
// job: the job object. // this.job.userName: the name we want to check.
// job.userName: the name we want to check. // this.job.storage.storageArray: An Array of storages.
// job.storage.storageArray: An Array of storages.
// jobendcallback: the function called at the end of the job.
// returns {'status':string,'message':string,'isAvailable':boolean,
// 'resultArray':Array} in the jobendcallback arguments.
var t = this, newjob = {}, isavailable = true, var t = this, newjob = {}, isavailable = true,
res = {'status':'done'}, i = 'ind'; res = {'status':'done'}, i = 'ind';
for (i in job.storage.storageArray) { for (i in t.job.storage.storageArray) {
newjob = $.extend({},job); newjob = $.extend({},t.job);
newjob.storage = job.storage.storageArray[i]; newjob.storage = t.job.storage.storageArray[i];
newjob.callback = function (result){ newjob.callback = function (result) {
t.returnsValuesArray.push(result); t.returnsValuesArray.push(result);
if (result.status === 'fail') { if (result.status === 'fail') {
res.status = 'fail'; res.status = 'fail';
...@@ -744,17 +524,13 @@ ...@@ -744,17 +524,13 @@
if (!result.isAvailable) { isavailable = false; } if (!result.isAvailable) { isavailable = false; }
if (t.returnsValuesArray.length === t.length) { if (t.returnsValuesArray.length === t.length) {
// if this is the last callback // if this is the last callback
job.status = res.status; t.done(isavailable);
res.resultArray = t.returnsValuesArray;
res.isAvailable = isavailable;
jobendcallback(job);
job.callback(res);
} }
}; };
this.queue.createJob ( newjob ) ; this.queue.createJob ( newjob ) ;
} }
}, },
saveDocument: function ( job, jobendcallback ) { saveDocument: function () {
// Save a single document in several storages. // Save a single document in several storages.
// If a storage failed to save the document, it modify the job in // If a storage failed to save the document, it modify the job in
// in order to invoke it sometime later. // in order to invoke it sometime later.
...@@ -770,13 +546,13 @@ ...@@ -770,13 +546,13 @@
// TODO // TODO
}, },
loadDocument: function ( job, jobendcallback ) { loadDocument: function () {
// TODO // TODO
}, },
getDocumentList: function ( job, jobendcallback ) { getDocumentList: function () {
// TODO // TODO
}, },
removeDocument: function ( job, jobendcallback ) { removeDocument: function () {
// TODO // TODO
} }
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment