/*******************************************************************************
* This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* Peter Smith
*******************************************************************************/
package org.boris.xlloop.http;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import org.boris.xlloop.IFunctionHandler;
import org.boris.xlloop.RequestException;
import org.boris.xlloop.xloper.XLArray;
import org.boris.xlloop.xloper.XLBool;
import org.boris.xlloop.xloper.XLError;
import org.boris.xlloop.xloper.XLInt;
import org.boris.xlloop.xloper.XLMissing;
import org.boris.xlloop.xloper.XLNil;
import org.boris.xlloop.xloper.XLNum;
import org.boris.xlloop.xloper.XLSRef;
import org.boris.xlloop.xloper.XLString;
import org.boris.xlloop.xloper.XLoper;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
public class JSONCodec
{
public static void doRequest(IFunctionHandler handler, Reader input, Writer output) throws IOException,
JSONException {
BufferedWriter bw = new BufferedWriter(output);
try {
FunctionRequest fr = JSONCodec.decodeRequest(input);
System.out.println(JSONCodec.encodeRequest(fr).toString(4));
XLoper res = handler.execute(null, fr.getName(), fr.getArgs());
System.out.println(JSONCodec.encode(res).toString(4));
JSONCodec.encodeXLoper(res, bw);
} catch (RequestException e) {
e.printStackTrace();
XLoper res = new XLString(e.getMessage());
JSONCodec.encodeXLoper(res, bw);
bw.flush();
} finally {
if (bw != null)
bw.flush();
}
}
public static FunctionRequest decodeRequest(Reader r) throws IOException, JSONException {
JSONTokener t = new JSONTokener(r);
JSONObject jo = new JSONObject(t);
String name = jo.getString("name");
JSONArray args = jo.getJSONArray("args");
String sheetName = (String) jo.opt("sheetName");
JSONObject caller = (JSONObject) jo.opt("caller");
XLSRef cref = null;
if (caller != null) {
cref = (XLSRef) decode(caller);
}
XLoper[] xargs = new XLoper[args.length()];
for (int i = 0; i < xargs.length; i++) {
xargs[i] = decode(args.getJSONObject(i));
}
return new FunctionRequest(name, xargs, cref, sheetName);
}
public static XLoper decodeXLoper(Reader r) throws IOException, JSONException {
JSONTokener t = new JSONTokener(r);
JSONObject jo = new JSONObject(t);
return decode(jo);
}
public static void encodeRequest(FunctionRequest fr, Writer w) throws IOException, JSONException {
encodeRequest(fr).write(w);
}
public static JSONObject encodeRequest(FunctionRequest fr) throws IOException, JSONException {
JSONObject o = new JSONObject();
o.put("request", "XLLoop");
o.put("version", "0.1.0");
o.put("name", fr.getName());
if (fr.getSheetName() != null)
o.put("sheetName", fr.getSheetName());
if (fr.getCaller() != null)
o.put("caller", encode(fr.getCaller()));
JSONArray a = new JSONArray();
XLoper[] xargs = fr.getArgs();
if (xargs != null) {
for (int i = 0; i < xargs.length; i++) {
a.put(encode(xargs[i]));
}
}
o.put("args", a);
return o;
}
public static void encodeXLoper(XLoper x, Writer w) throws IOException, JSONException {
JSONObject o = encode(x);
o.write(w);
}
public static JSONObject encode(XLoper x) throws JSONException {
JSONObject o = new JSONObject();
if (x == null) {
o.put("type", XLoper.xlTypeNil);
return o;
}
o.put("type", x.type);
switch (x.type) {
case XLoper.xlTypeBool:
o.put("bool", ((XLBool) x).bool);
break;
case XLoper.xlTypeErr:
o.put("error", ((XLError) x).err);
break;
case XLoper.xlTypeInt:
o.put("int", ((XLInt) x).w);
break;
case XLoper.xlTypeMissing:
break;
case XLoper.xlTypeMulti:
XLArray a = (XLArray) x;
o.put("rows", a.rows);
o.put("cols", a.columns);
JSONArray ja = new JSONArray();
for (int i = 0; i < a.length; i++) {
ja.put(encode(a.array[i]));
}
o.put("array", ja);
break;
case XLoper.xlTypeNil:
break;
case XLoper.xlTypeNum:
o.put("num", ((XLNum) x).num);
break;
case XLoper.xlTypeStr:
o.put("str", ((XLString) x).str);
break;
case XLoper.xlTypeSRef:
o.put("colFirst", ((XLSRef) x).colFirst);
o.put("colLast", ((XLSRef) x).colLast);
o.put("rowFirst", ((XLSRef) x).rwFirst);
o.put("rowLast", ((XLSRef) x).rwLast);
}
return o;
}
private static XLoper decode(JSONObject jo) throws JSONException {
switch (jo.getInt("type")) {
case XLoper.xlTypeBool:
return jo.getBoolean("bool") ? XLBool.TRUE : XLBool.FALSE;
case XLoper.xlTypeErr:
return new XLError(jo.getInt("error"));
case XLoper.xlTypeInt:
return new XLInt(jo.getInt("int"));
case XLoper.xlTypeMissing:
return XLMissing.MISSING;
case XLoper.xlTypeMulti:
int rows = jo.getInt("rows");
int cols = jo.getInt("cols");
int len = rows * cols;
XLoper[] a = new XLoper[len];
JSONArray ja = jo.getJSONArray("array");
for (int i = 0; i < len; i++) {
a[i] = decode(ja.getJSONObject(i));
}
return new XLArray(a, rows, cols);
case XLoper.xlTypeNil:
return XLNil.NIL;
case XLoper.xlTypeNum:
return new XLNum(jo.getDouble("num"));
case XLoper.xlTypeStr:
return new XLString(jo.getString("str"));
case XLoper.xlTypeSRef:
return new XLSRef(jo.getInt("colFirst"), jo.getInt("colLast"), jo.getInt("rowFirst"), jo.getInt("rowLast"));
}
return null;
}
}