From f87b9f1e48df02c26e0bbe3f8f1664c2b0862e52 Mon Sep 17 00:00:00 2001 From: jsdelfino Date: Sun, 18 Oct 2009 22:25:08 +0000 Subject: Some fixes to the JSON and httpd support. Added support for Atom. Adjusted store test. git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@826545 13f79535-47bb-0310-9956-ffa450edef68 --- cpp/sca/configure.ac | 1 + cpp/sca/etc/git-exclude | 4 +- cpp/sca/modules/Makefile.am | 2 +- cpp/sca/modules/atom/Makefile.am | 23 ++++ cpp/sca/modules/atom/atom-test.cpp | 150 +++++++++++++++++++++++ cpp/sca/modules/atom/atom.hpp | 154 ++++++++++++++++++++++++ cpp/sca/modules/httpd/mod.cpp | 10 +- cpp/sca/modules/json/json-test.cpp | 56 +++++---- cpp/sca/modules/json/json.hpp | 113 +++++++++-------- cpp/sca/test/store-script/htdocs/store.html | 21 ++-- cpp/sca/test/store-script/htdocs/store.js | 2 +- cpp/sca/test/store-script/store-script-test.cpp | 34 ++++-- cpp/sca/test/store-script/store.scm | 14 ++- 13 files changed, 484 insertions(+), 100 deletions(-) create mode 100644 cpp/sca/modules/atom/Makefile.am create mode 100644 cpp/sca/modules/atom/atom-test.cpp create mode 100644 cpp/sca/modules/atom/atom.hpp diff --git a/cpp/sca/configure.ac b/cpp/sca/configure.ac index edf471fcae..46584271b4 100644 --- a/cpp/sca/configure.ac +++ b/cpp/sca/configure.ac @@ -266,6 +266,7 @@ AM_CONDITIONAL([WANT_DOXYGEN], [test x$want_doxygen = xtrue]) AC_CONFIG_FILES([Makefile kernel/Makefile modules/Makefile + modules/atom/Makefile modules/eval/Makefile modules/httpd/Makefile modules/json/Makefile diff --git a/cpp/sca/etc/git-exclude b/cpp/sca/etc/git-exclude index 048c6979a1..70284ba699 100644 --- a/cpp/sca/etc/git-exclude +++ b/cpp/sca/etc/git-exclude @@ -60,8 +60,10 @@ sca/runtime/extensions/cpp/tools/scagen/docs/ account_client calculator_client kernel-test -xml-test +xsd-test +atom-test eval-test +eval-shell json-test store-function-test store-object-test diff --git a/cpp/sca/modules/Makefile.am b/cpp/sca/modules/Makefile.am index f152862a75..025a549df3 100644 --- a/cpp/sca/modules/Makefile.am +++ b/cpp/sca/modules/Makefile.am @@ -15,5 +15,5 @@ # specific language governing permissions and limitations # under the License. -SUBDIRS = eval httpd json +SUBDIRS = atom eval httpd json diff --git a/cpp/sca/modules/atom/Makefile.am b/cpp/sca/modules/atom/Makefile.am new file mode 100644 index 0000000000..90e3207bb2 --- /dev/null +++ b/cpp/sca/modules/atom/Makefile.am @@ -0,0 +1,23 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +noinst_PROGRAMS = atom-test + +INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE} + +atom_test_SOURCES = atom-test.cpp +atom_test_LDADD = -lpthread -L${LIBXML2_LIB} -lxml2 diff --git a/cpp/sca/modules/atom/atom-test.cpp b/cpp/sca/modules/atom/atom-test.cpp new file mode 100644 index 0000000000..0cef6b3b60 --- /dev/null +++ b/cpp/sca/modules/atom/atom-test.cpp @@ -0,0 +1,150 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +/* $Rev$ $Date$ */ + +/** + * Test ATOM data conversion functions. + */ + +#include +#include +#include +#include +#include "slist.hpp" +#include "atom.hpp" + +namespace tuscany { + +std::ostringstream* atomWriter(std::ostringstream* os, const std::string& s) { + (*os) << s; + return os; +} + +std::string itemEntry("\n" + "" + "item" + "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b" + "" + "" + "Apple$2.99" + "" + "" + "" + "\n"); + +bool testATOMEntry() { + { + const list i = list() << element << "item" + << (list() << element << "name" << std::string("Apple")) + << (list() << element << "price" << std::string("$2.99")); + const list a = mklist(std::string("item"), std::string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); + std::ostringstream os; + writeATOMEntry(atomWriter, &os, a); + assert(os.str() == itemEntry); + } + { + const list a = readATOMEntry(mklist(itemEntry)); + std::ostringstream os; + writeATOMEntry(atomWriter, &os, a); + assert(os.str() == itemEntry); + } + return true; +} + +std::string emptyFeed("\n" + "" + "Feed" + "1234" + "\n"); + +std::string itemFeed("\n" + "" + "Feed" + "1234" + "" + "item" + "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b" + "" + "" + "Apple$2.99" + "" + "" + "" + "" + "" + "item" + "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c" + "" + "" + "Orange$3.55" + "" + "" + "" + "" + "\n"); + +bool testATOMFeed() { + { + std::ostringstream os; + writeATOMFeed(atomWriter, &os, mklist("Feed", "1234")); + assert(os.str() == emptyFeed); + } + { + const list a = readATOMFeed(mklist(emptyFeed)); + std::ostringstream os; + writeATOMFeed(atomWriter, &os, a); + assert(os.str() == emptyFeed); + } + { + const list i = list() + << (list() << "item" << "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b" + << (list() << element << "item" + << (list() << element << "name" << "Apple") + << (list() << element << "price" << "$2.99"))) + << (list() << "item" << "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c" + << (list() << element << "item" + << (list() << element << "name" << "Orange") + << (list() << element << "price" << "$3.55"))); + const list a = cons("Feed", cons("1234", i)); + std::ostringstream os; + writeATOMFeed(atomWriter, &os, a); + assert(os.str() == itemFeed); + } + { + const list a = readATOMFeed(mklist(itemFeed)); + std::ostringstream os; + writeATOMFeed(atomWriter, &os, a); + assert(os.str() == itemFeed); + } + return true; +} + +} + +int main() { + std::cout << "Testing..." << std::endl; + + tuscany::testATOMEntry(); + tuscany::testATOMFeed(); + + std::cout << "OK" << std::endl; + + return 0; +} diff --git a/cpp/sca/modules/atom/atom.hpp b/cpp/sca/modules/atom/atom.hpp new file mode 100644 index 0000000000..5bb8d45e38 --- /dev/null +++ b/cpp/sca/modules/atom/atom.hpp @@ -0,0 +1,154 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +/* $Rev$ $Date$ */ + +#ifndef tuscany_atom_hpp +#define tuscany_atom_hpp + +/** + * ATOM data conversion functions. + */ + +#include +#include "list.hpp" +#include "value.hpp" +#include "monad.hpp" +#include "xml.hpp" + +namespace tuscany { + +/** + * Convert a list of elements to a list of values representing an ATOM entry. + */ +const list atomEntry(const list& e) { + const list t = filter(selector(mklist(element, "title")), e); + const list i = filter(selector(mklist(element, "id")), e); + const list c = filter(selector(mklist(element, "content")), e); + return mklist(elementValue(car(t)), elementValue(car(i)), cadr(elementChildren(car(c)))); +} + +/** + * Convert a list of elements to a list of values representing ATOM entries. + */ +const list atomEntries(const list& e) { + if (isNil(e)) + return list(); + return cons(atomEntry(car(e)), atomEntries(cdr(e))); +} + +/** + * Convert a list of strings to a list of values representing an ATOM entry. + */ +const failable, std::string> readATOMEntry(const list& ilist) { + const list e = readXML(ilist); + if (isNil(e)) + return std::string("Empty entry"); + return atomEntry(car(e)); +} + +/** + * Convert a list of strings to a list of values representing an ATOM feed. + */ +const failable, std::string> readATOMFeed(const list& ilist) { + const list f = readXML(ilist); + if (isNil(f)) + return std::string("Empty feed"); + const list t = filter(selector(mklist(element, "title")), car(f)); + const list i = filter(selector(mklist(element, "id")), car(f)); + const list e = filter(selector(mklist(element, "entry")), car(f)); + if (isNil(e)) + return mklist(elementValue(car(t)), elementValue(car(i))); + return cons(elementValue(car(t)), cons(elementValue(car(i)), atomEntries(e))); +} + +/** + * Convert a list of values representing an ATOM entry to a list of elements. + * The first two values in the list are the entry title and id. + */ +const list atomEntryElement(const list& l) { + return list() + << element << "entry" << (list() << attribute << "xmlns" << "http://www.w3.org/2005/Atom") + << (list() << element << "title" << (list() << attribute << "type" << "text") << car(l)) + << (list() << element << "id" << cadr(l)) + << (list() << element << "content" << (list() << attribute << "type" << "application/xml") << caddr(l)) + << (list() << element << "link" << (list() << attribute << "href" << cadr(l))); +} + +/** + * Convert a list of values representing ATOM entries to a list of elements. + */ +const list atomEntriesElements(const list& l) { + if (isNil(l)) + return list(); + return cons(atomEntryElement(car(l)), atomEntriesElements(cdr(l))); +} + +/** + * Convert a list of values representing an ATOM entry to an ATOM entry. + * The first two values in the list are the entry id and title. + */ +template const failable writeATOMEntry(const lambda& reduce, const R& initial, const list& l) { + return writeXML(reduce, initial, mklist(atomEntryElement(l))); +} + +/** + * Convert a list of values representing an ATOM entry to a list of strings. + * The first two values in the list are the entry id and title. + */ +const list writeATOMList(const list& listSoFar, const std::string& s) { + return cons(s, listSoFar); +} + +const failable, std::string> writeATOMEntry(const list& l) { + const failable, std::string> ls = writeATOMEntry >(writeATOMList, list(), l); + if (!hasValue(ls)) + return ls; + return reverse(list(ls)); +} + +/** + * Convert a list of values representing an ATOM feed to an ATOM feed. + * The first two values in the list are the feed id and title. + */ +template const failable writeATOMFeed(const lambda& reduce, const R& initial, const list& l) { + const list f = list() + << element << "feed" << (list() << attribute << "xmlns" << "http://www.w3.org/2005/Atom") + << (list() << element << "title" << (list() << attribute << "type" << "text") << car(l)) + << (list() << element << "id" << cadr(l)); + if (isNil(cddr(l))) + return writeXML(reduce, initial, mklist(f)); + const list fe = append(f, atomEntriesElements(cddr(l))); + return writeXML(reduce, initial, mklist(fe)); +} + +/** + * Convert a list of values representing an ATOM feed to a list of strings. + * The first two values in the list are the feed id and title. + */ +const failable, std::string> writeATOMFeed(const list& l) { + const failable, std::string> ls = writeATOMFeed >(writeATOMList, list(), l); + if (!hasValue(ls)) + return ls; + return reverse(list(ls)); +} + +} + +#endif /* tuscany_atom_hpp */ diff --git a/cpp/sca/modules/httpd/mod.cpp b/cpp/sca/modules/httpd/mod.cpp index feebca4b5c..81e12934e7 100644 --- a/cpp/sca/modules/httpd/mod.cpp +++ b/cpp/sca/modules/httpd/mod.cpp @@ -50,6 +50,7 @@ #include "list.hpp" #include "slist.hpp" #include "value.hpp" +#include "element.hpp" #include "monad.hpp" #include "../json/json.hpp" #include "../eval/driver.hpp" @@ -160,7 +161,7 @@ const value evalLoop(std::istream& is, const value& req, Env& globalEnv) { */ const list queryArg(std::string s) { const list t = tokenize("=", s); - return makeList(car(t).c_str(), cadr(t)); + return mklist(car(t).c_str(), cadr(t)); } const list > queryArgs(const request_rec* r) { @@ -218,7 +219,7 @@ const int get(request_rec* r) { // Convert the expr value to JSON const JSONContext cx; - failable, std::string> jsval = writeJSON(cx, makeList(makeList("id", id), makeList("result", val))); + failable, std::string> jsval = writeJSON(cx, mklist(mklist("id", id), mklist("result", val))); if (!hasValue(jsval)) return HTTP_INTERNAL_SERVER_ERROR; @@ -277,7 +278,7 @@ const int post(request_rec* r) { // Read the JSON request const list req = read(r); JSONContext cx; - const list json = readJSON(cx, req); + const list json = elementsToValues(readJSON(cx, req)); const list > args = postArgs(json); // Extract the request id, method and params @@ -298,7 +299,8 @@ const int post(request_rec* r) { std::cout.flush(); // Convert the expr value to JSON - failable, std::string> jsval = writeJSON(cx, makeList(makeList("id", id), makeList("result", val))); + const list result = valuesToElements(mklist(mklist("id", id), mklist("result", val))); + failable, std::string> jsval = writeJSON(cx, result); if (!hasValue(jsval)) return HTTP_INTERNAL_SERVER_ERROR; diff --git a/cpp/sca/modules/json/json-test.cpp b/cpp/sca/modules/json/json-test.cpp index 1ebece647b..b7cc4e4eeb 100644 --- a/cpp/sca/modules/json/json-test.cpp +++ b/cpp/sca/modules/json/json-test.cpp @@ -20,7 +20,7 @@ /* $Rev$ $Date$ */ /** - * Test JSON read/write functions. + * Test JSON data conversion functions. */ #include @@ -50,34 +50,44 @@ std::ostringstream* jsonWriter(std::ostringstream* os, const std::string& s) { bool testJSON() { const JSONContext cx; - const list phones = makeList (std::string("408-1234"), std::string("650-1234")); - const list l = makeList (makeList ("phones", phones), makeList ("lastName", std::string("test\ttab")), makeList ("firstName", std::string("test1"))); - print(l, std::cout); - std::cout << std::endl; - - std::ostringstream os; - writeJSON(cx, jsonWriter, &os, l); - std::cout << os.str() << std::endl; - - std::istringstream is(os.str()); - const list il = makeStreamList(is); - const list r = readJSON(cx, il); - print(r, std::cout); - std::cout << std::endl; - assert(r == l); - - std::ostringstream wos; - write(writeJSON(cx, r), wos); - assert(wos.str() == os.str()); - + { + const list ad = mklist(mklist(attribute, "city", std::string("san francisco")), mklist(attribute, "state", std::string("ca"))); + const list ac = mklist(mklist(element, "id", std::string("1234")), mklist(attribute, "balance", 1000)); + const list cr = mklist(mklist (attribute, "name", std::string("jdoe")), cons(element, cons("address", ad)), cons(element, cons("account", ac))); + const list c = mklist(cons(element, cons("customer", cr))); + std::ostringstream os; + writeJSON(cx, jsonWriter, &os, c); + assert(os.str() == "{\"customer\":{\"name\":\"jdoe\",\"address\":{\"city\":\"san francisco\",\"state\":\"ca\"},\"account\":{\"id\":\"1234\",\"balance\":1000}}}"); + } + { + const list phones = mklist (std::string("408-1234"), std::string("650-1234")); + const list l = mklist (mklist (element, "phones", phones), mklist (attribute, "lastName", std::string("test\ttab")), mklist (attribute, "firstName", std::string("test1"))); + + std::ostringstream os; + writeJSON(cx, jsonWriter, &os, l); + assert(os.str() == "{\"phones\":[\"408-1234\",\"650-1234\"],\"lastName\":\"test\\u0009tab\",\"firstName\":\"test1\"}"); + + std::istringstream is(os.str()); + const list il = streamList(is); + const list r = readJSON(cx, il); + assert(r == l); + + std::ostringstream wos; + write(writeJSON(cx, r), wos); + assert(wos.str() == os.str()); + } return true; } bool testJSONRPC() { const std::string lm("{\"id\": 1, \"method\": \"system.listMethods\", \"params\": []}"); JSONContext cx; - const list v = readJSON(cx, makeList(lm)); - std::cout << v << std::endl; + const list e = readJSON(cx, mklist(lm)); + const list v = elementsToValues(e); + + assert(assoc("id", v) == mklist("id", 1)); + assert(assoc("method", v) == mklist("method", std::string("system.listMethods"))); + assert(assoc("params", v) == mklist("params", list())); return true; } diff --git a/cpp/sca/modules/json/json.hpp b/cpp/sca/modules/json/json.hpp index f6ed9202c3..5f3d8c21e0 100644 --- a/cpp/sca/modules/json/json.hpp +++ b/cpp/sca/modules/json/json.hpp @@ -23,15 +23,15 @@ #define tuscany_json_hpp /** - * JSON read/write functions. + * JSON data conversion functions. */ -#include #define XP_UNIX #include #include #include "list.hpp" #include "value.hpp" +#include "element.hpp" #include "monad.hpp" namespace tuscany { @@ -139,10 +139,9 @@ private: }; /** - * Converts JS properties to Tuscany values. + * Converts JS properties to values. */ -const list jsPropertiesToValues(const JSONContext& cx, const list& propertiesSoFar, JSObject* o, - JSObject* i) { +const list jsPropertiesToValues(const JSONContext& cx, const list& propertiesSoFar, JSObject* o, JSObject* i) { const value jsValToValue(const JSONContext& cx, const jsval& jsv); @@ -155,14 +154,15 @@ const list jsPropertiesToValues(const JSONContext& cx, const list& const value val = jsValToValue(cx, jsv); jsval idv; JS_IdToValue(cx, id, &idv); - if(JSVAL_IS_STRING(idv)) - return jsPropertiesToValues(cx, cons (makeList (JS_GetStringBytes(JSVAL_TO_STRING(idv)), val), - propertiesSoFar), o, i); + if(JSVAL_IS_STRING(idv)) { + const value type = isList(val)? element : attribute; + return jsPropertiesToValues(cx, cons (mklist (type, JS_GetStringBytes(JSVAL_TO_STRING(idv)), val), propertiesSoFar), o, i); + } return jsPropertiesToValues(cx, cons(val, propertiesSoFar), o, i); } /** - * Converts a JS value to a Tuscany value. + * Converts a JS val to a value. */ const value jsValToValue(const JSONContext& cx, const jsval& jsv) { switch(JS_TypeOfValue(cx, jsv)) { @@ -182,7 +182,8 @@ const value jsValToValue(const JSONContext& cx, const jsval& jsv) { JSObject* i = JS_NewPropertyIterator(cx, o); if(i == NULL) return value(list ()); - return jsPropertiesToValues(cx, list (), o, i); + const value pv = jsPropertiesToValues(cx, list (), o, i); + return pv; } default: { return value(); @@ -203,7 +204,7 @@ failable consumeJSON(const JSONContext& cx, JSONParser* parse } /** - * Read JSON tokens from list of strings. + * Convert a list of strings representing a JSON document to a list of values. */ const failable, std::string> readJSON(const JSONContext& cx, const list& ilist) { jsval val; @@ -221,22 +222,6 @@ const failable, std::string> readJSON(const JSONContext& cx, const l return list(jsValToValue(cx, val)); } -/** - * Returns true if a list represents a JS array. - */ -const bool isJSArray(const list& l) { - if(isNil(l)) - return false; - value v = car(l); - if(isList(v)) { - const list p = v; - if(isSymbol(car(p))) { - return false; - } - } - return true; -} - /** * Converts a list of values to JS array elements. */ @@ -250,24 +235,12 @@ JSObject* valuesToJSElements(const JSONContext& cx, JSObject* a, const list& l) { - const jsval valueToJSVal(const JSONContext& cx, const value& val); - if(isNil(l)) - return o; - const list p = car(l); - jsval pv = valueToJSVal(cx, cadr(p)); - JS_SetProperty(cx, o, ((std::string)car(p)).c_str(), &pv); - return valuesToJSProperties(cx, o, cdr(l)); -} - -/** - * Converts a Tuscany value to a JS value. + * Converts a value to a JS val. */ const jsval valueToJSVal(const JSONContext& cx, const value& val) { switch(type(val)) { - case value::String: { + case value::String: + case value::Symbol: { return STRING_TO_JSVAL(JS_NewStringCopyZ(cx, ((std::string)val).c_str())); } case value::Boolean: { @@ -277,10 +250,7 @@ const jsval valueToJSVal(const JSONContext& cx, const value& val) { return DOUBLE_TO_JSVAL(JS_NewDouble(cx, (double)val)); } case value::List: { - if (isJSArray(val)) { - return OBJECT_TO_JSVAL(valuesToJSElements(cx, JS_NewArrayObject(cx, 0, NULL), val, 0)); - } - return OBJECT_TO_JSVAL(valuesToJSProperties(cx, JS_NewObject(cx, NULL, NULL, NULL), val)); + return OBJECT_TO_JSVAL(valuesToJSElements(cx, JS_NewArrayObject(cx, 0, NULL), val, 0)); } default: { return JSVAL_VOID; @@ -288,8 +258,44 @@ const jsval valueToJSVal(const JSONContext& cx, const value& val) { } } +const failable writeList(const JSONContext& cx, const list& l, JSObject* o) { + if (isNil(l)) + return true; + + // Write an attribute + const value token(car(l)); + + if (isTaggedList(token, attribute)) { + jsval pv = valueToJSVal(cx, attributeValue(token)); + JS_SetProperty(cx, o, std::string(attributeName(token)).c_str(), &pv); + + } else if (isTaggedList(token, element)) { + + // Write the value of an element + if (elementHasValue(token)) { + jsval pv = valueToJSVal(cx, elementValue(token)); + JS_SetProperty(cx, o, std::string(elementName(token)).c_str(), &pv); + + } else { + + // Write a parent element + JSObject* child = JS_NewObject(cx, NULL, NULL, NULL); + jsval pv = OBJECT_TO_JSVAL(child); + JS_SetProperty(cx, o, std::string(elementName(token)).c_str(), &pv); + + // Write its children + const failable w = writeList(cx, elementChildren(token), child); + if (!hasValue(w)) + return w; + } + } + + // Go on + return writeList(cx, cdr(l), o); +} + /** - * Context passed to JSON write callback function. + * Context passed to the JSON write callback function. */ template class JSONWriteContext { public: @@ -314,20 +320,25 @@ template JSBool writeCallback(const jschar *buf, uint32 len, void *d * Convert a list of values to a JSON document. */ template const failable writeJSON(const JSONContext& cx, const lambda& reduce, const R& initial, const list& l) { - jsval val = valueToJSVal(cx, l); + JSObject* o = JS_NewObject(cx, NULL, NULL, NULL); + jsval val = OBJECT_TO_JSVAL(o); + const failable w = writeList(cx, l, o); + if (!hasValue(w)) + return std::string(w); + JSONWriteContext wcx(cx, reduce, initial); if (!JS_Stringify(cx, &val, NULL, JSVAL_NULL, writeCallback, &wcx)) return std::string("JS_Stringify failed"); return wcx.accum; } +/** + * Convert a list of values to a list of strings representing a JSON document. + */ const list writeJSONList(const list& listSoFar, const std::string& s) { return cons(s, listSoFar); } -/** - * Convert a list of values to a JSON document represented as a list of strings. - */ const failable, std::string> writeJSON(const JSONContext& cx, const list& l) { const failable, std::string> ls = writeJSON >(cx, writeJSONList, list(), l); if (!hasValue(ls)) diff --git a/cpp/sca/test/store-script/htdocs/store.html b/cpp/sca/test/store-script/htdocs/store.html index 42f58ab40c..4a2c65d07c 100644 --- a/cpp/sca/test/store-script/htdocs/store.html +++ b/cpp/sca/test/store-script/htdocs/store.html @@ -31,7 +31,7 @@ //var shoppingCart = new tuscany.sca.Reference("shoppingCart"); //@Reference - //var shoppingTotal = new tuscany.sca.Reference("shoppingTotal"); + var shoppingTotal = new tuscany.sca.Reference("shoppingTotal"); var catalogItems; @@ -42,13 +42,16 @@ } var catalog = ""; - for (var i=0; i' + item + '
'; - } - document.getElementById('catalog').innerHTML=catalog; - catalogItems = items; + for (var i=0; i' + item + '
'; + } + document.getElementById('catalog').innerHTML=catalog; + catalogItems = items; + + // TEMP + shoppingTotal.getTotal(shoppingTotal_getTotalResponse); } function shoppingCart_getResponse(feed) { @@ -65,7 +68,7 @@ if (entries.length != 0) { try { - //shoppingTotal.getTotal(shoppingTotal_getTotalResponse); + shoppingTotal.getTotal(shoppingTotal_getTotalResponse); } catch(e){ alert(e); diff --git a/cpp/sca/test/store-script/htdocs/store.js b/cpp/sca/test/store-script/htdocs/store.js index 47af7c01f7..526d36790a 100644 --- a/cpp/sca/test/store-script/htdocs/store.js +++ b/cpp/sca/test/store-script/htdocs/store.js @@ -652,7 +652,7 @@ tuscany.sca.Property = function (name) { tuscany.sca.referenceMap = new Object(); tuscany.sca.referenceMap.catalog = new JSONRpcClient("/Catalog").Service; //tuscany.sca.referenceMap.shoppingCart = new AtomClient("/ShoppingCart/Cart"); -//tuscany.sca.referenceMap.shoppingTotal = new JSONRpcClient("/ShoppingCart/Total").Service; +tuscany.sca.referenceMap.shoppingTotal = new JSONRpcClient("/ShoppingCart/Total").Service; tuscany.sca.Reference = function (name) { return tuscany.sca.referenceMap[name]; } diff --git a/cpp/sca/test/store-script/store-script-test.cpp b/cpp/sca/test/store-script/store-script-test.cpp index 95e7ba0929..8eac2f7b8b 100644 --- a/cpp/sca/test/store-script/store-script-test.cpp +++ b/cpp/sca/test/store-script/store-script-test.cpp @@ -52,19 +52,35 @@ const tuscany::value evalLoop(std::istream& is, const tuscany::value& req, tusca } bool testEval() { - std::ifstream is("store.scm", std::ios_base::in); - std::ostringstream os; + { + std::ifstream is("store.scm", std::ios_base::in); + std::ostringstream os; + + tuscany::setupEvalOut(os); + tuscany::Env globalEnv = tuscany::setupEnvironment(); + + const tuscany::value req(tuscany::mklist("storeui_service", std::string("getcatalog"))); + const tuscany::value res = evalLoop(is, req, globalEnv); + + std::ostringstream rs; + rs << res; + assert(contains(rs.str(), "List::(List::(List::(Symbol::name, (String::\"apple\", ())), (List::(Symbol::currency, (String::\"USD\", ())), (List::(Symbol::symbol, (String::\"$\", ())), (List::(Symbol::price, (Number::2.99, ())), ())))), (List::(List::(Symbol::name, (String::\"orange\", ())), (List::(Symbol::currency, (String::\"USD\", ())), (List::(Symbol::symbol, (String::\"$\", ())), (List::(Symbol::price, (Number::3.55, ())), ())))), (List::(List::(Symbol::name, (String::\"pear\", ())), (List::(Symbol::currency, (String::\"USD\", ())), (List::(Symbol::symbol, (String::\"$\", ())), (List::(Symbol::price, (Number::1.55, ())), ())))), ())))")); + } - tuscany::setupEvalOut(os); - tuscany::Env globalEnv = tuscany::setupEnvironment(); + { + std::ifstream is("store.scm", std::ios_base::in); + std::ostringstream os; - const tuscany::value req(tuscany::makeList("storeui_service", std::string("getcatalog"))); - const tuscany::value res = evalLoop(is, req, globalEnv); + tuscany::setupEvalOut(os); + tuscany::Env globalEnv = tuscany::setupEnvironment(); - std::ostringstream rs; - rs << res; - assert(contains(rs.str(), "List::(List::(List::(Symbol::name, (String::\"apple\", ())), (List::(Symbol::currency, (String::\"USD\", ())), (List::(Symbol::symbol, (String::\"$\", ())), (List::(Symbol::price, (Number::2.99, ())), ())))), (List::(List::(Symbol::name, (String::\"orange\", ())), (List::(Symbol::currency, (String::\"USD\", ())), (List::(Symbol::symbol, (String::\"$\", ())), (List::(Symbol::price, (Number::3.55, ())), ())))), (List::(List::(Symbol::name, (String::\"pear\", ())), (List::(Symbol::currency, (String::\"USD\", ())), (List::(Symbol::symbol, (String::\"$\", ())), (List::(Symbol::price, (Number::1.55, ())), ())))), ())))")); + const tuscany::value req(tuscany::mklist("storeui_service", std::string("gettotal"))); + const tuscany::value res = evalLoop(is, req, globalEnv); + std::ostringstream rs; + rs << res; + assert(contains(rs.str(), "Number::10")); + } return true; } diff --git a/cpp/sca/test/store-script/store.scm b/cpp/sca/test/store-script/store.scm index 5bda81ca69..323a2ca304 100644 --- a/cpp/sca/test/store-script/store.scm +++ b/cpp/sca/test/store-script/store.scm @@ -54,10 +54,15 @@ content ) +(define (cart_gettotal) + 10.0 +) + (define (cart_impl op args) (cond ((equal? op "post") (apply cart_post args)) ((equal? op "getall") (apply cart_getall args)) + ((equal? op "gettotal") (apply cart_gettotal args)) ) ) @@ -75,11 +80,16 @@ (catalog "get") ) +(define (storeui_gettotal cart) + (cart "gettotal") +) + (define (storeui_impl cart catalog op args) (cond ((equal? op "post") (apply storeui_post (cons cart args))) ((equal? op "getall") (apply storeui_getcart (cons cart args))) ((equal? op "getcatalog") (apply storeui_getcatalog (cons catalog args))) + ((equal? op "gettotal") (apply storeui_gettotal (cons cart args))) ) ) @@ -96,9 +106,11 @@ (define apple (car catalog)) (define full (storeui_service "post" empty apple)) (display (storeui_service "getall" full)) +(display (storeui_service "gettotal")) (; "Store UI JSON-RPC interop test case") -(define (system.listMethods) (list "Service.get")) +(define (system.listMethods) (list "Service.get" "Service.getTotal")) (define (Service.get) (storeui_service "getcatalog")) +(define (Service.getTotal) (storeui_service "gettotal")) -- cgit v1.2.3