/*jslint rhino: true, forin: true, onevar: false, browser: true */
/*global exports: false */
"use strict";
// Modification of Matěj Cepl released under the MIT/X11 license
// http://www.opensource.org/licenses/mit-license.php
/*
*
* xmlrpc.js beta version 1 Tool for creating XML-RPC formatted requests in
* JavaScript
*
* Copyright 2001 Scott Andrew LePera scott@scottandrew.com
*
*
* License: You are granted the right to use and/or redistribute this code only
* if this license and the copyright notice are included and you accept that no
* warranty of any kind is made or implied by the author.
*
*/
/**
* checks whether parameter is an array
*
* @param obj Object
* @return Boolean true if obj is array
*
* The problem is that in different contexts, Array is not same, and so obj is
* not an instance of SAME Array.
*/
var XMLRPCMessage = exports.XMLRPCMessage = function XMLRPCMessage(methodname) {
this.method = methodname || "system.listMethods";
this.params = [];
return this;
};
XMLRPCMessage.prototype.myIsArray = function myIsArray(obj) {
return (typeof obj.sort === 'function');
};
XMLRPCMessage.prototype.setMethod = function (methodName) {
if (methodName !== undefined) {
this.method = methodName;
}
};
XMLRPCMessage.prototype.addParameter = function (data) {
if (data !== undefined) {
this.params.push(data);
}
};
XMLRPCMessage.prototype.xml = function () {
var method = this.method;
// assemble the XML message header
var xml = "";
xml += "\n";
xml += "\n";
xml += "" + method + "\n";
xml += "\n";
// do individual parameters
this.params.forEach(function (data) {
xml += "\n";
xml += "" +
this.getParamXML(this.dataTypeOf(data),
data) + "\n";
xml += "\n";
}, this);
xml += "\n";
xml += "";
return xml; // for now
};
XMLRPCMessage.prototype.dataTypeOf = function (o) {
// identifies the data type
var type = typeof (o);
type = type.toLowerCase();
switch (type) {
case "number":
if (Math.round(o) === o) {
type = "i4";
} else {
type = "double";
}
break;
case "object":
if ((o instanceof Date)) {
type = "date";
} else if (this.myIsArray(o)) {
type = "array";
} else {
type = "struct";
}
break;
}
return type;
};
XMLRPCMessage.prototype.doValueXML = function (type, data) {
var xml = "<" + type + ">" + data + "" + type + ">";
return xml;
};
XMLRPCMessage.prototype.doBooleanXML = function (data) {
var value = (data === true) ? 1 : 0;
var xml = "" + value + "";
return xml;
};
XMLRPCMessage.prototype.doDateXML = function (data) {
function leadingZero(n) {
// pads a single number with a leading zero. Heh.
if (n.length === 1) {
n = "0" + n;
}
return n;
}
function dateToISO8601(date) {
// wow I hate working with the Date object
var year = date.getYear();
var month = this.leadingZero(date.getMonth());
var day = this.leadingZero(date.getDate());
var time = this.leadingZero(date.getHours()) +
":" + this.leadingZero(date.getMinutes()) +
":" + this.leadingZero(date.getSeconds());
var converted = year + month + day + "T" + time;
return converted;
}
var xml = "";
xml += dateToISO8601(data);
xml += "";
return xml;
};
XMLRPCMessage.prototype.doArrayXML = function (data) {
var xml = "\n";
for (var i = 0; i < data.length; i++) {
xml += "" +
this.getParamXML(this.dataTypeOf(data[i]),
data[i]) + "\n";
}
xml += "\n";
return xml;
};
XMLRPCMessage.prototype.doStructXML = function (data) {
var xml = "\n";
for (var i in data) {
xml += "\n";
xml += "" + i + "\n";
xml += "" + this.getParamXML(this.dataTypeOf(data[i]),
data[i]) + "\n";
xml += "\n";
}
xml += "\n";
return xml;
};
XMLRPCMessage.prototype.getParamXML = function (type, data) {
var xml;
switch (type) {
case "date":
xml = this.doDateXML(data);
break;
case "array":
xml = this.doArrayXML(data);
break;
case "struct":
xml = this.doStructXML(data);
break;
case "boolean":
xml = this.doBooleanXML(data);
break;
default:
xml = this.doValueXML(type, data);
break;
}
return xml;
};