/*
* Copyright 2012 Anyware Services
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Defines a dedicated proxy that use the {@link Ametys.data.ServerComm} to communicate with the server.
*
* Examples of configuration in a store:
*
* Ext.create('Ext.data.Store', {
* model: 'my.own.Model',
* proxy: {
* type: 'ametys',
* plugin: 'projects',
* url: 'administrator/projects/list.xml',
* reader: {
* type: 'xml',
* record: 'element',
* rootProperty: 'root'
* }
* }
* });
*
* or
*
* Ext.create('Ext.data.Store', {
* model: 'my.own.Model',
* proxy: {
* type: 'ametys',
* methodName: 'getProjects',
* methodArguments: ['siteName', 'lang'],
* role: 'my.own.ProjectDAO',
* reader: {
* type: 'xml',
* record: 'element',
* rootProperty: 'root'
* }
* }
* });
*
* or
*
* Ext.create('Ext.data.Store', {
* model: 'my.own.Model',
* proxy: {
* type: 'ametys',
* methodName: 'getProjects',
* methodArguments: ['siteName', 'lang'],
* serverCaller: this,
* reader: {
* type: 'xml',
* record: 'element',
* rootProperty: 'root'
* }
* }
* });
*/
Ext.define('Ametys.data.ServerCommProxy', {
alias: 'proxy.ametys',
extend: 'Ext.data.proxy.Server',
noCache: false,
/**
* @cfg {String} plugin The name of the plugin receiving the request. See Ametys.data.ServerComm#send.
*/
plugin: null,
/**
* @cfg {String} workspace The name of the workspace receiving the request. See Ametys.data.ServerComm#send.
*/
workspace: null,
/**
* @cfg {String} serverId If the server-side {@link #cfg-role} is a multiple extension point, this refers to an extension. See Ametys.data.ServerComm#callMethod. Can be null if {@link #cfg-url} or {@link #cfg-serverCaller} is used.
*/
serverId: null,
/**
* @cfg {String} role The id of Java component. See Ametys.data.ServerComm#callMethod. Can be null if {@link #cfg-url} or {@link #cfg-serverCaller} is used.
*/
role: null,
/**
* @cfg {Ametys.data.ServerCaller} serverCaller The JS component corresponding to a serverside ClientSideElement to call {@link #cfg-methodName} callable method. Can be null if {@link #cfg-url} or {@link #cfg-role} is used.
*/
serverCaller: null,
/**
* @cfg {String} methodName The "callable" method to call for this proxy. See Ametys.data.ServerComm#callMethod. Can be null {@link #cfg-url} is used.
*/
methodName: null,
/**
* @cfg {String[]} methodArguments Names of the parameters expected by the "callable" method, in expected order. If null, the all request's parameters as a Object will be pass to the "callable" method.
*/
methodArguments: null,
/**
* @cfg {Boolean} cancelOutdatedRequest True to cancel the old and outdated requests of this proxy
*/
/**
* @private
* @property {String} _cancelCode The cancel code for the requests of this proxy.
*/
_cancelCode: null,
/**
* @cfg {String} errorMessage The error message to display if an error occures. There is a default value.
*/
errorMessage: "{{i18n PLUGINS_CORE_UI_SERVERCOMMPROXY_ERROR_MSG}}",
/**
* @cfg {Object} reader2ResponseTypes Values are the responseType of Ametys.data.ServerComm#send and keys possible reader type.
* The default value do associate xml<->xml and json<->text
*/
reader2ResponseTypes: {
xml: 'xml',
json: 'text'
},
statics: {
/**
* Add a new mapping between a reader type and a response type. This is
* necessary to define a new reader to be used by this proxy.
* @param {String} readerType The type of the reader
* @param {String} responseType The type of the response
*/
addReader2ResponseType: function(readerType, responseType)
{
this.prototype.reader2ResponseTypes[readerType] = responseType;
}
},
constructor: function(config)
{
if (config.cancelOutdatedRequest)
{
this._cancelCode = Ext.id(null, this.self.getName() + '$');
}
this.callParent(arguments);
},
/**
* Gets the cancel code
* @return {String} The cancel code for this proxy
*/
getCancelCode: function()
{
return this._cancelCode;
},
doRequest: function(operation, callback, scope)
{
if (this.methodName && (this.role || this.serverCaller))
{
operation.setUrl('client-call');
this.plugin = 'core-ui';
}
var request = this.buildRequest(operation);
var params = {};
if (this.methodName && this.role)
{
params = {
role: this.role,
id: this.serverId,
methodName: this.methodName,
parameters: this._getMethodParameters(request)
}
}
else if (this.methodName && this.serverCaller)
{
if (!this.serverCaller.isServerCaller)
{
Ametys.log.ErrorDialog.display({
title: "{{i18n PLUGINS_CORE_UI_SERVERCOMM_ERROR_TITLE}}",
text: this.errorMessage,
details: this.serverCaller.$className + " is not a instance of Ametys.data.ServerCaller",
category: "Ametys.data.ServerCommProxy"
});
return;
}
params = {
role: this.serverCaller.getServerRole(),
id: this.serverCaller.getServerId(),
methodName: this.methodName,
parameters: this._getMethodParameters(request)
}
}
else
{
params = request.getParams();
}
var writer = this.getWriter();
if (operation.allowWrite()) {
request = writer.write(request);
}
Ametys.data.ServerComm.send({
priority: Ametys.data.ServerComm.PRIORITY_MAJOR,
plugin: this.plugin,
workspace: this.workspace,
url: request.getUrl(),
parameters: params,
responseType: this.getResponseType(),
callback: {
handler: this.createRequestCallback,
scope: this,
arguments: {
request: request,
operation: operation,
callback: callback,
scope: scope
}
},
cancelCode: this._cancelCode
});
},
/**
* @private
* Get the method's parameters as a Array.
* If {@link #cfg-methodArguments} is not null, the parameters will be extracted from request's parameters and flatten into the returned array, in same order.
* Otherwise, the returned parameters will be a one-size array with the request's parameters
* @param {Ext.data.Request} request The request
* @return {Object[]} The method's parameters into a Array
*/
_getMethodParameters: function(request)
{
var params = request.getParams();
if (this.methodArguments && Ext.isArray(this.methodArguments))
{
var paramsAsArray = [];
Ext.Array.each(this.methodArguments, function (name) {
paramsAsArray.push(params[name]);
});
return paramsAsArray;
}
else
{
return [params];
}
},
/**
* @private
* Get the response type for Ametys.data.ServerComm#send depending on the current reader type.
* @return {String} A response type accepted by Ametys.data.ServerComm#send. Default value is 'xml'.
*/
getResponseType: function()
{
return this.reader2ResponseTypes[this.getReader().type || 'xml'];
},
/**
* @private
* Creates an intermediary callback for the Ametys.data.ServerComm#send to call the #doRequest callback with the rights arguments
* @param {Object} response The response
* @param {Object[]} arguments The arguments transmited to the Ametys.data.ServerComm#send call in the #doRequest method.
* @return {Function} A callback function at the Ametys.data.ServerComm#send format to call the #doRequest callback
*/
createRequestCallback: function(response, arguments)
{
var failure = Ametys.data.ServerComm.handleBadResponse(this.errorMessage,
response,
Ext.getClassName(this) + '.createRequestCallback');
this.processResponse(!failure, arguments.operation, arguments.request, response, arguments.callback, arguments.scope);
},
extractResponseData: function(response)
{
var responseType = this.getResponseType();
// Return first child which is the expected root node
if (responseType == 'xml')
{
return Ext.dom.Query.selectNode('*', response)
}
else
{
return Ext.JSON.decode(Ext.dom.Query.selectValue('', response));
}
}
});