001 
002 /*
003  *  JScripter Standard 1.0 - To Script In Java
004  *  Copyright (C) 2008-2011  J.J.Liu<jianjunliu@126.com> <http://www.jscripter.org>
005  *  
006  *  This program is free software: you can redistribute it and/or modify
007  *  it under the terms of the GNU Affero General Public License as published by
008  *  the Free Software Foundation, either version 3 of the License, or
009  *  (at your option) any later version.
010  *  
011  *  This program is distributed in the hope that it will be useful,
012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014  *  GNU Affero General Public License for more details.
015  *  
016  *  You should have received a copy of the GNU Affero General Public License
017  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
018  */
019 
020 package jsx.http.rpc;
021 
022 import js.ArrayLike;
023 import js.Js;
024 import js.ObjectLike;
025 import js.user.JsDocument;
026 import js.user.JsElement;
027 import js.user.JsNode;
028 import js.user.JsNodeList;
029 import jsx.client.Global;
030 import jsx.core.ArrayLikes;
031 import jsx.dom.Nodes;
032 
033 /**
034  * <p>XML & HTTP serialization contexts for client-side.</p>
035  * 
036  * @author <a href="mailto:jianjunliu@126.com">J.J.Liu (Jianjun Liu)</a> at <a href="http://www.jscripter.org" target="_blank">http://www.jscripter.org</a>
037  */
038 public class XMLHttpClient extends XMLHttpContext
039 {
040     /**
041      * <p>The default constructor for the contexts of this class type.</p>
042      * <p>The constructor simply invokes the default constructor of the super class.</p>
043      * @since 1.0
044      */
045     public XMLHttpClient() {
046         super();
047     }
048 
049     /**
050      * <p>Prepares XML body for {@link jsx.http.Http} or {@link jsx.http.Ajax} to send or post.</p>
051      * @param base The base object for a remote call.
052      * @param args An array of arguments for a remote call.
053      * @return The XML document ready for {@link jsx.http.Http} or {@link jsx.http.Ajax} to send or post.
054      * @since 1.0
055      */
056     public final String body(HttpRemote base, ArrayLike<?> args) {
057         String s = "";
058         for (int i = 0, len = ArrayLikes.length(args); i < len; i++) {
059             s = Js.add(s, serialize(args.get(i), 0));
060         }
061         s = xelt(ARGS, s);
062         s = Js.add(xelt(BASE, serialize(base, 0)), s);
063         s = Js.add(xelt(CNTX, serialize()), s);
064         s = Js.add(xelt(SIDS, sids()), s);
065         return doc(xelt(XML, s));
066     }
067 
068     /**
069      * <p>Gets the return value of a remote call.</p>
070      * @param response The XML response of the remote call.
071      * @return The return value.
072      * @since 1.0
073      */
074     public final Object getReturn(JsDocument response) {
075         return deserialize(
076                 Nodes.firstChild(
077                         getFirstByTag(response, RTRN)
078                 )
079         );
080     }
081 
082     /**
083      * <p>Updates the calling context with an XML response.</p>
084      * @param response The XML response of the remote call.
085      * @since 1.0
086      */
087     public final void updateContext(JsDocument response) {
088         expand(getText(getFirstByTag(response, SIDS)));
089         JsNode n = Nodes.firstChild(
090                 getFirstByTag(response, CNTX)
091         );
092         while (Js.be(n)) {
093             updateObject(n);
094             n = Nodes.nextSibling(n);
095         }
096     }
097 
098     private final void updateObject(JsNode n) {
099         ObjectLike o = object(getText(getFirstByTag(n, SID)));
100         JsNodeList<? extends JsElement> flds = Nodes.getElementsByTagName(n, FLD);
101         for (int i = 0, len = flds.length(); i < len; i++) {
102             JsNode f = flds.get(i);
103             o.var(
104                     getText(
105                             getFirstByTag(f, IDX)
106                     ),
107                     deserialize(
108                             Nodes.firstChild(
109                                     getFirstByTag(f, VAL)
110                             )
111                     )
112             );
113         }
114     }
115 
116     private static final JsElement getFirstByTag(JsNode node, String tag) {
117         return Nodes.getElementsByTagName(node, tag).get(0);
118     }
119 
120     private static final String getText(JsNode n) {
121         return Nodes.nodeValue(Nodes.firstChild(n));
122     }
123 
124     private final Object deserialize(JsNode n) {
125         String t = Nodes.tagName(n);
126         if (t == NUM) {
127             return Global.parseFloat(getText(n));
128         }
129         if (t == STR) {
130             return getText(n);
131         }
132         return object(getText(n));
133     }
134 }