001 
002 /*
003  *  JScripter Simulation 1.0 - For Java To Script
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 org.jscripter.sim.client;
021 
022 import java.applet.Applet;
023 
024 import netscape.javascript.JSObject;
025 import js.*;
026 import js.core.*;
027 import js.user.*;
028 
029 /**
030  * <p>An <b>internal</b> class for JS Embeded Simulation on FireFox-compatible browsers.</p>
031  * <p>This <b>internal</b> class is only extended internally in JS Simulation Library.</p>
032  *
033  * @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>
034  * 
035  * @javascript Re-compilers must report error on resolving an <tt>internal</tt> class. 
036  */
037 public final class EmbededFF extends Embeded
038 {
039     /**
040      * <p>Internally constructs a JS Embeded Simulation from an applet on a FireFox-compatible browser.</p>
041      * @param applet A Java applet.
042      * @since 1.0
043      * 
044      * @javascript Re-compilers must report error on the invocation to an <b>internal</b> constructor. 
045      */
046     protected EmbededFF(Applet applet) {
047         super(applet);
048     }
049 
050     /**
051      * <p>Internally creates function object from a function definition.</p>
052      * @param f A {@link Function} definition.
053      * @return The function object.
054      * @since 1.0
055      * @javascript Re-compilers must report error on the invocation to an <b>internal</b> method. 
056      */
057     @Override
058     protected <T> JsFunction<T> var(Function<T> f) {
059         return new JseFunction<T>(
060                 new JseObjectFF.JseoFunction<T>(
061                         f
062                 )
063         );
064     }
065 
066     private JsWin win;
067 
068     /**
069      * <p>Returns the opaque global object with the client-side support.</p>
070      * @return The opaque global object with the client-side support.
071      * @see Js#win()
072      * @see jsx.client.Client
073      * @since 1.0
074      * @javascript Re-compilers must report error on the invocation to an <b>internal</b> method. 
075      */
076     @Override
077     protected JsWin win() {
078         if (win == null) {
079             win = new JsWin(new JseObjectFF(getWindow()));;
080         }
081         return win;
082     }
083 
084     /**
085      * <p>Internally creates a variable list from a value or object.</p>
086      * @param args A value or object.
087      * @return The variable list created.
088      * @since 1.0
089      * @javascript Re-compilers must report error on the invocation to an <b>internal</b> method. 
090      */
091     @Override
092     protected Vars<?> vars(Object args) {
093         if (args instanceof Var<?>) {
094             args = ((Var<?>)args).var();
095         }
096         Vars<Object> vars = new Vars<Object>();
097         if (args instanceof JsObject) {
098             args = ((Live)((JsObject)args).var()).getJSObject();
099         }
100         if (args instanceof JSObject) {
101             if (((JSObject)args).getMember("length") != null) {
102                 args = new JseArray(new JseObjectFF(args));
103             }
104         }
105         if (args instanceof ArrayObject<?>) {
106             ArrayObject<?> a = (ArrayObject<?>)args;
107             for (int l = a.length(), i = 0; i < l; i++) {
108                 vars.add(JseObjectFF.wrap(a.get(i)));
109             }
110         } else if (args.getClass().isArray()) {
111             Object[] a = (Object[])args;
112             for (int l = a.length, i = 0; i < l; i++) {
113                 vars.add(JseObjectFF.wrap(a[i]));
114             }
115         } else if (args != null) {
116             vars.add(JseObjectFF.wrap(args));
117         }
118         return vars;
119     }
120 
121     /**
122      * <p>Creates a JavaScript function.</p>
123      * <p>A function is a fundamental data-type in JavaScript. Note that although functions 
124      * may be created with this method, this is not efficient, and the preferred way to 
125      * define functions, in most cases, is to extend {@link Function}.</p>
126      * @param args A list of the argument values, each naming one or more arguments of the 
127      * function being created, ended with a string that specifies the body of the function.
128      * @return A newly created function. Invoking it executes the JavaScript code specified 
129      * by last string value of the variable argument <tt>args</tt>.
130      * @throws RuntimeException JavaScript throws a <tt>SyntaxError</tt> if there was a 
131      * JavaScript syntax error in one of the value of the variable arguments. See {@link Js#err(Object)} 
132      * and {@link js.core.JsSyntaxError} for JS Simulation.
133      * @see Function
134      * @since 1.0
135      * @javascript Re-compilers must report error on the invocation to an <b>internal</b> method. 
136      */
137     @Override
138     protected <T> JsFunction<T> function(Vars<String> args) {
139         ArrayLike<String> a = args.var();
140         int alen = a.length();
141         StringBuilder sb = new StringBuilder("Object(function(");
142         if (alen < 1) {
143             sb.append("){})");
144         } else {
145             for (int i = 0; i < alen - 1; i++) {
146                 if (i > 0) {
147                     sb.append(',');
148                 }
149                 sb.append(a.get(i));
150             }
151             sb.append("){").append(a.get(alen - 1)).append("})");
152         }
153         return new JseFunction<T>(
154                 new JseObjectFF(
155                         getWindow().eval(sb.toString())
156                 )
157         );
158     }
159 
160     /**
161      * <p>Gets the list of the property names of an object.</p>
162      * @param o The object.
163      * @return The list of the property names of the object.
164      * @since 1.0
165      * @javascript Re-compilers must report error on the invocation to an <b>internal</b> method. 
166      */
167     @SuppressWarnings("unchecked")
168     @Override
169     protected final ArrayLike<String> keys(JsObject o) {
170         return (ArrayLike<String>)(ArrayLike<?>)new JseArray(new JseObjectFF(
171                 getWindow().call(
172                         "$keys",
173                         new Object[]{JseObject.unwrap(o)}
174                 )
175         ));
176     }
177 }