Commit 7bfedd00 authored by Sven Franck's avatar Sven Franck

updated version of erp5storage to handle offline

parent 53e7dcba
/* /*
* Copyright 2013, Nexedi SA * JIO extension for resource replication.
* Released under the LGPL license. * Copyright (C) 2013 Nexedi SA
* http://www.gnu.org/licenses/lgpl.html *
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
// JIO ERP5 Storage Description :
// {
// type: "erp5"
// url: {string}
// }
/*jslint indent: 2, nomen: true, unparam: true */ /*jslint indent: 2, nomen: true, unparam: true */
/*global jIO, complex_queries, console, UriTemplate, FormData, RSVP, URI */ /*global jIO, complex_queries, UriTemplate, FormData, RSVP, URI */
(function (jIO, complex_queries, URI) { (function (jIO, complex_queries, URI) {
"use strict"; "use strict";
/**
* The JIO ERP5storage extension
*
* @class ERP5Storage
* @constructor
* @param {Object} spec Storage definition
*/
function ERP5Storage(spec) { function ERP5Storage(spec) {
if (typeof spec.url !== 'string' && !spec.url) { if (typeof spec.url !== 'string' && !spec.url) {
throw new TypeError("ERP5 'url' must be a string " + throw new TypeError("ERP5 'url' must be a string " +
...@@ -23,19 +36,43 @@ ...@@ -23,19 +36,43 @@
this._url = spec.url; this._url = spec.url;
} }
ERP5Storage.prototype._getFile = function (command, site_hal, param, options) { /**
var fetch, item = (param || {})._id || (site_hal._links.me || {}).href; * Get a document ("me" or regular document)
*
* @method _getDoc
* @param {Object} command The JIO command
* @param {Object} site_hal The object to lookup needed href for request
* @param {Object} param The given parameters
* @param {Object} options The command options (including custom options!)
* @return {Object} the requested document
*/
ERP5Storage.prototype._getDoc = function (command, hal, param, options) {
var fetch, force, item = (param || {})._id || (hal._links.me || {}).href;
if (!item) { if (!item) {
command.error(401); command.error(401);
} }
fetch = new URI(item); // HACK: remove, when forcing ALLDOCS over a GET (installed_instances eg.)
return this._getSiteDocument( if (options._id) {
site_hal._links.traverse.href, force = "urn:jio:get:" + options._id;
}
fetch = new URI(force || item);
return this._getBase(
hal._links.traverse.href,
{"relative_url": fetch.segment(2) || item, "view": options._view} {"relative_url": fetch.segment(2) || item, "view": options._view}
); );
}; };
ERP5Storage.prototype._getSiteDocument = function (traverse, expando) { /**
* Retrieves document defined in _getDoc. Called directly to get "root"
* with both parameters undefined
*
* @method _getBase
* @param {String} traverse The url to call ("" falls back to this._url!)
* @param {Object} expando The url parameters for the UriTemplate
* @return {Object} the requested document
*/
ERP5Storage.prototype._getBase = function (traverse, expando) {
var url = UriTemplate.parse(traverse || "").expand(expando || {}); var url = UriTemplate.parse(traverse || "").expand(expando || {});
return jIO.util.ajax({ return jIO.util.ajax({
"type": "GET", "type": "GET",
...@@ -48,43 +85,105 @@ ...@@ -48,43 +85,105 @@
}); });
}; };
ERP5Storage.prototype._get = function (command, param, options) { /**
* Retrieves a parameter from an object or array
*
* @method _getParam
* @param {Object} haystack The object/array to search
* @param {String} needle The value to search
* @return {String} the requested parameter
*/
ERP5Storage.prototype._getParam = function (haystack, needle) {
var i, key, list, len;
if (!haystack.length && haystack.name === needle) {
return haystack._query;
}
list = haystack || [];
len = list.length;
for (i = 0; i < len; i += 1) {
key = list[i];
if (key.name === needle) {
return key._query;
}
}
return undefined;
};
/**
* Get a document
*
* @method get
* @param {Object} command The JIO command
* @param {Object} param The given parameters
* @param {Object} options The command options
*/
ERP5Storage.prototype.get = function (command, param, options) {
var that = this; var that = this;
return that._getSiteDocument() return that._getBase()
.then(function (site_hal) { .then(function (site_hal) {
return that._getFile(command, site_hal, param, options); return that._getDoc(command, site_hal, param, options);
}) })
.then(function (response) { .then(function (response) {
response._id = param._id; response._id = param._id;
return response;
});
};
ERP5Storage.prototype.get = function (command, param, options) {
this._get(command, param, options)
.then(function (response) {
command.success({"data": response}); command.success({"data": response});
}) })
.fail(function (error) { .fail(function (error) {
console.error(error); command.error(error.target.status);
// XXX How to propagate the error
command.error(
"not_found",
"missing",
"Cannot find document"
);
}); });
}; };
/**
* Get an attachment
*
* @method getAttachment
* @param {Object} command The JIO command
* @param {Object} param The given parameters
*/
ERP5Storage.prototype.getAttachment = function (command, param) {
command.error(501);
};
/**
* Remove a document
*
* @method get
* @param {Object} command The JIO command
* @param {Object} param The given parameters
* @param {Object} options The command options
*/
ERP5Storage.prototype.remove = function (command, param, options) {
command.error(501);
};
/**
* Remove an attachment
*
* @method removeAttachment
* @param {Object} command The JIO command
* @param {Object} param The given parameters
*/
ERP5Storage.prototype.removeAttachment = function (command, param) {
command.error(501);
};
/**
* Create a document
*
* @method post
* @param {Object} command The JIO command
* @param {Object} metadata The metadata to store
* @param {Object} options The command options
*/
ERP5Storage.prototype.post = function (command, metadata, options) { ERP5Storage.prototype.post = function (command, metadata, options) {
var that = this; var that = this;
return that._getSiteDocument() return that._getBase()
.then(function (site_hal) { .then(function (site_hal) {
return that._getFile(command, site_hal, undefined, options); return that._getDoc(command, site_hal, undefined, options);
}) })
.then(function(opts) { .then(function (result) {
var key, custom_action = opts._actions[options.action], var key, custom_action = result._actions[options._action],
post_action = custom_action || site_hal._actions.add, post_action = custom_action || result._actions.add,
data = new FormData(); data = new FormData();
for (key in metadata) { for (key in metadata) {
...@@ -107,81 +206,129 @@ ...@@ -107,81 +206,129 @@
var uri = new URI(doc.target.getResponseHeader("X-Location")); var uri = new URI(doc.target.getResponseHeader("X-Location"));
command.success({"id": uri.segment(2)}); command.success({"id": uri.segment(2)});
}).fail(function (error) { }).fail(function (error) {
console.error(error); command.error(error.target.status);
command.error(
500,
"Too bad...",
"Unable to post doc"
);
}); });
}; };
/**
* Create or update a document
*
* @method post
* @param {Object} command The JIO command
* @param {Object} metadata The metadata to store
* @param {Object} options The command options
*/
ERP5Storage.prototype.put = function (command, metadata, options) { ERP5Storage.prototype.put = function (command, metadata, options) {
return this._get(metadata, options) var that = this, custom_action = (options || {})._action;
return that._getBase()
.then(function (site_hal) {
var param;
// force another id over "me"
// HACK: reference for service_installation (= server to install on)
if (custom_action || metadata._id) {
param = {"_id": metadata._reference || metadata._id};
}
return that._getDoc(command, site_hal, param, options);
})
.then(function (result) { .then(function (result) {
var put_action = result._embedded._view._actions.put, var key, renderer_form,
renderer_form = result._embedded._view,
data = new FormData(), data = new FormData(),
key; put_action = result._actions[custom_action] ||
data.append(renderer_form.form_id.key, result._embedded._view._actions.put;
renderer_form.form_id['default']);
renderer_form = result._embedded._view;
data.append(
renderer_form.form_id.key,
renderer_form.form_id['default']
);
for (key in metadata) { for (key in metadata) {
if (metadata.hasOwnProperty(key)) { if (metadata.hasOwnProperty(key)) {
if (key !== "_id") { if (key !== "_id" && !metadata._reference) {
// Hardcoded my_ ERP5 behaviour // HACK: update_scope does not implement my_
if (options._force_data) {
data.append(key, metadata[key]);
} else {
// Hardcoded my_ ERP5 behaviour - fails so silently...!!!!!
try {
if (renderer_form.hasOwnProperty("my_" + key)) { if (renderer_form.hasOwnProperty("my_" + key)) {
data.append(renderer_form["my_" + key].key, metadata[key]); data.append(renderer_form["my_" + key].key, metadata[key]);
} else { }
} catch (e) {
throw new Error("Can not save property " + key); throw new Error("Can not save property " + key);
} }
} }
} }
} }
}
return jIO.util.ajax({ return jIO.util.ajax({
"type": put_action.method, "type": put_action.method,
"url": put_action.href, "url": put_action.href,
"data": data, "data": data,
"xhrFields": { "xhrFields": {
withCredentials: true "withCredentials": true
} }
}); });
}) })
.then(function (result) { .then(function (event) {
command.success(result); var response, answer = event.target.responseText;
if (answer !== "") {
response = {
"status": event.target.status,
"_temp": JSON.parse(answer)
};
}
command.success(response || event);
}) })
.fail(function (error) { .fail(function (error) {
console.error(error); // DEBUG EXAMPLE
command.error( // if (error instanceof ProgressEvent) {
"error", // return command.error(
"did not work as expected", // error.target.status,
"Unable to call put" // error.target.statusText,
); // "custom message"
// );
// }
command.error(error.target.status);
}); });
}; };
/**
* Add an attachment to a document
*
* @method putAttachment
* @param {Object} command The JIO command
* @param {Object} param The given parameters
*/
ERP5Storage.prototype.putAttachment = function (command, param) {
command.error(501);
};
/**
* Get all filenames (and files)
*
* @method allDocs
* @param {Object} command The JIO command
* @param {Object} param The given parameters
* @param {Object} options The command options (HACKED, because needed)
*/
ERP5Storage.prototype.allDocs = function (command, param, options) { ERP5Storage.prototype.allDocs = function (command, param, options) {
var that = this, search_pointer; var that = this, search_pointer;
return this._getSiteDocument() return that._getBase()
.then(function (site_hal) { .then(function (site_hal) {
search_pointer = site_hal._links.raw_search.href; search_pointer = site_hal._links.raw_search.href;
return that._getFile(command, site_hal, undefined, options); return that._getDoc(command, site_hal, param, options);
}) })
.then(function (opts) { .then(function (opts) {
var i, len, jump_list, jump; // HACK: options._id needed when forcing GET through ALLDOCS
if (param._jump && (options.query || options._id)) {
// HACK: add ERP5 custom jump options.query = that._getParam(opts._links.slapos_jump, param._jump);
if (param._jump && options.query) {
jump_list = opts._links["slapos_jump" || []];
len = jump_list.length;
for (i = 0; i < len; i += 1) {
jump = jump_list[i];
if (jump.name === param._jump) {
options.query = jump._query;
}
} }
}
return that._getSiteDocument( return that._getBase(
search_pointer, search_pointer,
{ {
"query": options.query, "query": options.query,
...@@ -192,13 +339,12 @@ ...@@ -192,13 +339,12 @@
); );
}) })
.then(function (catalog_json) { .then(function (catalog_json) {
var data = catalog_json._embedded.contents, var i, uri, item,
count = data.length,
i,
uri,
item,
result = [], result = [],
promise_list = [result]; promise_list = [result];
data = catalog_json._embedded.contents,
count = data.length,
for (i = 0; i < count; i += 1) { for (i = 0; i < count; i += 1) {
item = data[i]; item = data[i];
uri = new URI(item._links.self.href); uri = new URI(item._links.self.href);
...@@ -222,12 +368,7 @@ ...@@ -222,12 +368,7 @@
command.success({"data": {"rows": result, "total_rows": count}}); command.success({"data": {"rows": result, "total_rows": count}});
}) })
.fail(function (error) { .fail(function (error) {
console.error(error); command.error(error.target.status);
command.error(
"error",
"did not work as expected",
"Unable to call allDocs"
);
}); });
}; };
......
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