summaryrefslogtreecommitdiff
path: root/src/main/java/io/devnulllabs/openjava/mop/OJClass.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/io/devnulllabs/openjava/mop/OJClass.java')
-rw-r--r--src/main/java/io/devnulllabs/openjava/mop/OJClass.java3071
1 files changed, 3071 insertions, 0 deletions
diff --git a/src/main/java/io/devnulllabs/openjava/mop/OJClass.java b/src/main/java/io/devnulllabs/openjava/mop/OJClass.java
new file mode 100644
index 0000000..673e73e
--- /dev/null
+++ b/src/main/java/io/devnulllabs/openjava/mop/OJClass.java
@@ -0,0 +1,3071 @@
+/*
+ * OJClass.java
+ *
+ * comments here.
+ *
+ * @author Michiaki Tatsubori
+ * @version %VERSION% %DATE%
+ * @see java.lang.Object
+ *
+ * COPYRIGHT 1999 by Michiaki Tatsubori, ALL RIGHTS RESERVED.
+ */
+package io.devnulllabs.openjava.mop;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Writer;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import io.devnulllabs.openjava.ptree.AllocationExpression;
+import io.devnulllabs.openjava.ptree.ArrayAccess;
+import io.devnulllabs.openjava.ptree.ArrayAllocationExpression;
+import io.devnulllabs.openjava.ptree.AssignmentExpression;
+import io.devnulllabs.openjava.ptree.CastExpression;
+import io.devnulllabs.openjava.ptree.ClassDeclaration;
+import io.devnulllabs.openjava.ptree.ConstructorDeclaration;
+import io.devnulllabs.openjava.ptree.Expression;
+import io.devnulllabs.openjava.ptree.FieldAccess;
+import io.devnulllabs.openjava.ptree.FieldDeclaration;
+import io.devnulllabs.openjava.ptree.MemberDeclaration;
+import io.devnulllabs.openjava.ptree.MemberDeclarationList;
+import io.devnulllabs.openjava.ptree.MemberInitializer;
+import io.devnulllabs.openjava.ptree.MethodCall;
+import io.devnulllabs.openjava.ptree.MethodDeclaration;
+import io.devnulllabs.openjava.ptree.ParseTree;
+import io.devnulllabs.openjava.ptree.ParseTreeException;
+import io.devnulllabs.openjava.ptree.Statement;
+import io.devnulllabs.openjava.ptree.StatementList;
+import io.devnulllabs.openjava.ptree.TypeName;
+import io.devnulllabs.openjava.ptree.VariableDeclaration;
+import io.devnulllabs.openjava.ptree.util.PartialParser;
+import io.devnulllabs.openjava.ptree.util.TypeNameQualifier;
+import io.devnulllabs.openjava.syntax.SyntaxRule;
+import io.devnulllabs.openjava.tools.DebugOut;
+
+/**
+ * The <code>OJClass</code> class represents a class metaobject. If
+ * the class has its valid .class file in CLASSPATH, the metaobject can
+ * behave like <code>java.lang.Class</code>. If the class has its
+ * valid .oj file in the packages where some classes are being compiled
+ * by OpenJava system, or in the packages explicitly specified by
+ * something like OpenJava compiler option or environment variable, the
+ * metaobject can have information about source code just as
+ * stamements, expressions, and etc.
+ * <p>
+ * Additionaly, you can overrides the methods for introspection.
+ * <pre>
+ * OJClass[] getDeclaredClasses()
+ * OJMethod[] getDeclaredMethods()
+ * OJField[] getDeclaredFields()
+ * OJConstructor[] getDeclaredConstructors()
+ * OJMethod getAcceptableMethod(OJClass,String,OJClass[])
+ * OJMethod getAcceptableConstructor(OJClass,String,OJClass[])
+ * </pre>
+ *
+ * @author Michiaki Tatsubori
+ * @version 1.0
+ * @since $Id: OJClass.java,v 1.3 2005/04/04 08:27:49 tatsubori Exp $
+ * @see java.lang.Class
+ * @see io.devnulllabs.openjava.mop.OJMethod
+ * @see io.devnulllabs.openjava.mop.OJField
+ * @see io.devnulllabs.openjava.mop.OJConstructor
+ *
+ **/
+public class OJClass implements OJMember {
+
+ private OJClassImp substance;
+
+ /* -- constructors -- */
+
+ /**
+ * Generates a metaobject from source code.
+ * <p>
+ * This constructor will be invoked by the OpenJava system.
+ * In inheriting this class, you must call this consturctor
+ * from a constructor with the same signature in your class.
+ * <p>
+ * For example, in defining a subclass <code>YourClass</code>
+ * derived from this class, at least you have to write as follows:
+ * <pre>
+ * public YourClass( Environment outer_env, OJClass declarer,
+ * ClassDeclaration ptree ) {
+ * super( outer_env, declarer, ptree );
+ * }
+ * </pre>
+ *
+ * @param outer_env environment of this class metaobject
+ * @param declarer the class metaobject declaring this
+ * class metaobject.
+ * @param ptree the parse tree representing this class metaobject.
+ */
+ public OJClass(
+ Environment outer_env,
+ OJClass declarer,
+ ClassDeclaration ptree) {
+ substance = new OJClassSourceCode(this, outer_env, declarer, ptree);
+ }
+
+ /**
+ * Generates a metaobject from byte code.
+ * <p>
+ * This constructor will be invoked only by the OpenJava system.
+ * In inheriting this class, you must call this consturctor
+ * from a constructor with the same signature in your class.
+ * <p>
+ * For example, in defining a subclass <code>YourClass</code>
+ * derived from this class, at least you have to write as follows:
+ * <pre>
+ * public YourClass( Class java_class, MetaInfo metainfo ) {
+ * super( java_class, metainfo );
+ * }
+ * </pre>
+ *
+ * @param outer_env environment of this class metaobject
+ * @param declarer the class metaobject declaring this
+ * class metaobject.
+ * @param ptree the parse tree representing this class metaobject.
+ */
+ public OJClass(Class java_class, MetaInfo metainfo) {
+ substance = new OJClassByteCode(java_class, metainfo);
+ }
+
+ /**
+ * For arrays
+ */
+ private OJClass(OJClass componentType) {
+ substance = new OJClassArray(componentType);
+ }
+
+ /**
+ * For dummy type of null object.
+ * This should be called only once by OJSystem.initConstants().
+ */
+ OJClass() {
+ substance = new OJClassNull();
+ }
+
+ /* -- Introspection Part -- */
+
+ /**
+ * Returns the <code>OJClass</code> object associated with the class
+ * with the given string name.
+ * Given the fully-qualified name for a class or interface, this
+ * method attempts to locate, load and link the class. If it
+ * succeeds, returns the Class object representing the class. If
+ * it fails, the method throws a OJClassNotFoundException.
+ * <p>
+ * For example, the following code fragment returns the runtime
+ * <code>OJClass</code> descriptor for the class named
+ * <code>java.lang.Thread</code>:
+ * <ul><code>
+ * OJClass t = OJClass.forName( "java.lang.Thread" );
+ * </code></ul>
+ *
+ * @param name the fully qualified name of the desired
+ * class.
+ * @return the <code>OJClass</code> descriptor for the class with
+ * the specified name.
+ * @exception OJClassNotFoundException if the class could not be
+ * found.
+ */
+ public static OJClass forName(String name)
+ throws OJClassNotFoundException {
+ DebugOut.println("OJClass.forName(\"" + name.toString() + "\")");
+
+ name = nameForJavaClassName(name);
+
+ OJClass result;
+
+ result = OJSystem.env.lookupClass(name);
+ if (result != null)
+ return result;
+
+ if (isArrayName(name)) {
+ OJClass component = forName(stripBrackets(name));
+ result = new OJClass(component);
+ OJSystem.env.record(name, result);
+ return result;
+ }
+
+ result = lookupFromByteCode(nameToJavaClassName(name));
+ if (result != null) {
+ OJSystem.env.record(name, result);
+ return result;
+ }
+
+ throw new OJClassNotFoundException(name);
+ }
+
+ private static final OJClass lookupFromByteCode(String name) {
+ OJClass result = null;
+ try {
+ Class javaClass = Class.forName(name);
+ result = forClass(javaClass);
+ if (result != null) {
+ OJSystem.env.record(name, result);
+ return result;
+ }
+ } catch (ClassNotFoundException e) {
+ int dot = name.lastIndexOf('.');
+ if (dot == -1)
+ return null;
+ String innername = replaceDotWithDoller(name, dot);
+ result = lookupFromByteCode(innername);
+ }
+ return result;
+ }
+
+ private static final String replaceDotWithDoller(String base, int i) {
+ return base.substring(0, i) + '$' + base.substring(i + 1);
+ }
+
+ private static final boolean isArrayName(String name) {
+ return (name.startsWith("[") || name.endsWith("[]"));
+ }
+
+ private static final String stripBrackets(String ojcname) {
+ return ojcname.substring(0, ojcname.length() - 2);
+ }
+
+ private static final String nameForJavaClassName(String jcname) {
+ return Toolbox.nameForJavaClassName(jcname);
+ }
+
+ private static final String nameToJavaClassName(String ojcname) {
+ return Toolbox.nameToJavaClassName(ojcname);
+ }
+
+ static OJClass[] arrayForClasses(Class[] jclasses) {
+ OJClass[] result = new OJClass[jclasses.length];
+ for (int i = 0; i < result.length; ++i) {
+ result[i] = forClass(jclasses[i]);
+ }
+ return result;
+ }
+
+ static Class[] toClasses(OJClass[] classes) {
+ Class[] result = new Class[classes.length];
+ for (int i = 0; i < result.length; ++i) {
+ result[i] = classes[i].getCompatibleJavaClass();
+ }
+ return result;
+ }
+
+ /**
+ * Converts a <code>OJClass</code> object to an <code>OJClass</code>
+ * object.
+ * <p>
+ * This method returns the same <code>OJClass</code> object
+ * whenever it is invoked for the same <code>Class</code>object.
+ * It gurantees one-to-one correspondence between <code>Class</code>
+ * and <code>OJClass</code>.
+ *
+ * @param javaClass Java Class to translate into OJClass
+ * @return OJClass of given Java class
+ */
+ public static OJClass forClass(Class javaClass) {
+ if (javaClass == null)
+ return null;
+
+ String name = nameForJavaClassName(javaClass.getName());
+
+ OJClass result = OJSystem.env.lookupClass(name);
+ if (result != null)
+ return result;
+
+ if (isArrayName(name)) {
+ try {
+ OJClass component = forName(stripBrackets(name));
+ result = new OJClass(component);
+ OJSystem.env.record(name, result);
+ return result;
+ } catch (Exception e) {
+ System.err.println("OJClass.forClass(" + name + ") : " + e);
+ /* continue as a non array */
+ }
+ }
+
+ result = lookupFromMetaInfo(javaClass);
+ OJSystem.env.record(name, result);
+
+ return result;
+ }
+
+ private static final OJClass lookupFromMetaInfo(Class javaClass) {
+ MetaInfo metainfo = new MetaInfo(javaClass);
+ String mcname = metainfo.get("instantiates");
+ DebugOut.println(javaClass + " is an instance of " + mcname);
+ try {
+ Class metaclazz = Class.forName(mcname);
+ Class[] paramtypes = new Class[] { Class.class, MetaInfo.class };
+ Constructor constr = metaclazz.getConstructor(paramtypes);
+ Object[] args = new Object[] { javaClass, metainfo };
+ return (OJClass) constr.newInstance(args);
+ } catch (ClassNotFoundException e) {
+ System.err.println(
+ "metaclass "
+ + mcname
+ + " for "
+ + javaClass
+ + " not found."
+ + " substituted by default metaclass.");
+ metainfo = new MetaInfo(javaClass.getName());
+ return new OJClass(javaClass, metainfo);
+ } catch (Exception e) {
+ System.err.println(
+ "metaclass "
+ + mcname
+ + " doesn't provide"
+ + " proper constructor for bytecode."
+ + " substituted by default metaclass. : "
+ + e);
+ metainfo = new MetaInfo(javaClass.getName());
+ return new OJClass(javaClass, metainfo);
+ }
+ }
+
+ /**
+ * Converts <code>ParseTree</code> objects to an <code>OJClass</code>
+ * object. The generated <code>OJClass</code> object is to be
+ * registered as globally asscessible class but not to appear as
+ * generated source code.
+ * <p>
+ *
+ * @param env Environment object
+ * @param declaringClass OJClass
+ * @param ptree Parse Tree for declaringClass
+ * @return OJClass
+ * @throws AmbiguousClassesException If there is already an
+ * OJClass, throws AmbiguousClassesException
+ * @throws ClassNotFoundException If not class is found
+ */
+ public static OJClass forParseTree(
+ Environment env,
+ OJClass declaringClass,
+ ClassDeclaration ptree)
+ throws AmbiguousClassesException, ClassNotFoundException {
+ String qname;
+ if (declaringClass == null) {
+ qname = env.toQualifiedName(ptree.getName());
+ } else {
+ qname = env.currentClassName() + "." + ptree.getName();
+ }
+
+ Class metaclazz = null;
+ if (ptree.getMetaclass() != null) {
+ String mcname = env.toQualifiedName(ptree.getMetaclass());
+ metaclazz = Class.forName(mcname);
+ } else {
+ metaclazz = OJSystem.getMetabind(qname);
+ }
+
+ OJClass result;
+ try {
+ Constructor constr =
+ metaclazz.getConstructor(
+ new Class[] {
+ Environment.class,
+ OJClass.class,
+ ClassDeclaration.class });
+ Object[] args = new Object[] { env, declaringClass, ptree };
+ result = (OJClass) constr.newInstance(args);
+ } catch (NoSuchMethodException ex) {
+ System.err.println(
+ "errors during gererating a metaobject for "
+ + ptree.getName()
+ + " : "
+ + ex);
+ result = new OJClass(env, declaringClass, ptree);
+ } catch (InvocationTargetException ex) {
+ System.err.println(
+ "errors during gererating a metaobject for "
+ + ptree.getName()
+ + " : "
+ + ex.getTargetException());
+ ex.printStackTrace();
+ result = new OJClass(env, declaringClass, ptree);
+ } catch (Exception ex) {
+ System.err.println(
+ "errors during gererating a metaobject for "
+ + ptree.getName()
+ + " : "
+ + ex);
+ result = new OJClass(env, declaringClass, ptree);
+ }
+
+ OJClass existing = OJSystem.env.lookupClass(qname);
+
+ if (existing != null) {
+ throw new AmbiguousClassesException(qname);
+ }
+
+ OJSystem.env.record(qname, result);
+ return result;
+ }
+
+ /**
+ * Generates a expression parse tree from a given
+ * <code>String</code> object under the given environment.
+ *
+ * @param env an environment for the source code.
+ * @param str a fragment of source code representing an expression.
+ * @return an expression parse tree
+ * @throws MOPException Introspection cannot be performed
+ */
+ protected static final Expression makeExpression(
+ Environment env,
+ String str)
+ throws MOPException {
+ return PartialParser.makeExpression(env, str);
+ }
+
+ /**
+ * Generates an expression parse tree from a given
+ * <code>String</code> object under the environment of
+ * this class object.
+ *
+ * @param str a fragment of source code representing an expression.
+ * @return an expression parse tree
+ * @throws MOPException Introspection cannot be performed
+ */
+ protected final Expression makeExpression(String str) throws MOPException {
+ return makeExpression(getEnvironment(), str);
+ }
+
+ /**
+ * Generates a statement parse tree from a given
+ * <code>String</code> object under the given environment.
+ *
+ * @param env an environment for the source code.
+ * @param str a fragment of source code representing a statement.
+ * @return a statement parse tree
+ * @throws MOPException Introspection cannot be performed
+ */
+ protected static final Statement makeStatement(Environment env, String str)
+ throws MOPException {
+ return PartialParser.makeStatement(env, str);
+ }
+
+ /**
+ * Generates a statement parse tree from a given
+ * <code>String</code> object under the environment of
+ * this class object.
+ *
+ * @param str a fragment of source code representing a statement.
+ * @return a statement parse tree
+ * @throws MOPException Introspection cannot be performed
+ */
+ protected final Statement makeStatement(String str) throws MOPException {
+ return makeStatement(getEnvironment(), str);
+ }
+
+ /**
+ * Generates a statement list parse tree from a given
+ * <code>String</code> object under the given environment.
+ *
+ * @param env an environment for the source code.
+ * @param str a fragment of source code representing a statement list.
+ * @return a statement list parse tree
+ * @throws MOPException Introspection cannot be performed
+ */
+ protected static final StatementList makeStatementList(
+ Environment env,
+ String str)
+ throws MOPException {
+ return PartialParser.makeStatementList(env, str);
+ }
+
+ /**
+ * Generates a statement list parse tree from a given
+ * <code>String</code> object under the environment of
+ * this class object.
+ *
+ * @param str a fragment of source code representing a statement list.
+ * @return a statement list parse tree
+ * @throws MOPException Introspection cannot be performed
+ */
+ protected final StatementList makeStatementList(String str)
+ throws MOPException {
+ return makeStatementList(getEnvironment(), str);
+ }
+
+ /**
+ * Converts the object to a string. The string representation is
+ * the string "class" or "interface", followed by a space, and then
+ * by the fully qualified name of the class in the format returned
+ * by <code>getName</code>. If this <code>OJClass</code> object
+ * represents a primitive type, this method returns the name of the
+ * primitive type. If this <code>OJClass</code> object represents
+ * void this method returns "void".
+ *
+ * @return a string representation of this class object.
+ */
+ public String toString() {
+ return substance.toString();
+ }
+
+ /**
+ * Obtains an environment of this class object.
+ * This environment has information about members and outr
+ * environments such as packages but not local information like
+ * local variable in methods of this class.
+ *
+ * @return an environment of this class object.
+ */
+ public Environment getEnvironment() {
+ return substance.getEnvironment();
+ }
+
+ /**
+ * Determines if the class or interface represented by this
+ * <code>OJClass</code> object is either the same as, or is a
+ * superclass or superinterface of, the class or interface
+ * represented by the specified <code>OJClass</code> parameter. It
+ * returns <code>true</code> if so; otherwise it returns
+ * <code>false</code>. If this <code>OJClass</code> object
+ * represents a primitive type, this method returns
+ * <code>true</code> if the type represented by this
+ * <code>OJClass</code> object can accept the type represented by
+ * the specified <code>OJClass</code> parameter; otherwise it
+ * returns <code>false</code>.
+ *
+ * <p> Specifically, this method tests whether the type
+ * represented by the specified <code>OJClass</code> parameter can
+ * be converted to the type represented by this
+ * <code>OJClass</code> object via an identity conversion or via a
+ * widening reference/primitive conversion. <p> The behavior
+ * about primitive types is different from the method of the same
+ * name of <code>java.lang.Class</code>.
+ *
+ * @param clazz Class to test
+ * @exception NullPointerException if the specified class
+ * parameter is null.
+ * @return Result of test
+ */
+ public boolean isAssignableFrom(OJClass clazz) {
+ if (clazz.toString() == OJSystem.NULLTYPE_NAME)
+ return true;
+ if (clazz == this) {
+ /* if it is exactly the same type */
+ return true;
+ }
+ if (this.isPrimitive()) {
+ /* the java.lang.Class's returns always false */
+ if (!clazz.isPrimitive())
+ return false;
+ if (clazz == OJSystem.CHAR) {
+ return (
+ primitiveTypeWidth(this)
+ > primitiveTypeWidth(OJSystem.SHORT));
+ }
+ if (primitiveTypeWidth(this) > primitiveTypeWidth(OJSystem.VOID)) {
+ return (primitiveTypeWidth(this) > primitiveTypeWidth(clazz));
+ }
+ return false;
+ } else {
+ if (clazz.isPrimitive())
+ return false;
+ }
+ /* now class is a reference type */
+ if (this == OJSystem.OBJECT)
+ return true;
+ if (this.isArray()) {
+ if (!clazz.isArray())
+ return false;
+ OJClass comp = this.getComponentType();
+ return comp.isAssignableFrom(clazz.getComponentType());
+ } else {
+ if (clazz.isArray())
+ return false;
+ }
+ /* getInterfaces() returns only the declared intefaces
+ * So the interfaces of the superclasses should be checked.
+ */
+ if (this.isInterface()) {
+ /* for an assigning class which is either interface or class */
+ OJClass[] faces = clazz.getInterfaces();
+ for (int i = 0; i < faces.length; ++i) {
+ if (isAssignableFrom(faces[i]))
+ return true;
+ }
+ }
+ /* now this is a class */
+ if (clazz.isInterface())
+ return false;
+ OJClass base = clazz.getSuperclass();
+ return (base == null) ? false : isAssignableFrom(base);
+ }
+
+ private static int primitiveTypeWidth(OJClass ptype) {
+ if (ptype == OJSystem.BYTE)
+ return 1;
+ if (ptype == OJSystem.SHORT)
+ return 2;
+ if (ptype == OJSystem.INT)
+ return 3;
+ if (ptype == OJSystem.LONG)
+ return 4;
+ if (ptype == OJSystem.FLOAT)
+ return 5;
+ if (ptype == OJSystem.DOUBLE)
+ return 5;
+ return -1;
+ }
+
+ /**
+ * Determines if the specified <code>OJClass</code> object represents
+ * an interface type.
+ *
+ * @return <code>true</code> if this object represents an interface;
+ * <code>false</code> otherwise.
+ */
+ public boolean isInterface() {
+ return substance.isInterface();
+ }
+
+ /**
+ * Determines if this <code>OJClass</code> object represents an
+ * array class.
+ *
+ * @return <code>true</code> if this object represents an array class;
+ * <code>false</code> otherwise.
+ */
+ public boolean isArray() {
+ return substance.isArray();
+ }
+
+ /**
+ * Determines if the specified <code>OJClass</code> object represents a
+ * primitive type.
+ *
+ * <p> There are nine predefined <code>OJClass</code> objects to represent
+ * the eight primitive types and void. These are created by the Java
+ * Virtual Machine, and have the same names as the primitive types that
+ * they represent, namely <code>boolean</code>, <code>byte</code>,
+ * <code>char</code>, <code>short</code>, <code>int</code>,
+ * <code>long</code>, <code>float</code>, and <code>double</code>.
+ *
+ * <p> These objects may be accessed via the following public static
+ * final variables, and are the only <code>OJClass</code> objects for
+ * which this method returns <code>true</code>.
+ *
+ * @see io.devnulllabs.openjava.mop.OJSystem#BOOLEAN
+ * @see io.devnulllabs.openjava.mop.OJSystem#CHAR
+ * @see io.devnulllabs.openjava.mop.OJSystem#BYTE
+ * @see io.devnulllabs.openjava.mop.OJSystem#SHORT
+ * @see io.devnulllabs.openjava.mop.OJSystem#INT
+ * @see io.devnulllabs.openjava.mop.OJSystem#LONG
+ * @see io.devnulllabs.openjava.mop.OJSystem#FLOAT
+ * @see io.devnulllabs.openjava.mop.OJSystem#DOUBLE
+ * @see io.devnulllabs.openjava.mop.OJSystem#VOID
+ *
+ * @return <code>true</code> if this object represents a primitive type;
+ * <code>false</code> otherwise.
+ */
+ public boolean isPrimitive() {
+ return substance.isPrimitive();
+ }
+
+ /**
+ * Determines if the specified <code>OJClass</code> object represents a
+ * wrapper class for a primitive type.
+ *
+ * @return <code>true</code> if this object represents a wrapper class
+ * for a primitive type; <code>false</code> otherwise.
+ */
+ public boolean isPrimitiveWrapper() {
+ return (this != unwrappedPrimitive());
+ }
+
+ /**
+ * Obtains the wrapper class if this class represents a primitive
+ * type.
+ * <p>
+ * For example this method returns java.lang.Integer for int.
+ *
+ * @return The wrapper class for this primitive type.
+ * <code>null</code> for void.
+ */
+ public OJClass primitiveWrapper() {
+ if (this == OJSystem.VOID)
+ return null;
+ if (this == OJSystem.BOOLEAN)
+ return OJClass.forClass(java.lang.Boolean.class);
+ if (this == OJSystem.BYTE)
+ return OJClass.forClass(java.lang.Byte.class);
+ if (this == OJSystem.CHAR)
+ return OJClass.forClass(java.lang.Character.class);
+ if (this == OJSystem.SHORT)
+ return OJClass.forClass(java.lang.Short.class);
+ if (this == OJSystem.INT)
+ return OJClass.forClass(java.lang.Integer.class);
+ if (this == OJSystem.LONG)
+ return OJClass.forClass(java.lang.Long.class);
+ if (this == OJSystem.FLOAT)
+ return OJClass.forClass(java.lang.Float.class);
+ if (this == OJSystem.DOUBLE)
+ return OJClass.forClass(java.lang.Double.class);
+ //otherwise returns as is
+ return this;
+ }
+
+ /**
+ * Obtains the real type class if this class represents a primitive
+ * wrapper type.
+ * <p>
+ * For example this method returns int for java.lang.Integer.
+ *
+ * @return The real primitive type for this primitive wrapper class.
+ */
+ public OJClass unwrappedPrimitive() {
+ if (this == OJClass.forClass(java.lang.Boolean.class))
+ return OJSystem.BOOLEAN;
+ if (this == OJClass.forClass(java.lang.Byte.class))
+ return OJSystem.BYTE;
+ if (this == OJClass.forClass(java.lang.Character.class))
+ return OJSystem.CHAR;
+ if (this == OJClass.forClass(java.lang.Short.class))
+ return OJSystem.SHORT;
+ if (this == OJClass.forClass(java.lang.Integer.class))
+ return OJSystem.INT;
+ if (this == OJClass.forClass(java.lang.Long.class))
+ return OJSystem.LONG;
+ if (this == OJClass.forClass(java.lang.Float.class))
+ return OJSystem.FLOAT;
+ if (this == OJClass.forClass(java.lang.Double.class))
+ return OJSystem.DOUBLE;
+ //otherwise returns as is
+ return this;
+ }
+
+ /**
+ * Returns the fully-qualified name of the entity (class,
+ * interface, array class, primitive type, or void) represented by
+ * this <code>OJClass</code> object, as a <code>String</code>.
+ *
+ * <p> If this <code>OJClass</code> object represents a class of
+ * arrays, then the internal form of the name consists of the name
+ * of the element type in Java signature format, followed by one
+ * or more "<tt>[]</tt>" characters representing the depth of array
+ * nesting. This representation differs from that of
+ * <code>java.lang.Class.forName()</code>. Thus:
+ *
+ * <blockquote><pre>
+ * OJClass.forClass( (new int[3][4]).getClass() ).getName()
+ * </pre></blockquote>
+ *
+ * returns "<code>java.lang.Object[]</code>" and:
+ *
+ * <blockquote><pre>
+ * OJClass.forClass( (new int[3][4]).getClass() ).getName()
+ * </pre></blockquote>
+ *
+ * returns "<code>int[][]</code>".
+ *
+ * <p> The class or interface name <tt><i>classname</i></tt> is
+ * given in fully qualified form as shown in the example above.
+ *
+ * @return the fully qualified name of the class or interface
+ * represented by this object.
+ */
+ public String getName() {
+ return substance.getName();
+ }
+
+ /**
+ * Returns the simple name of the class, interface or array class
+ * represented by this <code>OJClass</code> object, as a
+ * <code>String</code>. Thus:
+ *
+ * <blockquote><pre>
+ * OJClass.forClass( (new Object[3]).getClass() ).getName()
+ * </pre></blockquote>
+ *
+ * returns "<code>Object</code>".
+ *
+ * @return the simple name of the class or interface
+ * represented by this object.
+ */
+ public String getSimpleName() {
+ return Environment.toSimpleName(getName());
+ }
+
+ /**
+ * Gets the package name for this class as a <code>String</code>.
+ * Null is returned if its package was not specified in source code of
+ * this class.
+ *
+ * @return the package name of the class, or null if its package
+ * was not specified in source code.
+ */
+ public String getPackage() {
+ int last = getName().lastIndexOf('.');
+ if (last == -1)
+ return null;
+ return getName().substring(0, last);
+ }
+
+ /**
+ * Determines if the specified class object is in the same package
+ * as this class object.
+ *
+ * <p>If null is given, this method returns alway false.
+ *
+ * @param c the class object to test against this class object.
+ * @return true in case that both class is is the sample package.
+ */
+ public boolean isInSamePackage(OJClass c) {
+ if (c == null)
+ return false;
+ String pack = c.getPackage();
+ if (pack == null)
+ return (getPackage() == null);
+ return pack.equals(getPackage());
+ }
+
+ /**
+ * Returns the <code>OJClass</code> representing the superclass of
+ * the entity (class, interface, primitive type or void)
+ * represented by this <code>OJClass</code>. If this
+ * <code>OJClass</code> represents either the
+ * <code>java.lang.Object</code> class, an interface, a primitive
+ * type, or void, then null is returned. If this object
+ * represents an array class then the <code>OJClass</code> object
+ * representing the <code>java.lang.Object</code> class is
+ * returned.
+ *
+ * @return the superclass of the class represented by this object.
+ */
+ public OJClass getSuperclass() {
+ return substance.getSuperclass();
+ }
+
+ /**
+ * Determines the interfaces implemented by the class or interface
+ * represented by this object.
+ *
+ * <p> If this object represents a class, the return value is an array
+ * containing objects representing all interfaces implemented by the
+ * class. The order of the interface objects in the array corresponds to
+ * the order of the interface names in the <code>implements</code> clause
+ * of the declaration of the class represented by this object. For
+ * example, given the declaration:
+ * <blockquote><pre>
+ * class Shimmer implements FloorWax, DessertTopping { ... }
+ * </pre></blockquote>
+ * suppose the value of <code>clazz</code> is an class object for
+ * the class <code>Shimmer</code>; the value of the expression:
+ * <blockquote><pre>
+ * clazz.getInterfaces()[0]
+ * </pre></blockquote>
+ * is the <code>OJClass</code> object that represents interface
+ * <code>FloorWax</code>; and the value of:
+ * <blockquote><pre>
+ * clazz.getInterfaces()[1]
+ * </pre></blockquote>
+ * is the <code>OJClass</code> object that represents interface
+ * <code>DessertTopping</code>.
+ *
+ * <p> If this object represents an interface, the array contains
+ * objects representing all interfaces extended by the
+ * interface. The order of the interface objects in the array
+ * corresponds to the order of the interface names in the
+ * <code>extends</code> clause of the declaration of the interface
+ * represented by this object.</p>
+ *
+ * <p> If this object represents a class or interface that
+ * implements no interfaces, the method returns an array of length
+ * 0.</p>
+ *
+ * <p> If this object represents a primitive type or void, the
+ * method returns an array of length 0.</p>
+ *
+ * To be <code>getDeclaredInterfaces()<code>.
+ *
+ * @return an array of interfaces implemented by this class object.
+ */
+ public OJClass[] getInterfaces() {
+ return substance.getInterfaces();
+ }
+
+ /**
+ * Returns the <code>OJClass</code> representing the component type of an
+ * array. If this class does not represent an array class this method
+ * returns null.
+ *
+ * @return the class object representing the type of component of this
+ * array.
+ */
+ public OJClass getComponentType() {
+ return substance.getComponentType();
+ }
+
+ /**
+ * Returns the Java language modifiers and the user defined modifiers
+ * for this class or interface, as a <code>OJModifier</code> object.
+ *
+ * <p> If the underlying class is an array class, then its
+ * <code>public</code>, <code>private</code> and <code>protected</code>
+ * modifiers are the same as those of its component type. If this
+ * <code>OJClass</code> represents a primitive type or void, its
+ * <code>public</code> modifier is always <code>true</code>, and its
+ * <code>protected</code> and <code>private</code> modifers are always
+ * <code>false</code>. If this object represents an array class, a
+ * primitive type or void, then its <code>final</code> modifier is always
+ * <code>true</code> and its interface modifer is always
+ * <code>false</code>. The values of its other modifiers are not determined
+ * by this specification.
+ *
+ * @see io.devnulllabs.openjava.mop.OJModifier
+ *
+ * @return the OJModifier object representing the modifiers of this class
+ * object
+ */
+ public OJModifier getModifiers() {
+ return substance.getModifiers();
+ }
+
+ /**
+ * Obtains an parse tree of suffix in extended syntax starting
+ * with the specified keyword. Returned
+ * <code>io.devnulllabs.openjava.ptree.ParseTree</code> object has a structure
+ * built by an <code>io.devnulllabs.openjava.syntax.SyntaxRule</code> object
+ * returned via the method <code>getDeclSuffixRule(String)</code>.
+ *
+ * @see io.devnulllabs.openjava.mop.OJClass#getDeclSuffixRule(String)
+ * @see io.devnulllabs.openjava.syntax.SyntaxRule
+ *
+ * @return the parse tree
+ */
+ public ParseTree getSuffix(String keyword) {
+ return substance.getSuffix(keyword);
+ }
+
+ /**
+ * If the class or interface represented by this
+ * <code>OJClass</code> object is a member of another class,
+ * returns the <code>OJClass</code> object representing the class
+ * in which it was declared. This method returns null if this
+ * class or interface is not a member of any other class. If this
+ * <code>OJClass</code> object represents an array class, a
+ * primitive type, or void, then this method returns null.
+ *
+ * @return the class object declaring this class object.
+ */
+ public OJClass getDeclaringClass() {
+ return substance.getDeclaringClass();
+ }
+
+ public final OJClass[] getAllClasses() {
+ return overridesOn(getDeclaredClasses(), getInheritedClasses());
+ }
+
+ public final OJField[] getAllFields() {
+ return overridesOn(getDeclaredFields(), getInheritedFields());
+ }
+
+ public final OJMethod[] getAllMethods() {
+ return overridesOn(getDeclaredMethods(), getInheritedMethods());
+ }
+
+ public OJClass[] getInheritedClasses() {
+ OJClass base = getSuperclass();
+ if (base == null) {
+ return new OJClass[0];
+ } else {
+ return base.getInheritableClasses(this);
+ }
+ }
+
+ public OJField[] getInheritedFields() {
+ OJClass base = getSuperclass();
+ OJField[] base_f;
+ if (base == null) {
+ base_f = new OJField[0];
+ } else {
+ base_f = base.getInheritableFields(this);
+ }
+ int len = base_f.length;
+ OJClass[] faces = getInterfaces();
+ OJField[][] face_fs = new OJField[faces.length][];
+ for (int i = 0; i < faces.length; ++i) {
+ face_fs[i] = faces[i].getInheritableFields(this);
+ len += face_fs[i].length;
+ }
+ OJField[] result = new OJField[len];
+ int count = 0;
+ for (int i = 0; i < faces.length; ++i) {
+ System.arraycopy(face_fs[i], 0, result, count, face_fs[i].length);
+ count += face_fs[i].length;
+ }
+ System.arraycopy(base_f, 0, result, count, base_f.length);
+ return result;
+ }
+
+ public final OJMethod[] getInheritedMethods() {
+ OJClass base = getSuperclass();
+ OJMethod[] base_m;
+ if (base == null) {
+ base_m = new OJMethod[0];
+ } else {
+ base_m = base.getInheritableMethods(this);
+ }
+ int len = base_m.length;
+ OJClass[] faces = getInterfaces();
+ OJMethod[][] face_ms = new OJMethod[faces.length][];
+ for (int i = 0; i < faces.length; ++i) {
+ face_ms[i] = faces[i].getInheritableMethods(this);
+ len += face_ms[i].length;
+ }
+ OJMethod[] result = new OJMethod[len];
+ int count = 0;
+ for (int i = 0; i < faces.length; ++i) {
+ System.arraycopy(face_ms[i], 0, result, count, face_ms[i].length);
+ count += face_ms[i].length;
+ }
+ System.arraycopy(base_m, 0, result, count, base_m.length);
+ return result;
+ }
+
+ /**
+ * Use <code>getInheritableClasses(OJClass)</code>
+ * @deprecated
+ * @see getInheritableClasses(OJClass)
+ */
+ public final OJClass[] getInheritableClasses() {
+ OJClass[] nonprivates = removeThePrivates(getAllClasses());
+ return removeTheDefaults(nonprivates);
+ }
+
+ /**
+ * Use <code>getInheritableFields(OJClass)</code>
+ * @deprecated
+ * @see getInheritableFields(OJClass)
+ */
+ public final OJField[] getInheritableFields() {
+ OJField[] nonprivates = removeThePrivates(getAllFields());
+ return removeTheDefaults(nonprivates);
+ }
+
+ /**
+ * Use <code>getInheritableMethods(OJClass)</code>
+ * @deprecated
+ * @see getInheritableMethodss(OJClass)
+ */
+ public final OJMethod[] getInheritableMethods() {
+ OJMethod[] nonprivates = removeThePrivates(getAllMethods());
+ return removeTheDefaults(nonprivates);
+ }
+
+ public OJClass[] getInheritableClasses(OJClass situation) {
+ OJClass[] result = removeThePrivates(getAllClasses());
+ if (isInSamePackage(situation))
+ return result;
+ return removeTheDefaults(result);
+ }
+
+ public OJField[] getInheritableFields(OJClass situation) {
+ OJField[] result = removeThePrivates(getAllFields());
+ if (isInSamePackage(situation))
+ return result;
+ return removeTheDefaults(result);
+ }
+
+ public OJMethod[] getInheritableMethods(OJClass situation) {
+ OJMethod[] result = removeThePrivates(getAllMethods());
+ if (isInSamePackage(situation))
+ return result;
+ return removeTheDefaults(result);
+ }
+
+ public OJConstructor[] getInheritableConstructors(OJClass situation) {
+ OJConstructor[] result = removeThePrivates(getDeclaredConstructors());
+ if (isInSamePackage(situation))
+ return result;
+ return removeTheDefaults(result);
+ }
+
+ private static final OJClass[] overridesOn(
+ OJClass[] declareds,
+ OJClass[] bases) {
+ return Toolbox.overridesOn(declareds, bases);
+ }
+
+ private static final OJField[] overridesOn(
+ OJField[] declareds,
+ OJField[] bases) {
+ return Toolbox.overridesOn(declareds, bases);
+ }
+
+ private static final OJMethod[] overridesOn(
+ OJMethod[] declareds,
+ OJMethod[] bases) {
+ return Toolbox.overridesOn(declareds, bases);
+ }
+
+ private static final OJClass[] removeThePrivates(OJClass[] src_classes) {
+ return Toolbox.removeThePrivates(src_classes);
+ }
+
+ private static final OJField[] removeThePrivates(OJField[] src_fields) {
+ return Toolbox.removeThePrivates(src_fields);
+ }
+
+ private static final OJMethod[] removeThePrivates(OJMethod[] src_methods) {
+ return Toolbox.removeThePrivates(src_methods);
+ }
+
+ private static final OJConstructor[] removeThePrivates(OJConstructor[] src_constrs) {
+ return Toolbox.removeThePrivates(src_constrs);
+ }
+
+ private static final OJClass[] removeTheDefaults(OJClass[] src_classes) {
+ return Toolbox.removeTheDefaults(src_classes);
+ }
+
+ private static final OJField[] removeTheDefaults(OJField[] src_fields) {
+ return Toolbox.removeTheDefaults(src_fields);
+ }
+
+ private static final OJMethod[] removeTheDefaults(OJMethod[] src_methods) {
+ return Toolbox.removeTheDefaults(src_methods);
+ }
+
+ private static final OJConstructor[] removeTheDefaults(OJConstructor[] src_constrs) {
+ return Toolbox.removeTheDefaults(src_constrs);
+ }
+
+ private static final OJClass[] removeTheNonPublics(OJClass[] src_classes) {
+ return Toolbox.removeTheNonPublics(src_classes);
+ }
+
+ private static final OJField[] removeTheNonPublics(OJField[] src_fields) {
+ return Toolbox.removeTheNonPublics(src_fields);
+ }
+
+ private static final OJMethod[] removeTheNonPublics(OJMethod[] src_methods) {
+ return Toolbox.removeTheNonPublics(src_methods);
+ }
+
+ private static final OJConstructor[] removeTheNonPublics(OJConstructor[] src_constrs) {
+ return Toolbox.removeTheNonPublics(src_constrs);
+ }
+
+ private static final OJMethod[] pickupMethodsByName(
+ OJMethod[] src_methods,
+ String name) {
+ return Toolbox.pickupMethodsByName(src_methods, name);
+ }
+
+ private static final OJField pickupField(
+ OJField[] src_fields,
+ String name) {
+ return Toolbox.pickupField(src_fields, name);
+ }
+
+ private static final OJMethod pickupMethod(
+ OJMethod[] src_methods,
+ String name,
+ OJClass[] parameterTypes) {
+ return Toolbox.pickupMethod(src_methods, name, parameterTypes);
+ }
+
+ private static final OJConstructor pickupConstructor(
+ OJConstructor[] src_constrs,
+ OJClass[] parameterTypes) {
+ return Toolbox.pickupConstructor(src_constrs, parameterTypes);
+ }
+
+ private static final OJMethod pickupAcceptableMethod(
+ OJMethod[] src_methods,
+ String name,
+ OJClass[] parameterTypes) {
+ return Toolbox.pickupAcceptableMethod(
+ src_methods,
+ name,
+ parameterTypes);
+ }
+
+ private static final OJConstructor pickupAcceptableConstructor(
+ OJConstructor[] src_constrs,
+ OJClass[] parameterTypes) {
+ return Toolbox.pickupAcceptableConstructor(src_constrs, parameterTypes);
+ }
+
+ /**
+ * Returns an array containing <code>OJClass</code> objects
+ * representing all the <em>public</em> classes and interfaces
+ * that are members of the class represented by this
+ * <code>OJClass</code> object. This includes public class and
+ * interface members inherited from superclasses and public class
+ * and interface members declared by the class. This method
+ * returns an array of length 0 if this <code>OJClass</code>
+ * object has no public member classes or interfaces. This method
+ * also returns an array of length 0 if this <code>OJClass</code>
+ * object represents a primitive type, an array class, or void.
+ *
+ */
+ public OJClass[] getClasses() {
+ return removeTheNonPublics(getAllClasses());
+ }
+
+ /**
+ * Returns an array containing <code>OJField</code> objects
+ * reflecting all the accessible <em>public</em> fields of the
+ * class or interface represented by this <code>OJClass</code>
+ * object. The elements in the array returned are not sorted and
+ * are not in any particular order. This method returns an array
+ * of length 0 if the class or interface has no accessible public
+ * fields, or if it represents an array class, a primitive type,
+ * or void.
+ *
+ * <p> Specifically, if this <code>OJClass</code> object
+ * represents a class, this method returns the public fields of
+ * this class and of all its superclasses. If this
+ * <code>OJClass</code> object represents an interface, this
+ * method returns the fields of this interface and of all its
+ * superinterfaces.
+ *
+ * <p> The implicit length field for array classs is reflected by this
+ * method.
+ *
+ * @see io.devnulllabs.openjava.mop.OJField
+ */
+ public OJField[] getFields() {
+ return removeTheNonPublics(getAllFields());
+ }
+
+ /**
+ * Returns an array containing <code>OJMethod</code> objects
+ * reflecting all the <em>public</em> member methods of the class
+ * or interface represented by this <code>OJClass</code> object,
+ * including those declared by the class or interface and and
+ * those inherited from superclasses and superinterfaces. The
+ * elements in the array returned are not sorted and are not in
+ * any particular order. This method returns an array of length 0
+ * if this <code>OJClass</code> object represents a class or
+ * interface that has no public member methods, or if this
+ * <code>OJClass</code> object represents an array class, primitive
+ * type, or void.
+ *
+ * @see io.devnulllabs.openjava.mop.OJMethod
+ */
+ public OJMethod[] getMethods() {
+ return removeTheNonPublics(getAllMethods());
+ }
+
+ /**
+ * Returns an array containing <code>OJConstructor</code> objects
+ * reflecting all the <em>public</em> constructors of the class
+ * represented by this <code>OJClass</code> object. An array of
+ * length 0 is returned if the class has no public constructors,
+ * or if the class is an array class, or if the class reflects a
+ * primitive type or void.
+ *
+ * @see io.devnulllabs.openjava.mop.OJConstructor
+ */
+ public OJConstructor[] getConstructors() {
+ return removeTheNonPublics(getDeclaredConstructors());
+ }
+
+ /**
+ * Returns a <code>OJField</code> object that reflects the
+ * specified <em>public</em> member field of the class or
+ * interface represented by this <code>OJClass</code> object. The
+ * <code>name</code> parameter is a <code>String</code> specifying
+ * the simple name of the desired field.
+ *
+ * @exception NoSuchMemberException if a field with the specified name is
+ * not found.
+ * @see io.devnulllabs.openjava.mop.OJField
+ */
+ public OJField getField(String name) throws NoSuchMemberException {
+ OJField field = pickupField(getFields(), name);
+ if (field != null)
+ return field;
+ throw new NoSuchMemberException(name);
+ }
+
+ /**
+ * Returns a <code>OJMethod</code> object that reflects the
+ * specified public member method of the class or interface
+ * represented by this <code>OJClass</code> object. The
+ * <code>name</code> parameter is a <code>String</code> specifying
+ * the simple name the desired method. The
+ * <code>parameterTypes</code> parameter is an array of
+ * <code>OJClass</code> objects that identify the method's formal
+ * parameter types, in declared order. If
+ * <code>parameterTypes</code> is <code>null</code>, it is treated
+ * as if it were an empty array.
+ *
+ * @exception NoSuchMemberException if a matching method is not found
+ * or if then name is "&lt;init>"or "&lt;clinit>".
+ * @see io.devnulllabs.openjava.mop.OJMethod
+ */
+ public OJMethod getMethod(String name, OJClass[] parameterTypes)
+ throws NoSuchMemberException {
+ OJMethod method = pickupMethod(getMethods(), name, parameterTypes);
+ if (method != null)
+ return method;
+ Signature sign = new Signature(name, parameterTypes);
+ throw new NoSuchMemberException(sign.toString());
+ }
+
+ /**
+ * Returns a <code>OJConstructor</code> object that reflects the
+ * specified public constructor of the class represented by this
+ * <code>OJClass</code> object. The <code>parameterTypes</code>
+ * parameter is an array of <code>OJClass</code> objects that
+ * identify the constructor's formal parameter types, in declared
+ * order.
+ *
+ * <p> The constructor to reflect is the public constructor of the
+ * class represented by this <code>OJClass</code> object whose
+ * formal parameter types match those specified by
+ * <code>parameterTypes</code>.
+ *
+ * @exception NoSuchMemberException if a matching method is not found.
+ * @see io.devnulllabs.openjava.mop.OJConstructor
+ */
+ public OJConstructor getConstructor(OJClass[] parameterTypes)
+ throws NoSuchMemberException {
+ OJConstructor constr =
+ pickupConstructor(getConstructors(), parameterTypes);
+ if (constr != null)
+ return constr;
+ Signature sign = new Signature(parameterTypes);
+ throw new NoSuchMemberException(sign.toString());
+ }
+
+ /**
+ * Returns an array containing <code>OJClass</code> objects
+ * representing all the classes and interfaces which are members
+ * of the class represented by this <code>OJClass</code> object,
+ * accessible from the situation represented by the given
+ * <code>OJClass</code> object. This includes class and interface
+ * members inherited from superclasses and declared class and
+ * interface members accessible from the given situation. This
+ * method returns an array of length 0 if this
+ * <code>OJClass</code> object has no public member classes or
+ * interfaces. This method also returns an array of length 0 if
+ * this <code>OJClass</code> object represents a primitive type,
+ * an array class, or void.
+ *
+ * <p>The accessiblity depends on the package of the class,
+ * modifiers of each members, and the package of the situation.
+ *
+ */
+ public final OJClass[] getClasses(OJClass situation) {
+ if (this == situation)
+ return getAllClasses();
+ if (isInSamePackage(situation)) {
+ return removeThePrivates(getAllClasses());
+ } else if (this.isAssignableFrom(situation)) {
+ return getInheritableClasses(situation);
+ }
+ return removeTheNonPublics(getAllClasses());
+ }
+
+ /**
+ * Returns an array containing <code>OJField</code> objects
+ * reflecting all the fields of the class or interface represented
+ * by this <code>OJClass</code> object, accessible from the
+ * situation represented by the given <code>OJClass</code> object.
+ * The elements in the array returned are not sorted and
+ * are not in any particular order. This method returns an array
+ * of length 0 if the class or interface has no accessible public
+ * fields, or if it represents an array class, a primitive type,
+ * or void.
+ *
+ * <p> Specifically, if this <code>OJClass</code> object
+ * represents a class, this method returns the public fields of
+ * this class and of all its superclasses. If this
+ * <code>OJClass</code> object represents an interface, this
+ * method returns the fields of this interface and of all its
+ * superinterfaces.
+ *
+ * <p>The accessiblity depends on the package of the class,
+ * modifiers of each members, and the package of the situation.
+ *
+ * <p> The implicit length field for array classs is reflected by this
+ * method.
+ *
+ * @see io.devnulllabs.openjava.mop.OJField
+ */
+ public final OJField[] getFields(OJClass situation) {
+ if (this == situation)
+ return getAllFields();
+ if (isInSamePackage(situation)) {
+ return removeThePrivates(getAllFields());
+ } else if (this.isAssignableFrom(situation)) {
+ return getInheritableFields(situation);
+ }
+ return removeTheNonPublics(getAllFields());
+ }
+
+ /**
+ * Returns an array containing <code>OJMethod</code> objects
+ * reflecting all the member methods of the class or interface
+ * represented by this <code>OJClass</code> object, accesible from
+ * the situation represented by the given <code>OJClass</code>
+ * object. Returned methods include those declared by the class
+ * or interface and and those inherited from superclasses and
+ * superinterfaces. The elements in the array returned are not
+ * sorted and are not in any particular order. This method
+ * returns an array of length 0 if this <code>OJClass</code>
+ * object represents a class or interface that has no public
+ * member methods, or if this <code>OJClass</code> object
+ * represents an array class, primitive type, or void.
+ *
+ * <p>The accessiblity depends on the package of the class,
+ * modifiers of each members, and the package of the situation.
+ *
+ * @see io.devnulllabs.openjava.mop.OJMethod
+ */
+ public final OJMethod[] getMethods(OJClass situation) {
+ if (this == situation)
+ return getAllMethods();
+ if (isInSamePackage(situation)) {
+ return removeThePrivates(getAllMethods());
+ } else if (this.isAssignableFrom(situation)) {
+ return getInheritableMethods(situation);
+ }
+ return removeTheNonPublics(getAllMethods());
+ }
+
+ /**
+ * Returns an array containing <code>OJConstructor</code> objects
+ * reflecting all the constructors of the class represented by
+ * this <code>OJClass</code> object, accesible from the situation
+ * represented by the given <code>OJClass</code> object. An array
+ * of length 0 is returned if the class has no public
+ * constructors, or if the class is an array class, or if the
+ * class reflects a primitive type or void.
+ *
+ * <p>The accessiblity depends on the package of the class,
+ * modifiers of each members, and the package of the situation.
+ *
+ * @see io.devnulllabs.openjava.mop.OJConstructor
+ */
+ public final OJConstructor[] getConstructors(OJClass situation) {
+ if (this == situation)
+ return getDeclaredConstructors();
+ if (isInSamePackage(situation)) {
+ return removeThePrivates(getDeclaredConstructors());
+ } else if (this.isAssignableFrom(situation)) {
+ return getInheritableConstructors(situation);
+ }
+ return removeTheNonPublics(getDeclaredConstructors());
+ }
+
+ /**
+ * Returns a <code>OJField</code> object that reflects the
+ * specified member field accesible from the situation represented
+ * by the given <code>OJClass</code> object. The
+ * <code>name</code> parameter is a <code>String</code> specifying
+ * the simple name of the desired field.
+ *
+ * @exception NoSuchMemberException if a field with the specified name is
+ * not found.
+ * @see io.devnulllabs.openjava.mop.OJField
+ */
+ public OJField getField(String name, OJClass situation)
+ throws NoSuchMemberException {
+ OJField field = pickupField(getFields(situation), name);
+ if (field != null)
+ return field;
+ throw new NoSuchMemberException(name);
+ }
+
+ /**
+ * Returns a <code>OJMethod</code> object that reflects the
+ * specified member method accesible from the situation
+ * represented by the given <code>OJClass</code> object. The
+ * <code>name</code> parameter is a <code>String</code> specifying
+ * the simple name the desired method. The
+ * <code>parameterTypes</code> parameter is an array of
+ * <code>OJClass</code> objects that identify the method's formal
+ * parameter types, in declared order. If
+ * <code>parameterTypes</code> is <code>null</code>, it is treated
+ * as if it were an empty array.
+ *
+ * @exception NoSuchMemberException if a matching method is not found.
+ * @see io.devnulllabs.openjava.mop.OJMethod
+ */
+ public OJMethod getMethod(
+ String name,
+ OJClass[] parameterTypes,
+ OJClass situation)
+ throws NoSuchMemberException {
+ OJMethod method =
+ pickupMethod(getMethods(situation), name, parameterTypes);
+ if (method != null)
+ return method;
+ Signature sign = new Signature(name, parameterTypes);
+ throw new NoSuchMemberException(sign.toString());
+ }
+
+ /**
+ * Returns a <code>OJConstructor</code> object that reflects the
+ * specified constructor accesible from the situation represented
+ * by the given <code>OJClass</code> object. The
+ * <code>parameterTypes</code> parameter is an array of
+ * <code>OJClass</code> objects that identify the constructor's
+ * formal parameter types, in declared order.
+ *
+ * <p> The constructor to reflect is the constructor of the
+ * class represented by this <code>OJClass</code> object whose
+ * formal parameter types match those specified by
+ * <code>parameterTypes</code>.
+ *
+ * @exception NoSuchMemberException if a matching method is not found.
+ * @see io.devnulllabs.openjava.mop.OJConstructor
+ */
+ public OJConstructor getConstructor(
+ OJClass[] parameterTypes,
+ OJClass situation)
+ throws NoSuchMemberException {
+ OJConstructor constr =
+ pickupConstructor(getConstructors(situation), parameterTypes);
+ if (constr != null)
+ return constr;
+ Signature sign = new Signature(parameterTypes);
+ throw new NoSuchMemberException(sign.toString());
+ }
+
+ /**
+ * Use <code>c.getField(name,c)</code>
+ * @deprecated
+ * @see getField(String,OJClass)
+ */
+ public final OJField getAllField(String name)
+ throws NoSuchMemberException {
+ OJField field = pickupField(getAllFields(), name);
+ if (field != null)
+ return field;
+ throw new NoSuchMemberException(name);
+ }
+
+ /**
+ * @deprecated
+ */
+ public final OJMethod[] getAllMethods(String name) {
+ return pickupMethodsByName(getAllMethods(), name);
+ }
+
+ /**
+ * Use <code>c.getMethod(name,ptypes,c)</code>
+ * @deprecated
+ * @see getMethod(String,OJClass[],OJClass)
+ */
+ public final OJMethod getAllMethod(String name, OJClass[] parameterTypes)
+ throws NoSuchMemberException {
+ OJMethod method = pickupMethod(getAllMethods(), name, parameterTypes);
+ if (method != null)
+ return method;
+ Signature sign = new Signature(name, parameterTypes);
+ throw new NoSuchMemberException(sign.toString());
+ }
+
+ /** Can be overriden */
+ public OJMethod getAcceptableMethod(
+ String name,
+ OJClass[] parameterTypes,
+ OJClass situation)
+ throws NoSuchMemberException {
+ OJMethod method =
+ pickupAcceptableMethod(getMethods(situation), name, parameterTypes);
+ if (method != null)
+ return method;
+ Signature sign = new Signature(name, parameterTypes);
+ throw new NoSuchMemberException(sign.toString());
+ }
+
+ /** Can be overriden */
+ public OJConstructor getAcceptableConstructor(
+ OJClass[] parameterTypes,
+ OJClass situation)
+ throws NoSuchMemberException {
+ OJConstructor constr =
+ pickupAcceptableConstructor(
+ getConstructors(situation),
+ parameterTypes);
+ if (constr != null)
+ return constr;
+ Signature sign = new Signature(parameterTypes);
+ throw new NoSuchMemberException(sign.toString());
+ }
+
+ /**
+ * Returns an array of <code>OJClass</code> objects reflecting all
+ * the classes and interfaces declared as members of the class
+ * represented by this <code>OJClass</code> object. This includes
+ * public, protected, default (package) access, and private
+ * classes and interfaces declared by the class, but excludes
+ * inherited classes and interfaces. This method returns an array
+ * of length 0 if the class declares no classes or interfaces as
+ * members, or if this <code>OJClass</code> object represents a
+ * primitive type, an array class, or void.
+ *
+ * <p>This method may be overriden to provide proper information
+ * in the extended language.
+ */
+ public OJClass[] getDeclaredClasses() {
+ return substance.getDeclaredClasses();
+ }
+
+ /**
+ * Returns an array of <code>OJField</code> objects reflecting all
+ * the fields declared by the class or interface represented by
+ * this <code>OJClass</code> object. This includes public,
+ * protected, default (package) access, and private fields, but
+ * excludes inherited fields. The elements in the array returned
+ * are not sorted and are not in any particular order. This
+ * method returns an array of length 0 if the class or interface
+ * declares no fields, or if this <code>OJClass</code> object
+ * represents a primitive type, an array class, or void.
+ *
+ * <p>This method may be overriden to provide proper information
+ * in the extended language.
+ *
+ * @see io.devnulllabs.openjava.mop.OJField
+ */
+ public OJField[] getDeclaredFields() {
+ return substance.getDeclaredFields();
+ }
+
+ /**
+ * Returns an array of <code>OJMethod</code> objects reflecting all
+ * the methods declared by the class or interface represented by
+ * this <code>OJClass</code> object. This includes public,
+ * protected, default (package) access, and private methods, but
+ * excludes inherited methods. The elements in the array returned
+ * are not sorted and are not in any particular order. This
+ * method returns an array of length 0 if the class or interface
+ * declares no methods, or if this <code>OJClass</code> object
+ * represents a primitive type, an array class, or void. The
+ * class initialization method <code>&lt;clinit&gt;</code> is not
+ * included in the returned array. If the class declares multiple
+ * public member methods with the same parameter types, they are
+ * all included in the returned array.
+ *
+ * <p>This method may be overriden to provide proper information
+ * in the extended language.
+ *
+ * @see io.devnulllabs.openjava.mop.OJMethod
+ */
+ public OJMethod[] getDeclaredMethods() {
+ return substance.getDeclaredMethods();
+ }
+
+ /**
+ * Returns an array of <code>OJConstructor</code> objects reflecting
+ * all the constructors declared by the class represented by this
+ * <code>OJClass</code> object. These are public, protected, default
+ * (package) access, and private constructors. The elements in
+ * the array returned are not sorted and are not in any particular
+ * order. If the class has a default constructor, it is included
+ * in the returned array. This method returns an array of length
+ * 0 if this <code>OJClass</code> object represents an interface, a
+ * primitive type, an array class, or void.
+ *
+ * <p>This method may be overriden to provide proper information
+ * in the extended language.
+ *
+ * @see io.devnulllabs.openjava.mop.OJConstructor
+ */
+ public OJConstructor[] getDeclaredConstructors() {
+ return substance.getDeclaredConstructors();
+ }
+
+ /**
+ * Returns a <code>OJField</code> object that reflects the specified
+ * declared field of the class or interface represented by this
+ * <code>OJClass</code> object. The <code>name</code> parameter is a
+ * <code>String</code> that specifies the simple name of the
+ * desired field. Note that this method will reflect the
+ * <code>length</code> field of an array class.
+ *
+ * @exception NoSuchMemberException if a field with the specified name is
+ * not found.
+ * @see io.devnulllabs.openjava.mop.OJField
+ */
+ public final OJField getDeclaredField(String name)
+ throws NoSuchMemberException {
+ OJField field = pickupField(getDeclaredFields(), name);
+ if (field != null)
+ return field;
+ throw new NoSuchMemberException(name);
+ }
+
+ /**
+ * Returns a <code>OJMethod</code> object that reflects the
+ * specified declared method of the class or interface represented
+ * by this <code>OJClass</code> object. The <code>name</code>
+ * parameter is a <code>String</code> that specifies the simple
+ * name of the desired method, and the <code>parameterTypes</code>
+ * parameter is an array of <code>OJClass</code> objects that
+ * identify the method's formal parameter types, in declared
+ * order. If more than one method with the same parameter types
+ * is declared in a class, and one of these methods has a return
+ * type that is more specific than any of the others, that method
+ * is returned; otherwise one of the methods is chosen
+ * arbitrarily.
+ *
+ * @exception NoSuchMemberException if a matching method is not found.
+ * @see io.devnulllabs.openjava.mop.OJMethod
+ */
+ public final OJMethod getDeclaredMethod(
+ String name,
+ OJClass[] parameterTypes)
+ throws NoSuchMemberException {
+ OJMethod method =
+ pickupMethod(getDeclaredMethods(), name, parameterTypes);
+ if (method != null)
+ return method;
+ Signature sign = new Signature(name, parameterTypes);
+ throw new NoSuchMemberException(sign.toString());
+ }
+
+ /**
+ * Returns a <code>OJConstructor</code> object that reflects the
+ * specified constructor of the class or interface represented by
+ * this <code>OJClass</code> object. The
+ * <code>parameterTypes</code> parameter is an array of
+ * <code>OJClass</code> objects that identify the constructor's
+ * formal parameter types, in declared order.
+ *
+ * @exception NoSuchMemberException if a matching method is not found.
+ * @see io.devnulllabs.openjava.mop.OJConstructor
+ */
+ public final OJConstructor getDeclaredConstructor(OJClass[] parameterTypes)
+ throws NoSuchMemberException {
+ OJConstructor constr =
+ pickupConstructor(getDeclaredConstructors(), parameterTypes);
+ if (constr != null)
+ return constr;
+ Signature sign = new Signature(parameterTypes);
+ throw new NoSuchMemberException(sign.toString());
+ }
+
+ /* -- the followings do not exist in regular Java -- */
+
+ /**
+ * Generate a copy of this class object with the specified name.
+ *
+ * @param qname a qualified name for the new copy.
+ */
+ public OJClass makeCopy(String qname) throws MOPException {
+ DebugOut.println(
+ "makeCopy() of " + getName() + " with a new name: " + qname);
+ try {
+ ClassDeclaration org = getSourceCode();
+ ClassDeclaration copy = (ClassDeclaration) org.makeRecursiveCopy();
+ String pack = Environment.toPackageName(qname);
+ String sname = Environment.toSimpleName(qname);
+ copy.setName(sname);
+ copy.accept(new TypeNameQualifier(getEnvironment(), sname));
+ FileEnvironment env =
+ new FileEnvironment(OJSystem.env, pack, sname);
+ return new OJClass(env, null, copy);
+ } catch (CannotAlterException ex1) {
+ return this;
+ } catch (ParseTreeException ex2) {
+ throw new MOPException(ex2);
+ }
+ }
+
+ public boolean isExecutable() {
+ return substance.isExecutable();
+ }
+
+ public boolean isAlterable() {
+ return substance.isAlterable();
+ }
+
+ public Class getByteCode() throws CannotExecuteException {
+ return substance.getByteCode();
+ }
+
+ public ClassDeclaration getSourceCode() throws CannotAlterException {
+ return substance.getSourceCode();
+ }
+
+ public Class getCompatibleJavaClass() {
+ return substance.getCompatibleJavaClass();
+ }
+
+ public Signature signature() {
+ return new Signature(this);
+ }
+
+ /* -- inner use only -- */
+
+ void setDeclaringClass(OJClass parent) throws CannotAlterException {
+ substance.setDeclaringClass(parent);
+ }
+
+ /**
+ * Waits a callee-side translation on another class metaobject
+ * to be done.
+ *
+ * @param clazz a class metaobject to wait
+ */
+ public final void waitTranslation(OJClass clazz) throws MOPException {
+ if (!OJSystem.underConstruction.containsKey(clazz))
+ return;
+
+ synchronized (OJSystem.waitingPool) {
+ if (OJSystem.waitingPool.contains(clazz)) {
+ System.err.println(
+ "a dead lock detected between "
+ + getName()
+ + " and "
+ + clazz.getName());
+ return;
+ }
+ OJSystem.waitingPool.add(this);
+ }
+
+ OJSystem.waited = clazz;
+ Object lock = OJSystem.orderingLock;
+ try {
+ synchronized (lock) {
+ synchronized (this) {
+ this.notifyAll();
+ }
+ lock.wait();
+ }
+ } catch (InterruptedException e) {
+ throw new MOPException(e.toString());
+ } finally {
+ OJSystem.waitingPool.remove(this);
+ }
+ }
+
+ /* -- Modifications -- */
+
+ /** not implemented yet */
+ protected String setName(String simple_name) throws CannotAlterException {
+ throw new CannotAlterException("not implemented");
+ }
+
+ /**
+ * Under implementation.
+ * Modifiers of members should be considered carefully.
+ * @throws CannotAlterException
+ */
+ protected void beInterface() throws CannotAlterException {
+ //do nothing if this is an interface.
+ if (isInterface()) return;
+
+ ClassDeclaration d = getSourceCode();
+ d.beInterface(true);
+ }
+
+ /**
+ * Under implementation.
+ * Modifiers of members should be considered carefully.
+ * @throws CannotAlterException
+ */
+ protected void beClass() throws CannotAlterException {
+ //do nothing if this is a class.
+ if (!isInterface()) return;
+
+ ClassDeclaration d = getSourceCode();
+ d.beInterface(false);
+ }
+
+ protected OJClass setSuperclass(OJClass clazz)
+ throws CannotAlterException {
+ ClassDeclaration d = getSourceCode();
+ if (isInterface()) {
+ throw new CannotAlterException("cannot set a superclass of interface");
+ }
+ OJClass result = getSuperclass();
+ d.setBaseclass(TypeName.forOJClass(clazz));
+ return result;
+ }
+
+ protected OJClass[] setInterfaces(OJClass[] classes)
+ throws CannotAlterException {
+ ClassDeclaration d = getSourceCode();
+ OJClass[] result = getInterfaces();
+ if (isInterface()) {
+ d.setBaseclasses(Toolbox.TNsForOJClasses(classes));
+ } else {
+ d.setInterfaces(Toolbox.TNsForOJClasses(classes));
+ }
+ return result;
+ }
+
+ protected void addInterface(OJClass clazz) throws CannotAlterException {
+ OJClass[] org = getInterfaces();
+ OJClass[] result = new OJClass[org.length + 1];
+ System.arraycopy(org, 0, result, 0, org.length);
+ result[org.length] = clazz;
+ setInterfaces(result);
+ }
+
+ protected OJClass addClass(OJClass clazz) throws CannotAlterException {
+ return substance.addClass(clazz);
+ }
+
+ protected OJClass removeClass(OJClass clazz) throws CannotAlterException {
+ return substance.removeClass(clazz);
+ }
+
+ protected OJField addField(OJField field) throws CannotAlterException {
+ return substance.addField(field);
+ }
+
+ protected OJField removeField(OJField field) throws CannotAlterException {
+ return substance.removeField(field);
+ }
+
+ protected OJMethod addMethod(OJMethod method) throws CannotAlterException {
+ return substance.addMethod(method);
+ }
+
+ protected OJMethod removeMethod(OJMethod method)
+ throws CannotAlterException {
+ return substance.removeMethod(method);
+ }
+
+ protected OJConstructor addConstructor(OJConstructor constr)
+ throws CannotAlterException {
+ return substance.addConstructor(constr);
+ }
+
+ protected OJConstructor removeConstructor(OJConstructor constr)
+ throws CannotAlterException {
+ return substance.removeConstructor(constr);
+ }
+
+ /* -- Translation (overridable) -- */
+
+ public void translateDefinition() throws MOPException {
+ ;
+ }
+
+ /* */
+
+ public ClassDeclaration translateDefinition(
+ Environment env,
+ ClassDeclaration decl)
+ throws MOPException {
+ OJClass base = getSuperclass();
+ if (base != null)
+ waitTranslation(base);
+ OJClass[] faces = getInterfaces();
+ for (int i = 0; i < faces.length; ++i) {
+ waitTranslation(faces[i]);
+ }
+ translateDefinition();
+ return decl;
+ }
+
+ public Expression expandFieldRead(Environment env, FieldAccess expr) {
+ return expr;
+ }
+
+ public Expression expandFieldWrite(
+ Environment env,
+ AssignmentExpression expr) {
+ return expr;
+ }
+
+ public Expression expandMethodCall(Environment env, MethodCall expr) {
+ return expr;
+ }
+
+ public TypeName expandTypeName(Environment env, TypeName expr) {
+ if (isArray()) {
+ return getComponentType().expandTypeName(env, expr);
+ }
+ return expr;
+ }
+
+ public Expression expandAllocation(
+ Environment env,
+ AllocationExpression expr) {
+ return expr;
+ }
+
+ public Expression expandArrayAllocation(
+ Environment env,
+ ArrayAllocationExpression expr) {
+ if (isArray()) {
+ return getComponentType().expandArrayAllocation(env, expr);
+ }
+ return expr;
+ }
+
+ public Expression expandArrayAccess(Environment env, ArrayAccess expr) {
+ if (isArray()) {
+ return getComponentType().expandArrayAccess(env, expr);
+ }
+ return expr;
+ }
+
+ public Expression expandAssignmentExpression(
+ Environment env,
+ AssignmentExpression expr) {
+ if (isArray()) {
+ return getComponentType().expandAssignmentExpression(env, expr);
+ }
+ return expr;
+ }
+
+ public Expression expandExpression(Environment env, Expression expr) {
+ if (isArray()) {
+ return getComponentType().expandExpression(env, expr);
+ }
+ return expr;
+ }
+
+ public Statement expandVariableDeclaration(
+ Environment env,
+ VariableDeclaration decl) {
+ if (isArray()) {
+ return getComponentType().expandVariableDeclaration(env, decl);
+ }
+ return decl;
+ }
+
+ public Expression expandCastExpression(
+ Environment env,
+ CastExpression decl) {
+ if (isArray()) {
+ return getComponentType().expandCastExpression(env, decl);
+ }
+ return decl;
+ }
+
+ public Expression expandCastedExpression(
+ Environment env,
+ CastExpression decl) {
+ if (isArray()) {
+ return getComponentType().expandCastedExpression(env, decl);
+ }
+ return decl;
+ }
+
+ /* -- error handling -- */
+
+ public OJField resolveException(NoSuchMemberException e, String name)
+ throws NoSuchMemberException {
+ System.err.println(
+ "no such " + new Signature(name) + " in " + toString());
+ throw e;
+ }
+
+ public OJMethod resolveException(
+ NoSuchMemberException e,
+ String name,
+ OJClass[] argtypes)
+ throws NoSuchMemberException {
+ System.err.println(
+ "no such " + new Signature(name, argtypes) + " in " + toString());
+ throw e;
+ }
+
+ /* -- syntax extensions -- */
+
+ public static boolean isRegisteredKeyword(String keyword) {
+ return false;
+ }
+
+ public static SyntaxRule getDeclSuffixRule(String keyword) {
+ return null;
+ }
+
+ public static SyntaxRule getTypeSuffixRule(String keyword) {
+ return null;
+ }
+
+ public static boolean isRegisteredModifier(String keyword) {
+ return false;
+ }
+
+ /* -- persistant metalevel information */
+
+ public final String getMetaInfo(String key) {
+ return substance.getMetaInfo(key);
+ }
+
+ public final Enumeration getMetaInfoKeys() {
+ return substance.getMetaInfoKeys();
+ }
+
+ public final Enumeration getMetaInfoElements() {
+ return substance.getMetaInfoElements();
+ }
+
+ protected final String putMetaInfo(String key, String value)
+ throws CannotAlterException {
+ return substance.putMetaInfo(key, value);
+ }
+
+ /** inner use only */
+ public final void writeMetaInfo(Writer out) throws IOException {
+ substance.writeMetaInfo(out);
+ }
+
+}
+
+/**
+ * The abstract class <code>OJClassImp</code> provides an interface to
+ * an implementation of OJClass.
+ */
+abstract class OJClassImp {
+ public abstract String toString();
+ abstract ClassEnvironment getEnvironment();
+ abstract boolean isInterface();
+ abstract boolean isArray();
+ abstract boolean isPrimitive();
+
+ abstract String getName();
+
+ abstract OJClass getSuperclass();
+ abstract OJClass[] getInterfaces();
+ abstract OJClass getComponentType();
+ abstract OJModifier getModifiers();
+ abstract ParseTree getSuffix(String keyword);
+ abstract OJClass getDeclaringClass();
+
+ abstract OJClass[] getDeclaredClasses();
+ abstract OJField[] getDeclaredFields();
+ abstract OJMethod[] getDeclaredMethods();
+ abstract OJConstructor[] getDeclaredConstructors();
+
+ abstract boolean isExecutable();
+ abstract boolean isAlterable();
+ abstract Class getByteCode() throws CannotExecuteException;
+ abstract ClassDeclaration getSourceCode() throws CannotAlterException;
+ abstract Class getCompatibleJavaClass();
+
+ abstract void setDeclaringClass(OJClass parent)
+ throws CannotAlterException;
+
+ abstract OJClass addClass(OJClass clazz) throws CannotAlterException;
+ abstract OJClass removeClass(OJClass clazz) throws CannotAlterException;
+ abstract OJField addField(OJField field) throws CannotAlterException;
+ abstract OJField removeField(OJField field) throws CannotAlterException;
+ abstract OJMethod addMethod(OJMethod method) throws CannotAlterException;
+ abstract OJMethod removeMethod(OJMethod method)
+ throws CannotAlterException;
+ abstract OJConstructor addConstructor(OJConstructor constr)
+ throws CannotAlterException;
+ abstract OJConstructor removeConstructor(OJConstructor constr)
+ throws CannotAlterException;
+
+ abstract String getMetaInfo(String key);
+ abstract Enumeration getMetaInfoKeys();
+ abstract Enumeration getMetaInfoElements();
+ abstract String putMetaInfo(String key, String value)
+ throws CannotAlterException;
+ abstract void writeMetaInfo(Writer out) throws IOException;
+
+ final OJClass forNameAnyway(String name) {
+ return Toolbox.forNameAnyway(getEnvironment(), name);
+ }
+
+ final OJClass[] arrayForNames(String[] names) {
+ return Toolbox.arrayForNames(getEnvironment(), names);
+ }
+
+ static final OJClass forClass(Class javaclass) {
+ return OJClass.forClass(javaclass);
+ }
+
+ static final String nameForJavaClassName(String javaname) {
+ return Toolbox.nameForJavaClassName(javaname);
+ }
+
+ static final String nameToJavaClassName(String ojname) {
+ return Toolbox.nameToJavaClassName(ojname);
+ }
+
+ static final OJField[] arrayForFields(Field[] fields) {
+ return OJField.arrayForFields(fields);
+ }
+
+ static final OJMethod[] arrayForMethods(Method[] methods) {
+ return OJMethod.arrayForMethods(methods);
+ }
+
+ static final OJConstructor[] arrayForConstructors(Constructor[] constrs) {
+ return OJConstructor.arrayForConstructors(constrs);
+ }
+
+}
+
+class OJClassByteCode extends OJClassImp {
+ private Class javaClass;
+
+ private MetaInfo metainfo;
+
+ OJClassByteCode(Class java_class, MetaInfo metainfo) {
+ this.javaClass = java_class;
+ this.metainfo = metainfo;
+ }
+
+ ClassEnvironment getEnvironment() {
+ int last = getName().lastIndexOf('.');
+ String pack = (last == -1) ? null : getName().substring(0, last);
+ String name = Environment.toSimpleName(getName());
+ FileEnvironment fenv = new FileEnvironment(OJSystem.env, pack, name);
+ return new ClassEnvironment(fenv, name);
+ }
+
+ public String toString() {
+ return (isPrimitive() ? getName() : "class " + getName());
+ }
+
+ boolean isInterface() {
+ return javaClass.isInterface();
+ }
+
+ boolean isArray() {
+ return javaClass.isArray();
+ }
+
+ boolean isPrimitive() {
+ return javaClass.isPrimitive();
+ }
+
+ String getName() {
+ return nameForJavaClassName(javaClass.getName());
+ }
+
+ ClassLoader getClassLoader() throws CannotInspectException {
+ return javaClass.getClassLoader();
+ }
+
+ OJClass getSuperclass() {
+ Class base = javaClass.getSuperclass();
+ return ((base == null) ? null : forClass(base));
+ }
+
+ OJClass[] getInterfaces() {
+ return OJClass.arrayForClasses(javaClass.getInterfaces());
+ }
+
+ OJClass getComponentType() {
+ Class comp = javaClass.getComponentType();
+ return ((comp == null) ? null : forClass(comp));
+ }
+
+ OJModifier getModifiers() {
+ return OJModifier.forModifier(javaClass.getModifiers());
+ }
+
+ ParseTree getSuffix(String keyword) {
+ return null;
+ }
+
+ OJClass getDeclaringClass() {
+ Class declarer = javaClass.getDeclaringClass();
+ return ((declarer == null) ? null : forClass(declarer));
+ }
+
+ OJClass[] getDeclaredClasses() {
+ try {
+ return OJClass.arrayForClasses(javaClass.getDeclaredClasses());
+ } catch (SecurityException e) {
+ System.err.println(e);
+ return new OJClass[0];
+ }
+ }
+
+ OJField[] getDeclaredFields() {
+ try {
+ return arrayForFields(javaClass.getDeclaredFields());
+ } catch (SecurityException e) {
+ System.err.println(e);
+ return new OJField[0];
+ }
+ }
+
+ OJMethod[] getDeclaredMethods() {
+ try {
+ return arrayForMethods(javaClass.getDeclaredMethods());
+ } catch (SecurityException e) {
+ System.err.println(e);
+ return new OJMethod[0];
+ }
+ }
+
+ OJConstructor[] getDeclaredConstructors() {
+ try {
+ return arrayForConstructors(javaClass.getDeclaredConstructors());
+ } catch (SecurityException e) {
+ System.err.println(e);
+ return new OJConstructor[0];
+ }
+ }
+
+ /* -- the followings do not exist in regular Java -- */
+
+ boolean isExecutable() {
+ return true;
+ }
+
+ boolean isAlterable() {
+ return false;
+ }
+
+ Class getByteCode() throws CannotExecuteException {
+ return javaClass;
+ }
+
+ ClassDeclaration getSourceCode() throws CannotAlterException {
+ throw new CannotAlterException("getSourceCode()");
+ }
+
+ Class getCompatibleJavaClass() {
+ return javaClass;
+ }
+
+ void setDeclaringClass(OJClass parent) throws CannotAlterException {
+ throw new CannotAlterException("setDeclaringClass()");
+ }
+
+ OJClass addClass(OJClass clazz) throws CannotAlterException {
+ throw new CannotAlterException("addClass()");
+ }
+
+ OJClass removeClass(OJClass clazz) throws CannotAlterException {
+ throw new CannotAlterException("removeClass()");
+ }
+
+ OJField addField(OJField field) throws CannotAlterException {
+ throw new CannotAlterException("addField()");
+ }
+
+ OJField removeField(OJField field) throws CannotAlterException {
+ throw new CannotAlterException("removeField()");
+ }
+
+ OJMethod addMethod(OJMethod method) throws CannotAlterException {
+ throw new CannotAlterException("addMethod()");
+ }
+
+ OJMethod removeMethod(OJMethod method) throws CannotAlterException {
+ throw new CannotAlterException("removeMethod()");
+ }
+
+ OJConstructor addConstructor(OJConstructor constr)
+ throws CannotAlterException {
+ throw new CannotAlterException("addConstructor()");
+ }
+
+ OJConstructor removeConstructor(OJConstructor constr)
+ throws CannotAlterException {
+ throw new CannotAlterException("removeConstructor()");
+ }
+
+ /* -- persistant metalevel information */
+
+ String getMetaInfo(String key) {
+ return metainfo.get(key);
+ }
+
+ Enumeration getMetaInfoKeys() {
+ return metainfo.keys();
+ }
+
+ Enumeration getMetaInfoElements() {
+ return metainfo.elements();
+ }
+
+ String putMetaInfo(String key, String value) throws CannotAlterException {
+ throw new CannotAlterException("putMetaInfo()");
+ }
+
+ void writeMetaInfo(Writer out) throws IOException {
+ }
+
+}
+
+class OJClassSourceCode extends OJClassImp {
+ private OJClass declarer;
+ private ClassDeclaration definition;
+ private ClassEnvironment env;
+
+ private Vector classes = new Vector();
+ private Vector fields = new Vector();
+ private Vector methods = new Vector();
+ private Vector constrs = new Vector();
+
+ private MetaInfo metainfo;
+
+ /* -- constructors -- */
+
+ OJClassSourceCode(
+ OJClass holder,
+ Environment outer_env,
+ OJClass declarer,
+ ClassDeclaration ptree) {
+ this.declarer = declarer;
+ this.definition = ptree;
+ String qname;
+ if (declarer == null) {
+ qname = outer_env.toQualifiedName(definition.getName());
+ //String pack = outer_env.getPackage();
+ //qname = ((pack == null) ? "" : pack + ".") + definition.getName();
+ } else {
+ qname = outer_env.currentClassName() + "." + definition.getName();
+ }
+ this.env = new ClassEnvironment(outer_env, qname);
+ metainfo = new MetaInfo(holder.getClass().getName(), qname);
+
+ MemberDeclarationList mdecls = ptree.getBody();
+ for (int i = 0, len = mdecls.size(); i < len; ++i) {
+ MemberDeclaration mdecl = mdecls.get(i);
+ if (mdecl instanceof ClassDeclaration) {
+ ClassDeclaration d = (ClassDeclaration) mdecl;
+ this.env.recordMemberClass(d.getName());
+ try {
+ OJClass clazz = OJClass.forParseTree(this.env, holder, d);
+ this.classes.addElement(clazz);
+ } catch (Exception ex) {
+ /***** here should be error-handling */
+ ex.printStackTrace();
+ }
+ } else if (mdecl instanceof FieldDeclaration) {
+ FieldDeclaration d = (FieldDeclaration) mdecl;
+ OJField field = new OJField(this.env, holder, d);
+ this.fields.addElement(field);
+ } else if (mdecl instanceof MethodDeclaration) {
+ MethodDeclaration d = (MethodDeclaration) mdecl;
+ OJMethod method = new OJMethod(this.env, holder, d);
+ this.methods.addElement(method);
+ } else if (mdecl instanceof ConstructorDeclaration) {
+ ConstructorDeclaration d = (ConstructorDeclaration) mdecl;
+ OJConstructor constr = new OJConstructor(this.env, holder, d);
+ this.constrs.addElement(constr);
+ } else if (mdecl instanceof MemberInitializer) {
+ /***********/;
+ }
+ }
+ }
+
+ public String toString() {
+ return ("class " + getName());
+ }
+
+ ClassEnvironment getEnvironment() {
+ return env;
+ }
+
+ boolean isInterface() {
+ return definition.isInterface();
+ }
+
+ boolean isArray() {
+ return false;
+ }
+
+ boolean isPrimitive() {
+ return false;
+ }
+
+ String getName() {
+ if (declarer == null) {
+ return env.toQualifiedName(definition.getName());
+ } else {
+ return declarer.getName() + "." + definition.getName();
+ }
+ }
+
+ OJClass getSuperclass() {
+ if (isInterface()) {
+ return null;
+ } else {
+ TypeName base = definition.getBaseclass();
+ String basename =
+ (base == null) ? "java.lang.Object" : base.toString();
+ return forNameAnyway(basename);
+ }
+ }
+
+ OJClass[] getInterfaces() {
+ TypeName[] types;
+ if (isInterface()) {
+ types = definition.getBaseclasses();
+ } else {
+ types = definition.getInterfaces();
+ }
+ String[] names = new String[types.length];
+ for (int i = 0; i < names.length; ++i) {
+ names[i] = types[i].toString();
+ }
+ return arrayForNames(names);
+ }
+
+ OJClass getComponentType() {
+ return null;
+ }
+
+ OJModifier getModifiers() {
+ return OJModifier.forParseTree(definition.getModifiers());
+ }
+
+ ParseTree getSuffix(String keyword) {
+ Hashtable table = definition.getSuffixes();
+ if (table == null)
+ return null;
+ return (ParseTree) table.get(keyword);
+ }
+
+ OJClass getDeclaringClass() {
+ return declarer;
+ }
+
+ OJClass[] getDeclaredClasses() {
+ OJClass[] result = new OJClass[classes.size()];
+ for (int i = 0; i < result.length; ++i) {
+ result[i] = (OJClass) classes.elementAt(i);
+ }
+ return result;
+ }
+
+ OJField[] getDeclaredFields() {
+ OJField[] result = new OJField[fields.size()];
+ for (int i = 0; i < result.length; ++i) {
+ result[i] = (OJField) fields.elementAt(i);
+ }
+ return result;
+ }
+
+ OJMethod[] getDeclaredMethods() {
+ OJMethod[] result = new OJMethod[methods.size()];
+ for (int i = 0; i < result.length; ++i) {
+ result[i] = (OJMethod) methods.elementAt(i);
+ }
+ return result;
+ }
+
+ OJConstructor[] getDeclaredConstructors() {
+ OJConstructor[] result = new OJConstructor[constrs.size()];
+ for (int i = 0; i < result.length; ++i) {
+ result[i] = (OJConstructor) constrs.elementAt(i);
+ }
+ return result;
+ }
+
+ InputStream getResourceAsStream(String name)
+ throws CannotInspectException {
+ throw new CannotInspectException("getResourceAsStream()");
+ }
+
+ java.net.URL getResource(String name) throws CannotInspectException {
+ throw new CannotInspectException("getResource()");
+ }
+
+ /* -- the followings do not exist in regular Java -- */
+
+ boolean isExecutable() {
+ return false;
+ }
+
+ boolean isAlterable() {
+ return true;
+ }
+
+ Class getByteCode() throws CannotExecuteException {
+ throw new CannotExecuteException("getByteCode()");
+ }
+
+ ClassDeclaration getSourceCode() throws CannotAlterException {
+ return definition;
+ }
+
+ Class getCompatibleJavaClass() {
+ return getSuperclass().getCompatibleJavaClass();
+ }
+
+ void setDeclaringClass(OJClass parent) throws CannotAlterException {
+ this.declarer = parent;
+ }
+
+ OJClass addClass(OJClass clazz) throws CannotAlterException {
+ if (!clazz.isAlterable()) {
+ throw new CannotAlterException("cannot add by addClass()");
+ }
+ OJClass result = clazz;
+ /*ClassDeclaration result = clazz.makeCopy();*/
+ this.classes.addElement(result);
+ ClassDeclaration cdecl = result.getSourceCode();
+ MemberDeclarationList memdecls = getSourceCode().getBody();
+ memdecls.add(cdecl);
+ return result;
+ }
+
+ OJClass removeClass(OJClass clazz) throws CannotAlterException {
+ if (!clazz.isAlterable()) {
+ throw new CannotAlterException("cannot remove by removeClass()");
+ }
+ if (!classes.removeElement(clazz))
+ return null;
+ OJClass result = clazz;
+ ClassDeclaration cdecl = result.getSourceCode();
+ MemberDeclarationList memdecls = getSourceCode().getBody();
+ for (int i = 0; i < memdecls.size(); ++i) {
+ if (memdecls.get(i) == cdecl)
+ memdecls.remove(i--);
+ }
+ return result;
+ }
+
+ OJField addField(OJField field) throws CannotAlterException {
+ if (!field.isAlterable()) {
+ throw new CannotAlterException("cannot add by addField()");
+ }
+ OJField result = field;
+ /*FieldDeclaration result = field.makeCopy();*/
+ this.fields.addElement(result);
+ //result.set
+ FieldDeclaration fdecl = result.getSourceCode();
+ MemberDeclarationList memdecls = getSourceCode().getBody();
+ memdecls.add(fdecl);
+ return result;
+ }
+
+ OJField removeField(OJField field) throws CannotAlterException {
+ if (!field.isAlterable()) {
+ throw new CannotAlterException("cannot remove by removeField()");
+ }
+ if (!fields.removeElement(field))
+ return null;
+ OJField result = field;
+ FieldDeclaration fdecl = result.getSourceCode();
+ MemberDeclarationList memdecls = getSourceCode().getBody();
+ for (int i = 0; i < memdecls.size(); ++i) {
+ if (memdecls.get(i) == fdecl)
+ memdecls.remove(i--);
+ }
+ return result;
+ }
+
+ OJMethod addMethod(OJMethod method) throws CannotAlterException {
+ if (!method.isAlterable()) {
+ throw new CannotAlterException("cannot add by addMethod()");
+ }
+ OJMethod result = method;
+ /*MethodDeclaration result = field.makeCopy();*/
+ this.methods.addElement(result);
+ MethodDeclaration mdecl = result.getSourceCode();
+ MemberDeclarationList memdecls = getSourceCode().getBody();
+ memdecls.add(mdecl);
+ return result;
+ }
+
+ OJMethod removeMethod(OJMethod method) throws CannotAlterException {
+ if (!method.isAlterable()) {
+ throw new CannotAlterException("cannot remove by removeMethod()");
+ }
+ if (!methods.removeElement(method))
+ return null;
+ OJMethod result = method;
+ MethodDeclaration fdecl = result.getSourceCode();
+ MemberDeclarationList memdecls = getSourceCode().getBody();
+ for (int i = 0; i < memdecls.size(); ++i) {
+ if (memdecls.get(i) == fdecl)
+ memdecls.remove(i--);
+ }
+ return result;
+ }
+
+ OJConstructor addConstructor(OJConstructor constr)
+ throws CannotAlterException {
+ if (!constr.isAlterable()) {
+ throw new CannotAlterException("cannot add by addConstructor()");
+ }
+ OJConstructor result = constr;
+ /*ConstructorDeclaration result = constr.makeCopy();*/
+ this.constrs.addElement(result);
+ ConstructorDeclaration mdecl = result.getSourceCode();
+ MemberDeclarationList memdecls = getSourceCode().getBody();
+ memdecls.add(mdecl);
+ return result;
+ }
+
+ OJConstructor removeConstructor(OJConstructor constr)
+ throws CannotAlterException {
+ if (!constr.isAlterable()) {
+ throw new CannotAlterException("cannot remove by removeConstructor()");
+ }
+ if (!constrs.removeElement(constr))
+ return null;
+ OJConstructor result = constr;
+ ConstructorDeclaration fdecl = result.getSourceCode();
+ MemberDeclarationList memdecls = getSourceCode().getBody();
+ for (int i = 0; i < memdecls.size(); ++i) {
+ if (memdecls.get(i) == fdecl)
+ memdecls.remove(i--);
+ }
+ return result;
+ }
+
+ /* -- persistant metalevel information */
+
+ String getMetaInfo(String key) {
+ return metainfo.get(key);
+ }
+
+ Enumeration getMetaInfoKeys() {
+ return metainfo.keys();
+ }
+
+ Enumeration getMetaInfoElements() {
+ return metainfo.elements();
+ }
+
+ String putMetaInfo(String key, String value) throws CannotAlterException {
+ return metainfo.put(key, value);
+ }
+
+ void writeMetaInfo(Writer out) throws IOException {
+ metainfo.write(out);
+ }
+
+}
+
+class OJClassArray extends OJClassImp {
+ private OJClass componentType;
+ private OJClass[] classes = new OJClass[0];
+ private OJMethod[] methods = new OJMethod[0];
+ private OJConstructor[] constrs = new OJConstructor[0];
+ private Vector fields = new Vector();
+
+ private MetaInfo metainfo;
+
+ /* -- constructors -- */
+
+ OJClassArray(OJClass componentType) {
+ this.componentType = componentType;
+ fields.addElement(makeLengthField());
+ this.metainfo = new MetaInfo(componentType.getName() + "[]");
+ }
+
+ private final OJField makeLengthField() {
+ OJModifier modif = new OJModifier(OJModifier.PUBLIC | OJModifier.FINAL);
+ OJClass type = OJClass.forClass(int.class);
+ /* exactly not conmponent type */
+ return new OJField(componentType, modif, type, "length");
+ }
+
+ ClassEnvironment getEnvironment() {
+ return (ClassEnvironment) componentType.getEnvironment();
+ }
+
+ public String toString() {
+ return ("class " + componentType.getName() + "[]");
+ }
+
+ boolean isInterface() {
+ return false;
+ }
+
+ boolean isArray() {
+ return true;
+ }
+
+ boolean isPrimitive() {
+ return false;
+ }
+
+ String getName() {
+ return (componentType.getName() + "[]");
+ }
+
+ ClassLoader getClassLoader() throws CannotInspectException {
+ throw new CannotInspectException("getClassLoader()");
+ }
+
+ OJClass getSuperclass() {
+ return OJClass.forClass(Object[].class.getSuperclass());
+ }
+
+ OJClass[] getInterfaces() {
+ return OJClass.arrayForClasses(Object[].class.getInterfaces());
+ }
+
+ OJClass getComponentType() {
+ return componentType;
+ }
+
+ OJModifier getModifiers() {
+ return OJModifier.forModifier(Object[].class.getModifiers());
+ }
+
+ ParseTree getSuffix(String keyword) {
+ return null;
+ }
+
+ OJClass getDeclaringClass() {
+ return null;
+ }
+
+ OJClass[] getDeclaredClasses() {
+ return classes;
+ }
+
+ OJField[] getDeclaredFields() {
+ OJField[] result = new OJField[fields.size()];
+ for (int i = 0; i < result.length; ++i) {
+ result[i] = (OJField) fields.elementAt(i);
+ }
+ return result;
+ }
+
+ OJMethod[] getDeclaredMethods() {
+ return methods;
+ }
+
+ OJConstructor[] getDeclaredConstructors() {
+ return constrs;
+ }
+
+ /* -- the followings do not exist in regular Java -- */
+
+ boolean isExecutable() {
+ return false;
+ }
+
+ boolean isAlterable() {
+ return false;
+ }
+
+ Class getByteCode() throws CannotExecuteException {
+ throw new CannotExecuteException("getByteCode()");
+ }
+
+ ClassDeclaration getSourceCode() throws CannotAlterException {
+ throw new CannotAlterException("getSourceCode()");
+ }
+
+ Class getCompatibleJavaClass() {
+ return getSuperclass().getCompatibleJavaClass();
+ }
+
+ void setDeclaringClass(OJClass parent) throws CannotAlterException {
+ throw new CannotAlterException("setDeclaringClass()");
+ }
+
+ OJClass addClass(OJClass clazz) throws CannotAlterException {
+ throw new CannotAlterException("addClass()");
+ }
+
+ OJClass removeClass(OJClass clazz) throws CannotAlterException {
+ throw new CannotAlterException("removeClass()");
+ }
+
+ OJField addField(OJField field) throws CannotAlterException {
+ throw new CannotAlterException("addField()");
+ }
+
+ OJField removeField(OJField field) throws CannotAlterException {
+ throw new CannotAlterException("removeField()");
+ }
+
+ OJMethod addMethod(OJMethod method) throws CannotAlterException {
+ throw new CannotAlterException("addMethod()");
+ }
+
+ OJMethod removeMethod(OJMethod method) throws CannotAlterException {
+ throw new CannotAlterException("removeMethod()");
+ }
+
+ OJConstructor addConstructor(OJConstructor constr)
+ throws CannotAlterException {
+ throw new CannotAlterException("addConstructor()");
+ }
+
+ OJConstructor removeConstructor(OJConstructor constr)
+ throws CannotAlterException {
+ throw new CannotAlterException("removeConstructor()");
+ }
+
+ /* -- persistant metalevel information */
+
+ String getMetaInfo(String key) {
+ return null;
+ }
+
+ Enumeration getMetaInfoKeys() {
+ return new Vector().elements();
+ }
+
+ Enumeration getMetaInfoElements() {
+ return new Vector().elements();
+ }
+
+ String putMetaInfo(String key, String value) throws CannotAlterException {
+ throw new CannotAlterException("putMetaInfo()");
+ }
+
+ void writeMetaInfo(Writer out) throws IOException {
+ }
+
+}
+
+class OJClassNull extends OJClassImp {
+
+ OJClassNull() {
+ }
+
+ ClassEnvironment getEnvironment() {
+ return new ClassEnvironment(OJSystem.env, getName());
+ }
+
+ public String toString() {
+ return OJSystem.NULLTYPE_NAME;
+ }
+
+ boolean isInterface() {
+ return false;
+ }
+
+ boolean isArray() {
+ return false;
+ }
+
+ boolean isPrimitive() {
+ return false;
+ }
+
+ String getName() {
+ return null;
+ }
+
+ OJClass getSuperclass() {
+ return null;
+ }
+
+ OJClass[] getInterfaces() {
+ return null;
+ }
+
+ OJClass getComponentType() {
+ return null;
+ }
+
+ OJModifier getModifiers() {
+ return null;
+ }
+
+ ParseTree getSuffix(String keyword) {
+ return null;
+ }
+
+ OJClass getDeclaringClass() {
+ return null;
+ }
+
+ OJClass[] getDeclaredClasses() {
+ return null;
+ }
+
+ OJField[] getDeclaredFields() {
+ return null;
+ }
+
+ OJMethod[] getDeclaredMethods() {
+ return null;
+ }
+
+ OJConstructor[] getDeclaredConstructors() {
+ return null;
+ }
+
+ /* -- the followings do not exist in regular Java -- */
+
+ boolean isExecutable() {
+ return false;
+ }
+
+ boolean isAlterable() {
+ return false;
+ }
+
+ Class getByteCode() throws CannotExecuteException {
+ throw new CannotExecuteException("getByteCode()");
+ }
+
+ ClassDeclaration getSourceCode() throws CannotAlterException {
+ throw new CannotAlterException("getSourceCode()");
+ }
+
+ Class getCompatibleJavaClass() {
+ return null;
+ }
+
+ void setDeclaringClass(OJClass parent) throws CannotAlterException {
+ throw new CannotAlterException("setDeclaringClass()");
+ }
+
+ OJClass addClass(OJClass clazz) throws CannotAlterException {
+ throw new CannotAlterException("addClass()");
+ }
+
+ OJClass removeClass(OJClass clazz) throws CannotAlterException {
+ throw new CannotAlterException("removeClass()");
+ }
+
+ OJField addField(OJField field) throws CannotAlterException {
+ throw new CannotAlterException("addField()");
+ }
+
+ OJField removeField(OJField field) throws CannotAlterException {
+ throw new CannotAlterException("removeField()");
+ }
+
+ OJMethod addMethod(OJMethod method) throws CannotAlterException {
+ throw new CannotAlterException("addMethod()");
+ }
+
+ OJMethod removeMethod(OJMethod method) throws CannotAlterException {
+ throw new CannotAlterException("removeMethod()");
+ }
+
+ OJConstructor addConstructor(OJConstructor constr)
+ throws CannotAlterException {
+ throw new CannotAlterException("addConstructor()");
+ }
+
+ OJConstructor removeConstructor(OJConstructor constr)
+ throws CannotAlterException {
+ throw new CannotAlterException("removeConstructor()");
+ }
+
+ /* -- persistant metalevel information */
+
+ String getMetaInfo(String key) {
+ return null;
+ }
+
+ Enumeration getMetaInfoKeys() {
+ return new Vector().elements();
+ }
+
+ Enumeration getMetaInfoElements() {
+ return new Vector().elements();
+ }
+
+ String putMetaInfo(String key, String value) throws CannotAlterException {
+ throw new CannotAlterException("putMetaInfo()");
+ }
+
+ void writeMetaInfo(Writer out) throws IOException {
+ }
+}