diff options
author | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2009-10-18 22:25:08 +0000 |
---|---|---|
committer | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2009-10-18 22:25:08 +0000 |
commit | f87b9f1e48df02c26e0bbe3f8f1664c2b0862e52 (patch) | |
tree | 4d0ee23a5b5c7878b5b4f2131bc17f9765b93313 /cpp | |
parent | 6dd3610df5854ef9af7e5e2907b2f4065d69075d (diff) |
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
Diffstat (limited to 'cpp')
-rw-r--r-- | cpp/sca/configure.ac | 1 | ||||
-rw-r--r-- | cpp/sca/etc/git-exclude | 4 | ||||
-rw-r--r-- | cpp/sca/modules/Makefile.am | 2 | ||||
-rw-r--r-- | cpp/sca/modules/atom/Makefile.am | 23 | ||||
-rw-r--r-- | cpp/sca/modules/atom/atom-test.cpp | 150 | ||||
-rw-r--r-- | cpp/sca/modules/atom/atom.hpp | 154 | ||||
-rw-r--r-- | cpp/sca/modules/httpd/mod.cpp | 10 | ||||
-rw-r--r-- | cpp/sca/modules/json/json-test.cpp | 56 | ||||
-rw-r--r-- | cpp/sca/modules/json/json.hpp | 113 | ||||
-rw-r--r-- | cpp/sca/test/store-script/htdocs/store.html | 21 | ||||
-rw-r--r-- | cpp/sca/test/store-script/htdocs/store.js | 2 | ||||
-rw-r--r-- | cpp/sca/test/store-script/store-script-test.cpp | 34 | ||||
-rw-r--r-- | cpp/sca/test/store-script/store.scm | 14 |
13 files changed, 484 insertions, 100 deletions
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 <assert.h> +#include <iostream> +#include <sstream> +#include <string> +#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("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<entry xmlns=\"http://www.w3.org/2005/Atom\">" + "<title type=\"text\">item</title>" + "<id>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</id>" + "<content type=\"application/xml\">" + "<item>" + "<name>Apple</name><price>$2.99</price>" + "</item>" + "</content>" + "<link href=\"cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\"/>" + "</entry>\n"); + +bool testATOMEntry() { + { + const list<value> i = list<value>() << element << "item" + << (list<value>() << element << "name" << std::string("Apple")) + << (list<value>() << element << "price" << std::string("$2.99")); + const list<value> a = mklist<value>(std::string("item"), std::string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); + std::ostringstream os; + writeATOMEntry<std::ostringstream*>(atomWriter, &os, a); + assert(os.str() == itemEntry); + } + { + const list<value> a = readATOMEntry(mklist(itemEntry)); + std::ostringstream os; + writeATOMEntry<std::ostringstream*>(atomWriter, &os, a); + assert(os.str() == itemEntry); + } + return true; +} + +std::string emptyFeed("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<feed xmlns=\"http://www.w3.org/2005/Atom\">" + "<title type=\"text\">Feed</title>" + "<id>1234</id>" + "</feed>\n"); + +std::string itemFeed("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<feed xmlns=\"http://www.w3.org/2005/Atom\">" + "<title type=\"text\">Feed</title>" + "<id>1234</id>" + "<entry xmlns=\"http://www.w3.org/2005/Atom\">" + "<title type=\"text\">item</title>" + "<id>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</id>" + "<content type=\"application/xml\">" + "<item>" + "<name>Apple</name><price>$2.99</price>" + "</item>" + "</content>" + "<link href=\"cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\"/>" + "</entry>" + "<entry xmlns=\"http://www.w3.org/2005/Atom\">" + "<title type=\"text\">item</title>" + "<id>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c</id>" + "<content type=\"application/xml\">" + "<item>" + "<name>Orange</name><price>$3.55</price>" + "</item>" + "</content>" + "<link href=\"cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c\"/>" + "</entry>" + "</feed>\n"); + +bool testATOMFeed() { + { + std::ostringstream os; + writeATOMFeed<std::ostringstream*>(atomWriter, &os, mklist<value>("Feed", "1234")); + assert(os.str() == emptyFeed); + } + { + const list<value> a = readATOMFeed(mklist(emptyFeed)); + std::ostringstream os; + writeATOMFeed<std::ostringstream*>(atomWriter, &os, a); + assert(os.str() == emptyFeed); + } + { + const list<value> i = list<value>() + << (list<value>() << "item" << "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b" + << (list<value>() << element << "item" + << (list<value>() << element << "name" << "Apple") + << (list<value>() << element << "price" << "$2.99"))) + << (list<value>() << "item" << "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c" + << (list<value>() << element << "item" + << (list<value>() << element << "name" << "Orange") + << (list<value>() << element << "price" << "$3.55"))); + const list<value> a = cons<value>("Feed", cons<value>("1234", i)); + std::ostringstream os; + writeATOMFeed<std::ostringstream*>(atomWriter, &os, a); + assert(os.str() == itemFeed); + } + { + const list<value> a = readATOMFeed(mklist(itemFeed)); + std::ostringstream os; + writeATOMFeed<std::ostringstream*>(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 <string> +#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<value> atomEntry(const list<value>& e) { + const list<value> t = filter<value>(selector(mklist<value>(element, "title")), e); + const list<value> i = filter<value>(selector(mklist<value>(element, "id")), e); + const list<value> c = filter<value>(selector(mklist<value>(element, "content")), e); + return mklist<value>(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<value> atomEntries(const list<value>& e) { + if (isNil(e)) + return list<value>(); + return cons<value>(atomEntry(car(e)), atomEntries(cdr(e))); +} + +/** + * Convert a list of strings to a list of values representing an ATOM entry. + */ +const failable<list<value>, std::string> readATOMEntry(const list<std::string>& ilist) { + const list<value> 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<list<value>, std::string> readATOMFeed(const list<std::string>& ilist) { + const list<value> f = readXML(ilist); + if (isNil(f)) + return std::string("Empty feed"); + const list<value> t = filter<value>(selector(mklist<value>(element, "title")), car(f)); + const list<value> i = filter<value>(selector(mklist<value>(element, "id")), car(f)); + const list<value> e = filter<value>(selector(mklist<value>(element, "entry")), car(f)); + if (isNil(e)) + return mklist<value>(elementValue(car(t)), elementValue(car(i))); + return cons<value>(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<value> atomEntryElement(const list<value>& l) { + return list<value>() + << element << "entry" << (list<value>() << attribute << "xmlns" << "http://www.w3.org/2005/Atom") + << (list<value>() << element << "title" << (list<value>() << attribute << "type" << "text") << car(l)) + << (list<value>() << element << "id" << cadr(l)) + << (list<value>() << element << "content" << (list<value>() << attribute << "type" << "application/xml") << caddr(l)) + << (list<value>() << element << "link" << (list<value>() << attribute << "href" << cadr(l))); +} + +/** + * Convert a list of values representing ATOM entries to a list of elements. + */ +const list<value> atomEntriesElements(const list<value>& l) { + if (isNil(l)) + return list<value>(); + return cons<value>(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<typename R> const failable<R, std::string> writeATOMEntry(const lambda<R(R, std::string)>& reduce, const R& initial, const list<value>& l) { + return writeXML<R>(reduce, initial, mklist<value>(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<std::string> writeATOMList(const list<std::string>& listSoFar, const std::string& s) { + return cons(s, listSoFar); +} + +const failable<list<std::string>, std::string> writeATOMEntry(const list<value>& l) { + const failable<list<std::string>, std::string> ls = writeATOMEntry<list<std::string> >(writeATOMList, list<std::string>(), l); + if (!hasValue(ls)) + return ls; + return reverse(list<std::string>(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<typename R> const failable<R, std::string> writeATOMFeed(const lambda<R(R, std::string)>& reduce, const R& initial, const list<value>& l) { + const list<value> f = list<value>() + << element << "feed" << (list<value>() << attribute << "xmlns" << "http://www.w3.org/2005/Atom") + << (list<value>() << element << "title" << (list<value>() << attribute << "type" << "text") << car(l)) + << (list<value>() << element << "id" << cadr(l)); + if (isNil(cddr(l))) + return writeXML<R>(reduce, initial, mklist<value>(f)); + const list<value> fe = append(f, atomEntriesElements(cddr(l))); + return writeXML<R>(reduce, initial, mklist<value>(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<list<std::string>, std::string> writeATOMFeed(const list<value>& l) { + const failable<list<std::string>, std::string> ls = writeATOMFeed<list<std::string> >(writeATOMList, list<std::string>(), l); + if (!hasValue(ls)) + return ls; + return reverse(list<std::string>(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<value> queryArg(std::string s) { const list<std::string> t = tokenize("=", s); - return makeList<value>(car(t).c_str(), cadr(t)); + return mklist<value>(car(t).c_str(), cadr(t)); } const list<list<value> > 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<list<std::string>, std::string> jsval = writeJSON(cx, makeList<value>(makeList<value>("id", id), makeList<value>("result", val))); + failable<list<std::string>, std::string> jsval = writeJSON(cx, mklist<value>(mklist<value>("id", id), mklist<value>("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<std::string> req = read(r); JSONContext cx; - const list<value> json = readJSON(cx, req); + const list<value> json = elementsToValues(readJSON(cx, req)); const list<list<value> > 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<list<std::string>, std::string> jsval = writeJSON(cx, makeList<value>(makeList<value>("id", id), makeList<value>("result", val))); + const list<value> result = valuesToElements(mklist<value>(mklist<value>("id", id), mklist<value>("result", val))); + failable<list<std::string>, 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 <assert.h> @@ -50,34 +50,44 @@ std::ostringstream* jsonWriter(std::ostringstream* os, const std::string& s) { bool testJSON() { const JSONContext cx; - const list<value> phones = makeList<value> (std::string("408-1234"), std::string("650-1234")); - const list<value> l = makeList<value> (makeList<value> ("phones", phones), makeList<value> ("lastName", std::string("test\ttab")), makeList<value> ("firstName", std::string("test1"))); - print(l, std::cout); - std::cout << std::endl; - - std::ostringstream os; - writeJSON<std::ostringstream*>(cx, jsonWriter, &os, l); - std::cout << os.str() << std::endl; - - std::istringstream is(os.str()); - const list<std::string> il = makeStreamList(is); - const list<value> 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<value> ad = mklist<value>(mklist<value>(attribute, "city", std::string("san francisco")), mklist<value>(attribute, "state", std::string("ca"))); + const list<value> ac = mklist<value>(mklist<value>(element, "id", std::string("1234")), mklist<value>(attribute, "balance", 1000)); + const list<value> cr = mklist<value>(mklist<value> (attribute, "name", std::string("jdoe")), cons<value>(element, cons<value>("address", ad)), cons<value>(element, cons<value>("account", ac))); + const list<value> c = mklist<value>(cons<value>(element, cons<value>("customer", cr))); + std::ostringstream os; + writeJSON<std::ostringstream*>(cx, jsonWriter, &os, c); + assert(os.str() == "{\"customer\":{\"name\":\"jdoe\",\"address\":{\"city\":\"san francisco\",\"state\":\"ca\"},\"account\":{\"id\":\"1234\",\"balance\":1000}}}"); + } + { + const list<value> phones = mklist<value> (std::string("408-1234"), std::string("650-1234")); + const list<value> l = mklist<value> (mklist<value> (element, "phones", phones), mklist<value> (attribute, "lastName", std::string("test\ttab")), mklist<value> (attribute, "firstName", std::string("test1"))); + + std::ostringstream os; + writeJSON<std::ostringstream*>(cx, jsonWriter, &os, l); + assert(os.str() == "{\"phones\":[\"408-1234\",\"650-1234\"],\"lastName\":\"test\\u0009tab\",\"firstName\":\"test1\"}"); + + std::istringstream is(os.str()); + const list<std::string> il = streamList(is); + const list<value> 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<value> v = readJSON(cx, makeList(lm)); - std::cout << v << std::endl; + const list<value> e = readJSON(cx, mklist(lm)); + const list<value> v = elementsToValues(e); + + assert(assoc<value>("id", v) == mklist<value>("id", 1)); + assert(assoc<value>("method", v) == mklist<value>("method", std::string("system.listMethods"))); + assert(assoc<value>("params", v) == mklist<value>("params", list<value>())); 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 <assert.h> #define XP_UNIX #include <jsapi.h> #include <string> #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<value> jsPropertiesToValues(const JSONContext& cx, const list<value>& propertiesSoFar, JSObject* o, - JSObject* i) { +const list<value> jsPropertiesToValues(const JSONContext& cx, const list<value>& propertiesSoFar, JSObject* o, JSObject* i) { const value jsValToValue(const JSONContext& cx, const jsval& jsv); @@ -155,14 +154,15 @@ const list<value> jsPropertiesToValues(const JSONContext& cx, const list<value>& const value val = jsValToValue(cx, jsv); jsval idv; JS_IdToValue(cx, id, &idv); - if(JSVAL_IS_STRING(idv)) - return jsPropertiesToValues(cx, cons<value> (makeList<value> (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<value> (mklist<value> (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<value> ()); - return jsPropertiesToValues(cx, list<value> (), o, i); + const value pv = jsPropertiesToValues(cx, list<value> (), o, i); + return pv; } default: { return value(); @@ -203,7 +204,7 @@ failable<bool, std::string> 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<list<value>, std::string> readJSON(const JSONContext& cx, const list<std::string>& ilist) { jsval val; @@ -222,22 +223,6 @@ const failable<list<value>, std::string> readJSON(const JSONContext& cx, const l } /** - * Returns true if a list represents a JS array. - */ -const bool isJSArray(const list<value>& l) { - if(isNil(l)) - return false; - value v = car(l); - if(isList(v)) { - const list<value> p = v; - if(isSymbol(car(p))) { - return false; - } - } - return true; -} - -/** * Converts a list of values to JS array elements. */ JSObject* valuesToJSElements(const JSONContext& cx, JSObject* a, const list<value>& l, int i) { @@ -250,24 +235,12 @@ JSObject* valuesToJSElements(const JSONContext& cx, JSObject* a, const list<valu } /** - * Converts a list of values to JS properties. - */ -JSObject* valuesToJSProperties(const JSONContext& cx, JSObject* o, const list<value>& l) { - const jsval valueToJSVal(const JSONContext& cx, const value& val); - if(isNil(l)) - return o; - const list<value> 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<bool, std::string> writeList(const JSONContext& cx, const list<value>& 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<bool, std::string> 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<typename R> class JSONWriteContext { public: @@ -314,20 +320,25 @@ template<typename R> JSBool writeCallback(const jschar *buf, uint32 len, void *d * Convert a list of values to a JSON document. */ template<typename R> const failable<R, std::string> writeJSON(const JSONContext& cx, const lambda<R(R, std::string)>& reduce, const R& initial, const list<value>& l) { - jsval val = valueToJSVal(cx, l); + JSObject* o = JS_NewObject(cx, NULL, NULL, NULL); + jsval val = OBJECT_TO_JSVAL(o); + const failable<bool, std::string> w = writeList(cx, l, o); + if (!hasValue(w)) + return std::string(w); + JSONWriteContext<R> wcx(cx, reduce, initial); if (!JS_Stringify(cx, &val, NULL, JSVAL_NULL, writeCallback<R>, &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<std::string> writeJSONList(const list<std::string>& 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<list<std::string>, std::string> writeJSON(const JSONContext& cx, const list<value>& l) { const failable<list<std::string>, std::string> ls = writeJSON<list<std::string> >(cx, writeJSONList, list<std::string>(), 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<items.length; i++) {
- var item = items[i].name + ' - ' + items[i].price;
- catalog += '<input name="items" type="checkbox" value="' +
- item + '">' + item + ' <br>';
- }
- document.getElementById('catalog').innerHTML=catalog;
- catalogItems = items;
+ for (var i=0; i<items.length; i++) {
+ var item = items[i].name + ' - ' + items[i].price;
+ catalog += '<input name="items" type="checkbox" value="' +
+ item + '">' + item + ' <br>';
+ }
+ 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<tuscany::value>("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<tuscany::value>("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<tuscany::value>("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")) |