You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tuscany.apache.org by js...@apache.org on 2009/10/19 00:25:10 UTC

svn commit: r826545 - in /tuscany/cpp/sca: ./ etc/ modules/ modules/atom/ modules/httpd/ modules/json/ test/store-script/ test/store-script/htdocs/

Author: jsdelfino
Date: Sun Oct 18 22:25:08 2009
New Revision: 826545

URL: http://svn.apache.org/viewvc?rev=826545&view=rev
Log:
Some fixes to the JSON and httpd support. Added support for Atom. Adjusted store test.

Added:
    tuscany/cpp/sca/modules/atom/
    tuscany/cpp/sca/modules/atom/Makefile.am
      - copied, changed from r826544, tuscany/cpp/sca/modules/Makefile.am
    tuscany/cpp/sca/modules/atom/atom-test.cpp
    tuscany/cpp/sca/modules/atom/atom.hpp
Modified:
    tuscany/cpp/sca/configure.ac
    tuscany/cpp/sca/etc/git-exclude
    tuscany/cpp/sca/modules/Makefile.am
    tuscany/cpp/sca/modules/httpd/mod.cpp
    tuscany/cpp/sca/modules/json/json-test.cpp
    tuscany/cpp/sca/modules/json/json.hpp
    tuscany/cpp/sca/test/store-script/htdocs/store.html
    tuscany/cpp/sca/test/store-script/htdocs/store.js
    tuscany/cpp/sca/test/store-script/store-script-test.cpp
    tuscany/cpp/sca/test/store-script/store.scm

Modified: tuscany/cpp/sca/configure.ac
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/configure.ac?rev=826545&r1=826544&r2=826545&view=diff
==============================================================================
--- tuscany/cpp/sca/configure.ac (original)
+++ tuscany/cpp/sca/configure.ac Sun Oct 18 22:25:08 2009
@@ -266,6 +266,7 @@
 AC_CONFIG_FILES([Makefile
                  kernel/Makefile
                  modules/Makefile
+                 modules/atom/Makefile
                  modules/eval/Makefile
                  modules/httpd/Makefile
                  modules/json/Makefile

Modified: tuscany/cpp/sca/etc/git-exclude
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/etc/git-exclude?rev=826545&r1=826544&r2=826545&view=diff
==============================================================================
--- tuscany/cpp/sca/etc/git-exclude (original)
+++ tuscany/cpp/sca/etc/git-exclude Sun Oct 18 22:25:08 2009
@@ -60,8 +60,10 @@
 account_client
 calculator_client
 kernel-test
-xml-test
+xsd-test
+atom-test
 eval-test
+eval-shell
 json-test
 store-function-test
 store-object-test

Modified: tuscany/cpp/sca/modules/Makefile.am
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/modules/Makefile.am?rev=826545&r1=826544&r2=826545&view=diff
==============================================================================
--- tuscany/cpp/sca/modules/Makefile.am (original)
+++ tuscany/cpp/sca/modules/Makefile.am Sun Oct 18 22:25:08 2009
@@ -15,5 +15,5 @@
 #  specific language governing permissions and limitations
 #  under the License.
 
-SUBDIRS = eval httpd json 
+SUBDIRS = atom eval httpd json 
 

Copied: tuscany/cpp/sca/modules/atom/Makefile.am (from r826544, tuscany/cpp/sca/modules/Makefile.am)
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/modules/atom/Makefile.am?p2=tuscany/cpp/sca/modules/atom/Makefile.am&p1=tuscany/cpp/sca/modules/Makefile.am&r1=826544&r2=826545&rev=826545&view=diff
==============================================================================
--- tuscany/cpp/sca/modules/Makefile.am (original)
+++ tuscany/cpp/sca/modules/atom/Makefile.am Sun Oct 18 22:25:08 2009
@@ -15,5 +15,9 @@
 #  specific language governing permissions and limitations
 #  under the License.
 
-SUBDIRS = eval httpd json 
+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 

Added: tuscany/cpp/sca/modules/atom/atom-test.cpp
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/modules/atom/atom-test.cpp?rev=826545&view=auto
==============================================================================
--- tuscany/cpp/sca/modules/atom/atom-test.cpp (added)
+++ tuscany/cpp/sca/modules/atom/atom-test.cpp Sun Oct 18 22:25:08 2009
@@ -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;
+}

Added: tuscany/cpp/sca/modules/atom/atom.hpp
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/modules/atom/atom.hpp?rev=826545&view=auto
==============================================================================
--- tuscany/cpp/sca/modules/atom/atom.hpp (added)
+++ tuscany/cpp/sca/modules/atom/atom.hpp Sun Oct 18 22:25:08 2009
@@ -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 */

Modified: tuscany/cpp/sca/modules/httpd/mod.cpp
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/modules/httpd/mod.cpp?rev=826545&r1=826544&r2=826545&view=diff
==============================================================================
--- tuscany/cpp/sca/modules/httpd/mod.cpp (original)
+++ tuscany/cpp/sca/modules/httpd/mod.cpp Sun Oct 18 22:25:08 2009
@@ -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 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 @@
 
     // 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 @@
     // 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 @@
     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;
 

Modified: tuscany/cpp/sca/modules/json/json-test.cpp
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/modules/json/json-test.cpp?rev=826545&r1=826544&r2=826545&view=diff
==============================================================================
--- tuscany/cpp/sca/modules/json/json-test.cpp (original)
+++ tuscany/cpp/sca/modules/json/json-test.cpp Sun Oct 18 22:25:08 2009
@@ -20,7 +20,7 @@
 /* $Rev$ $Date$ */
 
 /**
- * Test JSON read/write functions.
+ * Test JSON data conversion functions.
  */
 
 #include <assert.h>
@@ -50,34 +50,44 @@
 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;
 }
 

