Commit e862dbff authored by Tristan Cavelier's avatar Tristan Cavelier

Merge branch 'attachments' into revision_storage

parents 3635597f 4a43816a
......@@ -138,6 +138,7 @@ var clearlog = function () {
<div id="log">
</div>
<script type="text/javascript" src="../localorcookiestorage.js"></script>
<script type="text/javascript" src="../lib/md5/md5.js"></script>
<script type="text/javascript" src="../jio.js"></script>
<script type="text/javascript" src="../lib/jquery/jquery.min.js"></script>
<script type="text/javascript" src="../lib/base64/base64.js"></script>
......@@ -217,7 +218,7 @@ var callback = function (err,val,begin_date) {
log ('return : ' + JSON.stringify (val));
};
var command = function (method) {
var begin_date = Date.now(), doc = {}, opts = {}, other = {};
var begin_date = Date.now(), doc = {}, opts = {};
log (method);
if (!my_jio) {
return error ('no jio set');
......@@ -230,14 +231,11 @@ var command = function (method) {
switch (method) {
case 'putAttachment':
other.docid = $('#document_id').attr('value');
other.revision = $('#prev_rev').attr('value');
other.content = $('#content').attr('value');
other.mimetype = $('#mimetype').attr('value');
log ('docid: '+ other.docid);
log ('revision: '+ other.revision);
log ('content: '+ other.content);
log ('mimetype: '+ other.mimetype);
doc.id = $('#document_id').attr('value');
doc.rev = $('#prev_rev').attr('value');
doc.data = $('#content').attr('value');
doc.mimetype = $('#mimetype').attr('value');
log ('attachment: '+ JSON.stringify (doc));
break;
case 'post':
case 'put':
......@@ -260,6 +258,7 @@ var command = function (method) {
log ('opts: ' + JSON.stringify (opts));
switch (method) {
case "putAttachment":
case 'remove':
case 'post':
case 'put':
......@@ -273,14 +272,6 @@ var command = function (method) {
callback(err,val,begin_date);
});
break;
case 'putAttachment':
my_jio[method](
other.docid, other.revision, other.content,
other.mimetype, opts, function (err, val) {
callback(err,val,begin_date);
}
);
break;
}
};
var post = function () {
......
......@@ -17,6 +17,7 @@ var log = function (o) {
<div id="log">
</div>
<script type="text/javascript" src="../localorcookiestorage.js"></script>
<script type="text/javascript" src="../lib/md5/md5.js"></script>
<script type="text/javascript" src="../jio.js"></script>
<script type="text/javascript" src="../lib/jquery/jquery.min.js"></script>
<script type="text/javascript" src="../lib/base64/base64.js"></script>
......@@ -28,29 +29,50 @@ var log = function (o) {
var my_jio = null;
log ('Welcome to the jIO example.html!')
log ('--> Create jIO instance');
log ('-> Create jIO instance');
my_jio = jIO.newJio({
type: 'local', username: 'jIOtest', applicationname: 'example'
});
log ('--> put "hello" document to localStorage');
// careful ! asynchronous method
my_jio.put({_id:'hello',content:'world'},function (val) {
log ('done');
// careful ! asynchronous methods
log ('-> post "video" document metadata to localStorage');
my_jio.post({_id:'video', title:'My Video Title', codec:'vorbis', language:'en', description: 'Image compilation'}, function (val) {
log ('-> put "thumbnail" attachment to localStorage');
my_jio.putAttachment({id:"video/thumb.jpg", data:"BASE64DATA", mimetype:'image/jpeg'}, function (val) {
log ('-> put "video" attachment to localStorage');
my_jio.putAttachment({id:"video/myvideo.ogg", data:"BASE64DATATOO", mimetype:'video/ogg'}, function (val) {
log ('Done! Refresh the page to see get and remove command.');
}, function (err) {
log ('Error! '+ err.reason);
});
}, function (err) {
log ('Error! ' + err.reason);
});
}, function (err) {
log ('error!');
});
log ('Error! ' + err.reason);
log ('-> get "video" document metadata from localStorage');
my_jio.get('video', function (val) {
log ('Title is: "' + val["title"] + '"');
setTimeout ( function () {
log ('--> get "hello" document from localStorage');
log ('-> remove "video" document from localStorage');
my_jio.remove({_id:'video'}, function (val) {
log ('Done! Refresh the page to see post and putAttachment command.');
}, function (err) {
log ('Error! ' + err.reason);
});
my_jio.get('hello',function (val) {
log ('done, content: ' + val.content);
}, function (err) {
log ('error!');
log ('Error! ' + err.reason);
});
}, 500);
});
//-->
</script>
</body>
......
......@@ -88,6 +88,7 @@ module.exports = function(grunt) {
},
globals: {
LocalOrCookieStorage: true,
hex_md5: true,
console: true,
unescape: true,
// Needed to avoid "not defined error" with requireJs
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
}( LocalOrCookieStorage, jQuery, Base64, sjcl, hex_sha256, jIO ));
}(jIO, jQuery, Base64, sjcl, hex_sha256));
......@@ -14,7 +14,7 @@ var activityUpdater = (function(spec, my) {
* @method touch
*/
priv.touch = function() {
LocalOrCookieStorage.setItem ('jio/id/'+priv.id, Date.now());
localstorage.setItem ('jio/id/'+priv.id, Date.now());
};
/**
......@@ -72,4 +72,3 @@ var activityUpdater = (function(spec, my) {
return that;
}());
var _allDocsCommand = function(spec, my) {
var that = command(spec, my);
spec = spec || {};
my = my || {};
// Attributes //
// Methods //
that.getLabel = function() {
return '_allDocs';
};
that.executeOn = function(storage) {
storage._allDocs (that);
};
that.canBeRestored = function() {
return false;
};
that.validateState = function () {
return true;
};
return that;
};
var _getCommand = function(spec, my) {
var that = command(spec, my);
spec = spec || {};
my = my || {};
// Attributes //
// Methods //
that.getLabel = function() {
return '_get';
};
that.validateState = function() {
if (!that.getDocId()) {
that.error({
status:20,statusText:'Document Id Required',
error:'document_id_required',
message:'No document id.',reason:'no document id'
});
return false;
}
return true;
};
that.executeOn = function(storage) {
storage._get (that);
};
that.canBeRestored = function() {
return false;
};
return that;
};
var _postCommand = function(spec, my) {
var that = command(spec, my);
spec = spec || {};
my = my || {};
// Attributes //
var priv = {};
// Methods //
that.getLabel = function() {
return '_post';
};
that.executeOn = function(storage) {
storage._post (that);
};
return that;
};
var _putAttachmentCommand = function(spec, my) {
var that = command(spec, my);
spec = spec || {};
my = my || {};
// Attributes //
// Methods //
that.getLabel = function () {
return '_putAttachment';
};
that.executeOn = function (storage) {
storage._putAttachment (that);
};
that.validateState = function () {
if (typeof that.getContent() !== 'string') {
that.error({
status:22,statusText:'Content Required',
error:'content_required',
message:'No data to put.',reason:'no data to put'
});
return false;
}
return true;
};
return that;
};
var _putCommand = function(spec, my) {
var that = command(spec, my);
spec = spec || {};
my = my || {};
// Attributes //
var priv = {};
// Methods //
that.getLabel = function() {
return '_put';
};
/**
* Validates the storage handler.
* @param {object} handler The storage handler
*/
that.validate = function () {
return that.validateState();
};
that.executeOn = function(storage) {
storage._put (that);
};
return that;
};
var _removeCommand = function(spec, my) {
var that = command(spec, my);
spec = spec || {};
my = my || {};
// Attributes //
// Methods //
that.getLabel = function() {
return '_remove';
};
that.executeOn = function(storage) {
storage._remove (that);
};
return that;
};
......@@ -11,12 +11,6 @@ var command = function(spec, my) {
'remove':removeCommand,
'allDocs':allDocsCommand,
'putAttachment':putAttachmentCommand
'_post':_postCommand,
'_put':_putCommand,
'_get':_getCommand,
'_remove':_removeCommand,
'_allDocs':_allDocsCommand,
'_putAttachment':_putAttachmentCommand
};
// creates the good command thanks to his label
if (spec.label && priv.commandlist[spec.label]) {
......@@ -27,7 +21,7 @@ var command = function(spec, my) {
priv.tried = 0;
priv.doc = spec.doc || {};
priv.docid = spec.docid || spec.doc._id || '';
priv.docid = spec.docid || priv.doc._id;
priv.option = spec.options || {};
priv.callbacks = spec.callbacks || {};
priv.success = priv.callbacks.success || function (){};
......@@ -42,6 +36,20 @@ var command = function(spec, my) {
priv.on_going = false;
// Methods //
/**
* Returns a serialized version of this command.
* @method super_serialized
* @return {object} The serialized command.
*/
that.super_serialized = function () {
var o = that.serialized() || {};
o["label"] = that.getLabel();
o["tried"] = priv.tried;
o["doc"] = that.cloneDoc();
o["option"] = that.cloneOption();
return o;
};
/**
* Returns a serialized version of this command.
* Override this function.
......@@ -49,10 +57,7 @@ var command = function(spec, my) {
* @return {object} The serialized command.
*/
that.serialized = function() {
return {label:that.getLabel(),
tried:priv.tried,
doc:that.cloneDoc(),
option:that.cloneOption()};
return {};
};
/**
......@@ -70,6 +75,9 @@ var command = function(spec, my) {
* @return {string} The document id
*/
that.getDocId = function () {
if (typeof priv.docid !== "string") {
return undefined;
}
return priv.docid.split('/')[0];
};
......@@ -79,6 +87,9 @@ var command = function(spec, my) {
* @return {string} The attachment id
*/
that.getAttachmentId = function () {
if (typeof priv.docid !== "string") {
return undefined;
}
return priv.docid.split('/')[1];
};
......@@ -91,6 +102,42 @@ var command = function(spec, my) {
return priv.doc;
};
/**
* Returns the data of the attachment
* @method getAttachmentData
* @return {string} The data
*/
that.getAttachmentData = function () {
return priv.doc._data;
};
/**
* Returns the data length of the attachment
* @method getAttachmentLength
* @return {number} The length
*/
that.getAttachmentLength = function () {
return priv.doc._data.length;
};
/**
* Returns the mimetype of the attachment
* @method getAttachmentMimeType
* @return {string} The mimetype
*/
that.getAttachmentMimeType = function () {
return priv.doc._mimetype;
};
/**
* Generate the md5sum of the attachment data
* @method md5SumAttachmentData
* @return {string} The md5sum
*/
that.md5SumAttachmentData = function () {
return hex_md5(priv.doc._data);
};
/**
* Returns an information about the document.
* @method getDocInfo
......@@ -116,7 +163,8 @@ var command = function(spec, my) {
* @param {object} storage The storage.
*/
that.validate = function (storage) {
if (!(priv.docid || priv.doc._id).match(/^[^\/]+([\/][^\/]+)?$/)) {
if (typeof priv.docid === "string" &&
!priv.docid.match(/^[^\/]+([\/][^\/]+)?$/)) {
that.error({
status:21,statusText:'Invalid Document Id',
error:'invalid_document_id',
......@@ -253,11 +301,7 @@ var command = function(spec, my) {
* @return {object} The clone of the command options.
*/
that.cloneOption = function () {
var k, o = {};
for (k in priv.option) {
o[k] = priv.option[k];
}
return o;
return JSON.parse(JSON.stringify(priv.option));
};
/**
......@@ -266,14 +310,7 @@ var command = function(spec, my) {
* @return {object} The clone of the document.
*/
that.cloneDoc = function () {
if (priv.docid) {
return priv.docid;
}
var k, o = {};
for (k in priv.doc) {
o[k] = priv.doc[k];
}
return o;
return JSON.parse(JSON.stringify(priv.doc));
};
return that;
......
......@@ -9,14 +9,28 @@ var getCommand = function(spec, my) {
};
that.validateState = function() {
if (!that.getDocId()) {
if (!(typeof that.getDocId() === "string" && that.getDocId() !== "")) {
that.error({
status:20,statusText:'Document Id Required',
error:'document_id_required',
message:'No document id.',reason:'no document id'
"status": 20,
"statusText": "Document Id Required",
"error": "document_id_required",
"message": "The document id is not provided",
"reason": "Document id is undefined"
});
return false;
}
if (typeof that.getAttachmentId() === "string") {
if (that.getAttachmentId() === "") {
that.error({
"status": 23,
"statusText": "Invalid Attachment Id",
"error": "invalid_attachment_id",
"message": "The attachment id must not be an empty string",
"reason": "Attachment id is empty"
});
}
return false;
}
return true;
};
......
......@@ -10,6 +10,21 @@ var postCommand = function(spec, my) {
return 'post';
};
that.validateState = function () {
if (typeof that.getAttachmentId() !== "undefined") {
that.error({
"status": 21,
"statusText": "Invalid Document Id",
"error": "invalid_document_id",
"message": "The document id contains '/' characters "+
"which are forbidden",
"reason": "Document id contains '/' character(s)"
});
return false;
}
return true;
};
that.executeOn = function(storage) {
storage.post (that);
};
......
......@@ -11,15 +11,27 @@ var putAttachmentCommand = function(spec, my) {
that.executeOn = function (storage) {
storage.putAttachment (that);
};
that.validateState = function () {
if (typeof that.getContent() !== 'string') {
if (typeof that.getAttachmentId() !== "string") {
that.error({
status:22,statusText:'Content Required',
error:'content_required',
message:'No data to put.',reason:'no data to put'
"status": 22,
"statusText": "Attachment Id Required",
"error": "attachment_id_required",
"message": "The attachment id must be set",
"reason": "Attachment id not set"
});
return false;
}
if (that.getAttachmentId() === "") {
that.error({
"status": 23,
"statusText": "Invalid Attachment Id",
"error": "invalid_attachment_id",
"message": "The attachment id must not be an empty string",
"reason": "Attachment id is empty"
});
}
return true;
};
......
......@@ -10,12 +10,29 @@ var putCommand = function(spec, my) {
return 'put';
};
/**
* Validates the storage handler.
* @param {object} handler The storage handler
*/
that.validate = function () {
return that.validateState();
that.validateState = function () {
if (!(typeof that.getDocId() === "string" && that.getDocId() !== "")) {
that.error({
"status": 20,
"statusText": "Document Id Required",
"error": "document_id_required",
"message": "The document id is not provided",
"reason": "Document id is undefined"
});
return false;
}
if (typeof that.getAttachmentId() !== "undefined") {
that.error({
"status": 21,
"statusText": "Invalid Document Id",
"error": "invalid_document_id",
"message": "The document id contains '/' characters "+
"which are forbidden",
"reason": "Document id contains '/' character(s)"
});
return false;
}
return true;
};
that.executeOn = function(storage) {
......
......@@ -8,6 +8,32 @@ var removeCommand = function(spec, my) {
return 'remove';
};
that.validateState = function() {
if (!(typeof that.getDocId() === "string" && that.getDocId() !== "")) {
that.error({
"status": 20,
"statusText": "Document Id Required",
"error": "document_id_required",
"message": "The document id is not provided",
"reason": "Document id is undefined"
});
return false;
}
if (typeof that.getAttachmentId() === "string") {
if (that.getAttachmentId() === "") {
that.error({
"status": 23,
"statusText": "Invalid Attachment Id",
"error": "invalid_attachment_id",
"message": "The attachment id must not be an empty string",
"reason": "Attachment id is empty"
});
}
return false;
}
return true;
};
that.executeOn = function(storage) {
storage.remove (that);
};
......
var jIO = (function () {
(function (scope, hex_md5) {
"use strict";
var localstorage;
if (typeof localStorage !== "undefined") {
localstorage = {
getItem: function (item) {
return JSON.parse(localStorage.getItem(item));
},
setItem: function (item, value) {
return localStorage.setItem(item, JSON.stringify(value));
},
deleteItem: function (item) {
delete localStorage[item];
},
clone: function () {
return JSON.parse(JSON.stringify(localStorage));
}
};
} else {
(function () {
var pseudo_localStorage = {};
localstorage = {
getItem: function (item) {
return JSON.parse(pseudo_localStorage[item]);
},
setItem: function (item, value) {
return pseudo_localStorage[item] = JSON.stringify(value);
},
deleteItem: function (item) {
delete pseudo_localStorage[item];
},
clone: function () {
return JSON.parse(JSON.stringify(pseudo_localStorage));
}
};
}());
}
......@@ -12,7 +12,7 @@
// Initialize the jio id and add the new id to the list
if (priv.id === null) {
var i, jio_id_a =
LocalOrCookieStorage.getItem (jio_id_array_name) || [];
localstorage.getItem (jio_id_array_name) || [];
priv.id = 1;
for (i = 0; i < jio_id_a.length; i+= 1) {
if (jio_id_a[i] >= priv.id) {
......@@ -20,7 +20,7 @@
}
}
jio_id_a.push(priv.id);
LocalOrCookieStorage.setItem (jio_id_array_name,jio_id_a);
localstorage.setItem (jio_id_array_name,jio_id_a);
activityUpdater.setId(priv.id);
jobManager.setId(priv.id);
}
......@@ -143,6 +143,8 @@
} else {
param.callback = callback1;
}
} else {
param.callback = function () {};
}
};
......@@ -176,7 +178,8 @@
/**
* Post a document.
* @method post
* @param {object} doc The document {"content":}.
* @param {object} doc The document object. Contains at least:
* - {string} _id The document id (optional), "/" are forbidden
* @param {object} options (optional) Contains some options:
* - {number} max_retry The number max of retries, 0 = infinity.
* - {boolean} revs Include revision history of the document.
......@@ -206,7 +209,8 @@
/**
* Put a document.
* @method put
* @param {object} doc The document {"_id":,"_rev":,"content":}.
* @param {object} doc The document object. Contains at least:
* - {string} _id The document id, "/" are forbidden
* @param {object} options (optional) Contains some options:
* - {number} max_retry The number max of retries, 0 = infinity.
* - {boolean} revs Include revision history of the document.
......@@ -236,7 +240,7 @@
/**
* Get a document.
* @method get
* @param {string} docid The document id (the path).
* @param {string} docid The document id: "doc_id" or "doc_id/attachmt_id".
* @param {object} options (optional) Contains some options:
* - {number} max_retry The number max of retries, 0 = infinity.
* - {string} rev The revision we want to get.
......@@ -267,7 +271,8 @@
/**
* Remove a document.
* @method remove
* @param {object} doc The document {"_id":,"_rev":}.
* @param {object} doc The document object. Contains at least:
* - {string} _id The document id: "doc_id" or "doc_id/attachment_id"
* @param {object} options (optional) Contains some options:
* - {number} max_retry The number max of retries, 0 = infinity.
* - {boolean} revs Include revision history of the document.
......@@ -312,7 +317,7 @@
configurable:false,enumerable:false,writable:false,value:
function(options, success, error) {
var param = priv.parametersToObject(
[options,success.error],
[options,success,error],
{max_retry: 3}
);
......@@ -326,10 +331,11 @@
/**
* Put an attachment to a document.
* @method putAttachment
* @param {string} id The attachment id ("document/attachment").
* @param {string} rev The document revision.
* @param {string} doc Base64 attachment content.
* @param {string} mimetype The attachment mimetype
* @param {object} doc The document object. Contains at least:
* - {string} id The document id: "doc_id/attchment_id"
* - {string} data Base64 attachment data
* - {string} mimetype The attachment mimetype
* - {string} rev The attachment revision
* @param {object} options (optional) Contains some options:
* - {number} max_retry The number max of retries, 0 = infinity.
* - {boolean} revs Include revision history of the document.
......@@ -342,14 +348,18 @@
*/
Object.defineProperty(that,"putAttachment",{
configurable:false,enumerable:false,writable:false,value:
function(id, rev, doc, mimetype, options, success, error) {
var param = priv.parametersToObject(
function(doc, options, success, error) {
var param, k, doc_with_underscores = {};
param = priv.parametersToObject(
[options, success, error],
{max_retry: 0}
);
for (k in doc) {
doc_with_underscores["_"+k] = doc[k];
}
console.log (doc_with_underscores);
priv.addJob(putAttachmentCommand,{
doc:{_id:id,content:doc,_rev:rev,mimetype:mimetype},
doc:doc_with_underscores,
options:param.options,
callbacks:{success:param.success,error:param.error}
});
......
......@@ -25,7 +25,7 @@ var jobManager = (function(spec) {
* @return {array} The job array.
*/
priv.getJobArray = function() {
return LocalOrCookieStorage.getItem(priv.getJobArrayName())||[];
return localstorage.getItem(priv.getJobArrayName())||[];
};
/**
......@@ -37,7 +37,7 @@ var jobManager = (function(spec) {
for (i = 0; i < priv.job_array.length; i+= 1) {
new_a.push(priv.job_array[i].serialized());
}
LocalOrCookieStorage.setItem(priv.getJobArrayName(),new_a);
localstorage.setItem(priv.getJobArrayName(),new_a);
};
/**
......@@ -90,7 +90,7 @@ var jobManager = (function(spec) {
clearInterval(priv.interval_id);
priv.interval_id = null;
if (priv.job_array.length === 0) {
LocalOrCookieStorage.deleteItem(priv.getJobArrayName());
localstorage.deleteItem(priv.getJobArrayName());
}
}
};
......@@ -105,7 +105,7 @@ var jobManager = (function(spec) {
var i, jio_id_a;
priv.lastrestore = priv.lastrestore || 0;
if (priv.lastrestore > (Date.now()) - 2000) { return; }
jio_id_a = LocalOrCookieStorage.getItem('jio/id_array')||[];
jio_id_a = localstorage.getItem('jio/id_array')||[];
for (i = 0; i < jio_id_a.length; i+= 1) {
priv.restoreOldJioId(jio_id_a[i]);
}
......@@ -119,7 +119,7 @@ var jobManager = (function(spec) {
*/
priv.restoreOldJioId = function(id) {
var jio_date;
jio_date = LocalOrCookieStorage.getItem('jio/id/'+id)||0;
jio_date = localstorage.getItem('jio/id/'+id)||0;
if (new Date(jio_date).getTime() < (Date.now() - 10000)) { // 10 sec
priv.restoreOldJobFromJioId(id);
priv.removeOldJioId(id);
......@@ -134,7 +134,7 @@ var jobManager = (function(spec) {
*/
priv.restoreOldJobFromJioId = function(id) {
var i, jio_job_array;
jio_job_array = LocalOrCookieStorage.getItem('jio/job_array/'+id)||[];
jio_job_array = localstorage.getItem('jio/job_array/'+id)||[];
for (i = 0; i < jio_job_array.length; i+= 1) {
var command_object = command(jio_job_array[i].command);
if (command_object.canBeRestored()) {
......@@ -152,14 +152,14 @@ var jobManager = (function(spec) {
*/
priv.removeOldJioId = function(id) {
var i, jio_id_array, new_array = [];
jio_id_array = LocalOrCookieStorage.getItem('jio/id_array')||[];
jio_id_array = localstorage.getItem('jio/id_array')||[];
for (i = 0; i < jio_id_array.length; i+= 1) {
if (jio_id_array[i] !== id) {
new_array.push(jio_id_array[i]);
}
}
LocalOrCookieStorage.setItem('jio/id_array',new_array);
LocalOrCookieStorage.deleteItem('jio/id/'+id);
localstorage.setItem('jio/id_array',new_array);
localstorage.deleteItem('jio/id/'+id);
};
/**
......@@ -168,7 +168,7 @@ var jobManager = (function(spec) {
* @param {number} id The jio id.
*/
priv.removeJobArrayFromJioId = function(id) {
LocalOrCookieStorage.deleteItem('jio/job_array/'+id);
localstorage.deleteItem('jio/job_array/'+id);
};
/**
......
return jioNamespace;
}());
Object.defineProperty(scope,"jIO",{
configurable:false,enumerable:false,writable:false,value:jioNamespace
});
}(window, hex_md5));
This diff is collapsed.
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