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.remote.client;
021 
022 import js.Js;
023 import jsx.Returnable;
024 import jsx.http.rpc.remote.Callback;
025 import jsx.http.rpc.remote.Objective;
026 import jsx.http.rpc.remote.Reflector;
027 import jsx.http.rpc.remote.Remote;
028 
029 /**
030  * <p>A client reflection to <tt>java.lang.Object</tt> with the help of {@link Reflector}.</p>
031  * <p>Note that a object of this class is an {@link Objective} at client-side in that 
032  * when finalized it automatically tries to asynchronously dereference its server-side entity.</p>
033  * 
034  * @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>
035  */
036 public class CObject extends Objective
037 {
038     /**
039      * <p>The typical constructor for a {@link CObject} reflection.</p>
040      * @param reflector The {@link Reflector} object associated with the {@link CObject} object 
041      * being constructed.
042      * @param remote The underlying {@link Remote} object associated with the {@link CObject} 
043      * object being constructed.
044      * @since 1.0
045      */
046     protected CObject(Reflector reflector, Remote remote) {
047         super(reflector, remote);
048     }
049 
050     /**
051      * <p>Synchronously creates a {@link CObject} reflection from a {@link Remote} object 
052      * with a {@link Reflector}.</p>
053      * <p>This method synchronously increases server-side references to the {@link Remote} object.</p>
054      * @param reflector The {@link Reflector} object associated with the {@link CObject} object 
055      * being constructed.
056      * @param remote The underlying {@link Remote} object associated with the {@link CObject} 
057      * object being constructed.
058      * @return The created {@link CObject} reflection.
059      * @since 1.0
060      */
061     public static CObject create(Reflector reflector, Remote remote) {
062         reflector.increase(cat(remote));
063         return new CObject(reflector, remote);
064     }
065 
066     /**
067      * <p>Asynchronously creates a {@link CObject} reflection from a {@link Remote} object 
068      * with a {@link Reflector}.</p>
069      * <p>This method asynchronously increases server-side references to the {@link Remote} object.</p>
070      * @param reflector The {@link Reflector} object associated with the {@link CObject} object 
071      * being constructed.
072      * @param remote The underlying {@link Remote} object associated with the {@link CObject} 
073      * object being constructed.
074      * @param rt A {@link Returnable} to return the created {@link CObject} reflection.
075      * @since 1.0
076      */
077     public static void create(final Reflector reflector, final Remote remote, final Returnable<CObject> rt) {
078         reflector.increase(cat(remote), new Callback<Remote>() {
079             @Override
080             public void onCall(Remote ret) {
081                 rt.onReturn(new CObject(reflector, remote));
082             }
083         });
084     }
085 
086     /**
087      * <p>Synchronously calls {@link Object#toString()} on the server-side entity.</p>
088      * @return The result of the remote invocation.
089      * @since 1.0
090      */
091     @Override
092     public final String toString() {
093         if (Js.not(toString)) {
094             toString = getRemoteClass().getMethod(
095                     "toString"
096             );
097         }
098         return Remote.getString(toString.invoke(cat()));
099     }
100 
101     private CMethod toString;
102 
103     /**
104      * <p>Asynchronously gets the {@link Object#toString()} method on the server-side entity.</p>
105      * @param rt A {@link Returnable} to return the result of the remote invocation.
106      * @since 1.0
107      */
108     public final void getToString(final Returnable<CMethod> rt) {
109         if (Js.not(toString)) {
110             getRemoteClass(new Returnable<CClass>() {
111                 public void onReturn(CClass cc) {
112                     cc.getMethod(
113                             "toString",
114                             new Returnable<CMethod>() {
115                                 public void onReturn(CMethod cm) {
116                                     toString = cm;
117                                     rt.onReturn(toString);
118                                 }
119                             }
120                     );
121                 }
122             });
123         } else {
124             rt.onReturn(toString);
125         }
126     }
127 
128     /**
129      * <p>Asynchronously calls {@link Object#toString()} on the server-side entity.</p>
130      * @param rt A {@link Returnable} to return the result of the remote invocation.
131      * @since 1.0
132      */
133     public final void toString(final Returnable<String> rt) {
134         getToString(new Returnable<CMethod>() {
135             public void onReturn(CMethod cm) {
136                 cm.invoke(
137                         cat(),
138                         relay(rt)
139                 );
140             }
141         });
142     }
143 
144     private CClass cClass;
145 
146     /**
147      * <p>Synchronously gets the class of the server-side entity as a {@link CClass}.</p>
148      * @return The result of the remote invocation.
149      * @since 1.0
150      */
151     public final CClass getRemoteClass() {
152         if (Js.not(cClass)) {
153             cClass = CClass.create(reflector, reflector.getRemoteClass(remote));
154         }
155         return cClass;
156     }
157 
158     /**
159      * <p>Asynchronously gets the class of the server-side entity as a {@link CClass}.</p>
160      * @param rt A {@link Returnable} to return the result of the remote invocation.
161      * @since 1.0
162      */
163     public final void getRemoteClass(final Returnable<CClass> rt) {
164         if (Js.not(cClass)) {
165             reflector.increase(cat(), new Callback<Remote>() {
166                 @Override
167                 protected void onCall(Remote ret) {
168                     reflector.getRemoteClass(
169                             remote,
170                             new Callback<Remote>() {
171                                 @Override
172                                 public void onCall(final Remote r) {
173                                     reflector.decrease(cat(), new Callback<Remote>() {
174                                         @Override
175                                         public void onCall(Remote dr) {
176                                             CClass.create(reflector, r, new Returnable<CClass>() {
177                                                 public void onReturn(CClass cc) {
178                                                     cClass = cc;
179                                                     rt.onReturn(cClass);
180                                                 }
181                                             });
182                                         }
183                                     });
184                                 }
185                             }
186                     );
187                 }
188                 
189             });
190         } else {
191             rt.onReturn(cClass);
192         }
193     }
194 
195     /**
196      * <p>Synchronously evaluates a string field of the server-side entity.</p>
197      * @param name The name of the field.
198      * @return The result of the remote evaluation.
199      * @since 1.0
200      */
201     public final String getStringField(String name) {
202         return Remote.getString(
203                 getRemoteClass().getField(name).get(this)
204         );
205     }
206 
207     /**
208      * <p>Asynchronously evaluates a string field of the server-side entity.</p>
209      * @param name The name of the field.
210      * @param rt A {@link Returnable} to return the result of the remote evaluation.
211      * @since 1.0
212      */
213     public final void getStringField(final String name, final Returnable<String> rt) {
214         getRemoteClass(new Returnable<CClass>() {
215             public void onReturn(CClass cc) {
216                 cc.getField(name, new Returnable<CField>() {
217                     public void onReturn(CField cf) {
218                         cf.get(CObject.this, relay(rt));
219                     }
220                 });
221             }
222         });
223     }
224 
225     /**
226      * <p>Relays a given {@link Returnable} for asynchronous service of {@link Reflector}.</p>
227      * @param rt The given {@link Returnable} to be relayed.
228      * @return The relaying {@link Returnable}.
229      * @since 1.0
230      */
231     protected static final Returnable<Remote> relay(final Returnable<String> rt) {
232         return new Returnable<Remote>() {
233             public void onReturn(Remote r) {
234                 rt.onReturn(Remote.getString(r));
235             }
236         };
237     }
238 
239     /**
240      * <p>Relays a given {@link Returnable} for asynchronous service of {@link Reflector}.</p>
241      * @param ref The associated {@link Reflector} object.
242      * @param rt The given {@link Returnable} to be relayed.
243      * @return The relaying {@link Returnable}.
244      * @since 1.0
245      */
246     protected static Returnable<Remote> relay(final Reflector ref, final Returnable<CObject> rt) {
247         return new Returnable<Remote>() {
248             public void onReturn(Remote r) {
249                 create(ref, r, rt);
250             }
251         };
252     }
253 }