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

updated version of erp5storage to handle offline

parent 53e7dcba
/*
* Copyright 2013, Nexedi SA
* Released under the LGPL license.
* http://www.gnu.org/licenses/lgpl.html
* JIO extension for resource replication.
* Copyright (C) 2013 Nexedi SA
*
* 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 */
/*global jIO, complex_queries, console, UriTemplate, FormData, RSVP, URI */
/*global jIO, complex_queries, UriTemplate, FormData, RSVP, URI */
(function (jIO, complex_queries, URI) {
"use strict";
/**
* The JIO ERP5storage extension
*
* @class ERP5Storage
* @constructor
* @param {Object} spec Storage definition
*/
function ERP5Storage(spec) {
if (typeof spec.url !== 'string' && !spec.url) {
throw new TypeError("ERP5 'url' must be a string " +
......@@ -23,19 +36,43 @@
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) {
command.error(401);
}
fetch = new URI(item);
return this._getSiteDocument(
site_hal._links.traverse.href,
// HACK: remove, when forcing ALLDOCS over a GET (installed_instances eg.)
if (options._id) {
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}
);
};
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 || {});
return jIO.util.ajax({
"type": "GET",
......@@ -47,44 +84,106 @@
return JSON.parse(response.target.responseText);
});
};
ERP5Storage.prototype._get = function (command, param, options) {
var that = this;
return that._getSiteDocument()
.then(function (site_hal) {
return that._getFile(command, site_hal, param, options);
})
.then(function (response) {
response._id = param._id;
return response;
});
/**
* 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) {
this._get(command, param, options)
var that = this;
return that._getBase()
.then(function (site_hal) {
return that._getDoc(command, site_hal, param, options);
})
.then(function (response) {
response._id = param._id;
command.success({"data": response});
})
.fail(function (error) {
console.error(error);
// XXX How to propagate the error
command.error(
"not_found",
"missing",
"Cannot find document"
);
command.error(error.target.status);
});
};
/**
* 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) {
var that = this;
return that._getSiteDocument()
return that._getBase()
.then(function (site_hal) {
return that._getFile(command, site_hal, undefined, options);
return that._getDoc(command, site_hal, undefined, options);
})
.then(function(opts) {
var key, custom_action = opts._actions[options.action],
post_action = custom_action || site_hal._actions.add,
.then(function (result) {
var key, custom_action = result._actions[options._action],
post_action = custom_action || result._actions.add,
data = new FormData();
for (key in metadata) {
......@@ -107,81 +206,129 @@
var uri = new URI(doc.target.getResponseHeader("X-Location"));
command.success({"id": uri.segment(2)});
}).fail(function (error) {
console.error(error);
command.error(
500,
"Too bad...",
"Unable to post doc"
);
command.error(error.target.status);
});
};
/**
* 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) {
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) {
var put_action = result._embedded._view._actions.put,
renderer_form = result._embedded._view,
var key, renderer_form,
data = new FormData(),
key;
data.append(renderer_form.form_id.key,
renderer_form.form_id['default']);
put_action = result._actions[custom_action] ||
result._embedded._view._actions.put;
renderer_form = result._embedded._view;
data.append(
renderer_form.form_id.key,
renderer_form.form_id['default']
);
for (key in metadata) {
if (metadata.hasOwnProperty(key)) {
if (key !== "_id") {
// Hardcoded my_ ERP5 behaviour
if (renderer_form.hasOwnProperty("my_" + key)) {
data.append(renderer_form["my_" + key].key, metadata[key]);
if (key !== "_id" && !metadata._reference) {
// HACK: update_scope does not implement my_
if (options._force_data) {
data.append(key, metadata[key]);
} else {
throw new Error("Can not save property " + key);
// Hardcoded my_ ERP5 behaviour - fails so silently...!!!!!
try {
if (renderer_form.hasOwnProperty("my_" + key)) {
data.append(renderer_form["my_" + key].key, metadata[key]);
}
} catch (e) {
throw new Error("Can not save property " + key);
}
}
}
}
}
return jIO.util.ajax({
"type": put_action.method,
"url": put_action.href,
"data": data,
"xhrFields": {
withCredentials: true
"withCredentials": true
}
});
})
.then(function (result) {
command.success(result);
.then(function (event) {
var response, answer = event.target.responseText;
if (answer !== "") {
response = {
"status": event.target.status,
"_temp": JSON.parse(answer)
};
}
command.success(response || event);
})
.fail(function (error) {
console.error(error);
command.error(
"error",
"did not work as expected",
"Unable to call put"
);
// DEBUG EXAMPLE
// if (error instanceof ProgressEvent) {
// return command.error(
// error.target.status,
// 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) {
var that = this, search_pointer;
return this._getSiteDocument()
return that._getBase()
.then(function (site_hal) {
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) {
var i, len, jump_list, jump;
// HACK: add ERP5 custom 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;
}
}
// HACK: options._id needed when forcing GET through ALLDOCS
if (param._jump && (options.query || options._id)) {
options.query = that._getParam(opts._links.slapos_jump, param._jump);
}
return that._getSiteDocument(
return that._getBase(
search_pointer,
{
"query": options.query,
......@@ -192,13 +339,12 @@
);
})
.then(function (catalog_json) {
var data = catalog_json._embedded.contents,
count = data.length,
i,
uri,
item,
var i, uri, item,
result = [],
promise_list = [result];
data = catalog_json._embedded.contents,
count = data.length,
for (i = 0; i < count; i += 1) {
item = data[i];
uri = new URI(item._links.self.href);
......@@ -222,12 +368,7 @@
command.success({"data": {"rows": result, "total_rows": count}});
})
.fail(function (error) {
console.error(error);
command.error(
"error",
"did not work as expected",
"Unable to call allDocs"
);
command.error(error.target.status);
});
};
......
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