Modified: tuscany/cpp/sca/modules/json/json.hpp
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/modules/json/json.hpp?rev=826545&r1=826544&r2=826545&view=diff
==============================================================================
--- tuscany/cpp/sca/modules/json/json.hpp (original)
+++ tuscany/cpp/sca/modules/json/json.hpp Sun Oct 18 22:25:08 2009
@@ -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 @@
 };
 
 /**
- * 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 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 @@
         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 @@
 }
 
 /**
- * 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 @@
 }
 
 /**
- * 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 @@
 }
 
 /**
- * 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 @@
         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 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 @@
  * 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))

Modified: tuscany/cpp/sca/test/store-script/htdocs/store.html
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/test/store-script/htdocs/store.html?rev=826545&r1=826544&r2=826545&view=diff
==============================================================================
--- tuscany/cpp/sca/test/store-script/htdocs/store.html (original)
+++ tuscany/cpp/sca/test/store-script/htdocs/store.html Sun Oct 18 22:25:08 2009
@@ -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);

Modified: tuscany/cpp/sca/test/store-script/htdocs/store.js
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/test/store-script/htdocs/store.js?rev=826545&r1=826544&r2=826545&view=diff
==============================================================================
--- tuscany/cpp/sca/test/store-script/htdocs/store.js (original)
+++ tuscany/cpp/sca/test/store-script/htdocs/store.js Sun Oct 18 22:25:08 2009
@@ -652,7 +652,7 @@
 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];
 }

Modified: tuscany/cpp/sca/test/store-script/store-script-test.cpp
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/test/store-script/store-script-test.cpp?rev=826545&r1=826544&r2=826545&view=diff
==============================================================================
--- tuscany/cpp/sca/test/store-script/store-script-test.cpp (original)
+++ tuscany/cpp/sca/test/store-script/store-script-test.cpp Sun Oct 18 22:25:08 2009
@@ -52,19 +52,35 @@
 }
 
 bool testEval() {
-    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::makeList<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, ())), ())))), ())))"));
-
+    {
+        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, ())), ())))), ())))"));
+    }
+
+    {
+        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("gettotal")));
+        const tuscany::value res = evalLoop(is, req, globalEnv);
+
+        std::ostringstream rs;
+        rs << res;
+        assert(contains(rs.str(), "Number::10"));
+    }
     return true;
 }
 

Modified: tuscany/cpp/sca/test/store-script/store.scm
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/test/store-script/store.scm?rev=826545&r1=826544&r2=826545&view=diff
==============================================================================
--- tuscany/cpp/sca/test/store-script/store.scm (original)
+++ tuscany/cpp/sca/test/store-script/store.scm Sun Oct 18 22:25:08 2009
@@ -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"))