/*
 * Jakelib2 - General purpose C++ library
 * Copyright (C) 2001 Florian Wolff  (florian@donuz.de)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * $Id: Class.h,v 1.15 2003/08/27 20:14:49 florian Exp $
 */

#ifndef INCLUDE_JAKELIB2_LANG_CLASS_H
# define INCLUDE_JAKELIB2_LANG_CLASS_H

namespace jakelib {
  namespace lang {

    class String;
    class Classs;

    /**
     * @brief \c Object is the base class for all classes of jakelib.
     * Every inheriting class should at least override the \c getClassname
     * method.
     *
     * @class Class
     * @version $Id: Class.h,v 1.15 2003/08/27 20:14:49 florian Exp $
     * @author Florian 'Overflo' Wolff (florian@donuz.de)
     */
    class Class : public Object
      {
      private:

        /** The fully qualified class name (like "\c jakelib.lang.String").
            The \c String object is created on demand and thus is \c null 
            in the beginning. */
	String* name;

	/** The C-style class name */
	char* name_cstr;

        /** The superclass or \c null for the root class \c Object */
	Class* superClass;

        /** Holds all directly implemented interfaces. 
            The array object is created on demand and thus is \c null
            in the beginning. */
        Classs *interfaces;

        /** A C-style array containing the implemented interfaces. */
        Class **interfaces_carray;

        /** Holds the number of implemented interfaces. */
        int numInterfaces;

        /** If this is an array class, this holds the class of the elements. */
        Class *arrayElementClass;

      public:

        typedef enum {
          CLASS,
          INTERFACE,
          ARRAY,
          PRIMITIVE
        } classtype;

	Class(classtype type, char* name, Class* superName, ...);

        /**
         * Constructs a new array class.
         *
         * @param elementClass The class of the array elements.
         */
	Class(Class *elementClass);

        /**
         * Constructs a new primitive class.
         *
         * @param name The name of the array elements' class.
         */
	Class(char *name);

        /**
         * Get the name of this class, separated by dots for package separators.
         */
	String* getName();

        /**
         * Get the direct superclass of this class.
         */
	Class* getSuperclass();
        
	jboolean isInstance(Object* obj);

	jboolean instanceOf(String* name);

        /**
         * Return the human-readable form of this Object. For an object, this
         * is either "interface " or "class " followed by \c getName().
         *
         * @return The human-readable form of this Object
         */
	String* toString();

        /**
         * Check whether this class represents an interface or not.
         */
        jboolean isInterface();

        /**
         * Return whether this class represents an array type.
         *
         * @return Whether this class represents an array type
         */
        jboolean isArray();

        /**
         * Return whether this class is a primitive type.
         *
         * @return Whether this class represents a primitive type
         */
        jboolean isPrimitive();

        /**
         * Get the interfaces this class directly implements, in the
         * order that they were declared. This returns an empty array, not null,
         * for Object, primitives, void, and classes or interfaces with no direct
         * superinterface.
         *
         * @return The interfaces this class directly implements
         */
        Classs* getInterfaces();

        /**
         * If this is an array, get the \c Class representing the type of array.
         * Examples: calling \c getComponentType() on "\c java.lang.String[]"
         * would return "\c java.lang.String". If
         * this is not an array, returns \c null.
         *
         * @return The array type of this class, or \c null
         */
        Class* getComponentType();

      private:

        /** Holds the type this class is of. */
        classtype type;   

	JAKELIB_DECLARE_CLASS(Class);     
      };

    JAKELIB_DECLARE_ARRAY(Class);
  }
}

#endif

