001 
002 /*
003  *  JScripter Emulation 1.0 - To Script 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 org.jscripter.emu.java.lang;
021 
022 import org.jscripter.emu.java.JavaClass;
023 import org.jscripter.emu.java.JavaInterface;
024 import org.jscripter.emu.java.JavaObject;
025 
026 import js.*;
027 import js.core.JsGlobal;
028 
029 /**
030  * <p><b>Internal</b> instances of the class <tt>java.lang.Class</tt> represent classes and 
031  * interfaces in a running application, emulating a 
032  * standard <tt>java.lang</tt> interface or class with the same simple name as this one.</p>
033  * <p>This interface or class is only used internally by JS re-compiler implementations.</p>
034  * <p>Please refer to <a href="http://java.sun.com/docs/">the Java API Standards</a> for detail description of the original class or interface.</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  * @javascript Re-compilers must redirect the resolution of the emulated original Java class or interface to this one.
039  */
040 public final class Class<T>
041 {
042     private Class() {}
043 
044     /**
045      * <p>Casts this Class object to represent a subclass of the class represented by the 
046      * specified class object. Checks that that the cast is valid, and throws a 
047      * <tt>java.lang.ClassCastException</tt> if it is not. If this method succeeds, it always 
048      * returns a reference to this class object.</p>
049      * @param clazz A class object.
050      * @return This Class object, cast to represent a subclass of the specified class object.
051      * @throws java.lang.ClassCastException if this Class object does not represent a subclass 
052      * of the specified class (here "subclass" includes the class itself).
053      * @since 1.0
054      * @javascript Re-compilers must report error on end-users directly using this method.
055      */
056     public <U> java.lang.Class<? extends U> asSubclass(java.lang.Class<U> clazz) {
057         if (isAssignableFrom(clazz)) {
058             return clazz;
059         }
060         throw new java.lang.ClassCastException();
061     }
062 
063     /**
064      * <p>Casts an object to the class or interface represented by this Class object.</p>
065      * @param obj An object to be cast.
066      * @return The object after casting, or <tt>null</tt> if <tt>obj</tt> is <tt>null</tt>.
067      * @throws java.lang.ClassCastException if the object is not <tt>null</tt> and is not 
068      * assignable to the type T.
069      * @since 1.0
070      * @javascript Re-compilers must report error on end-users directly using this method.
071      */
072     @SuppressWarnings("unchecked")
073     public T cast(Object obj) {
074         return (T)obj;
075     }
076 
077     /**
078      * <p>Determines the interfaces implemented by the class or interface represented by 
079      * this object.</p>
080      * @return An array of interfaces implemented by this class.
081      * @since 1.0
082      * @javascript Re-compilers must report error on end-users directly using this method.
083      */
084     public java.lang.Class<?>[] getInterfaces() {
085         return (java.lang.Class<?>[])(java.lang.Object)((JavaInterface)(java.lang.Object)this).interfaces;
086     }
087 
088     /**
089      * <p>Returns the name of the class or interface represented by this Class object, 
090      * as a string.</p>
091      * @return The name of the class or interface represented by this object.
092      * @since 1.0
093      * @javascript Re-compilers must report error on end-users directly using this method.
094      */
095     public java.lang.String getName() {
096         return JavaInterface.getName((JavaInterface)(java.lang.Object)this);
097     }
098 
099     /**
100      * <p>Returns the simple name of the underlying class.</p>
101      * <p>Returns an empty string if the underlying class is anonymous.</p>
102      * @return The simple name of the underlying class.
103      * @since 1.0
104      * @javascript Re-compilers must report error on end-users directly using this method.
105      */
106     public java.lang.String getSimpleName() {
107         return JavaInterface.getSimpleName((JavaInterface)(java.lang.Object)this);
108     }
109 
110     /**
111      * <p>Returns the Class representing the superclass of the class or interface represented 
112      * by this Class.</p>
113      * <p>If this Class represents either the <tt>java.lang.Object</tt> class or an interface, 
114      * then <tt>null</tt> is returned. If this object represents an array class then the Class 
115      * object representing the <tt>java.lang.Object</tt> class is returned.</p>
116      * @return The superclass of the class represented by this object.
117      * @since 1.0
118      * @javascript Re-compilers must report error on end-users directly using this method.
119      */
120     @SuppressWarnings("unchecked")
121     public java.lang.Class<? super T> getSuperclass() {
122         return (java.lang.Class<T>)(java.lang.Object)((JavaClass)(java.lang.Object)this).superClass;
123     }
124 
125     /**
126      * <p>Determines if this Class object represents an array class.</p>
127      * @return <tt>true</tt> if this object represents an array class; <tt>false</tt> otherwise.
128      * @since 1.0
129      * @javascript Re-compilers must report error on end-users directly using this method.
130      */
131     public boolean isArray() {
132         return Js.eq(this, JsGlobal.Array.with());
133     }
134 
135     /**
136      * <p>Determines if the class or interface represented by this Class object is either the 
137      * same as, or is a superclass or superinterface of, the class or interface represented by 
138      * the specified Class parameter.</p>
139      * @param cls A Class object to be checked.
140      * @return Indicates whether objects of the type <tt>cls</tt> can be assigned to objects of 
141      * this class.
142      * @throws java.lang.NullPointerException if the specified Class parameter is null.
143      * @since 1.0
144      * @javascript Re-compilers must report error on end-users directly using this method.
145      */
146     public boolean isAssignableFrom(java.lang.Class<?> cls) throws java.lang.NullPointerException {
147         return isInterface() ? JavaInterface.isSuperInterface(
148                 (JavaInterface)(java.lang.Object)this,
149                 (JavaInterface)(java.lang.Object)cls
150         ) : JavaClass.isSuperClass(
151                 (JavaClass)(java.lang.Object)this,
152                 (JavaClass)(java.lang.Object)cls
153         );
154     }
155 
156     /**
157      * <p>Determines if the specified Object is assignment-compatible with the object 
158      * represented by this Class.</p>
159      * @param obj An object to check.
160      * @return <tt>true</tt> if <tt>obj</tt> is an instance of this class; <tt>false</tt> otherwise.
161      * @since 1.0
162      * @javascript Re-compilers must report error on end-users directly using this method.
163      */
164     public boolean isInstance(Object obj) {
165         return JavaInterface.instanceOf(obj, (JavaInterface)(java.lang.Object)this);
166     }
167 
168     /**
169      * <p>Determines if the specified Class object represents an interface type.</p>
170      * @return <tt>true</tt> if this object represents an interface; <tt>false</tt> otherwise.
171      * @since 1.0
172      * @javascript Re-compilers must report error on end-users directly using this method.
173      */
174     public boolean isInterface() {
175         return Js.be(((JavaObject)(java.lang.Object)this).jclass) &&
176             Js.not(((JavaClass)(java.lang.Object)this).constructor);
177     }
178 
179     /**
180      * <p>Determines if the specified Class object represents a primitive type.</p>
181      * @return <tt>true</tt> if this object represents a primitive type; <tt>false</tt> otherwise.
182      * @since 1.0
183      * @javascript Re-compilers must report error on end-users directly using this method.
184      */
185     public boolean isPrimitive() {
186         return Js.not(((JavaObject)(java.lang.Object)this).jclass);
187     }
188 
189     /**
190      * <p>Creates a new instance of the class represented by this Class object.</p>
191      * @return A newly allocated instance of the class represented by this object.
192      * @throws java.lang.IllegalAccessException if the class or its nullary constructor 
193      * is not accessible.
194      * @throws java.lang.InstantiationException if this Class represents an abstract class, 
195      * an interface, an array class, a primitive type, or void; or if the class has no nullary 
196      * constructor; or if the instantiation fails for some other reason.
197      * @since 1.0
198      * @javascript Re-compilers must report error on end-users directly using this method.
199      */
200     public T newInstance() throws java.lang.InstantiationException, java.lang.IllegalAccessException {
201         if (isInterface()) {
202             throw new java.lang.IllegalAccessException(getName());
203         }
204         JavaClass jc = (JavaClass)(java.lang.Object)this;
205         if (isPrimitive() || Js.not(jc.init)) {
206             throw new java.lang.InstantiationException(getName());
207         }
208         JavaObject jo = JavaObject.createObject(jc);
209         jc.init.call(jo);
210         return new Ref<T>(jo).value;
211     }
212 
213     /**
214      * <p>Converts the object to a string.</p>
215      * <p>The string representation is the string "class" or "interface", followed by a space, 
216      * and then by the fully qualified name of the class in the format returned by {@link #getName()}.</p>
217      * @return A string representation of this class object.
218      * @since 1.0
219      * @javascript Re-compilers must report error on end-users directly using this method.
220      */
221     @Override
222     public java.lang.String toString() {
223         return Js.toString(this);
224     }
225 }