2005/5/9

     
 

Class.h

artefaktur
// -*- mode:C++; tab-width:2; c-basic-offset:2; indent-tabs-mode:nil -*- 
//
// Copyright (C) 2000-2005 by Roger Rene Kommer / artefaktur, Kassel, Germany.
// 
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public License (LGPL).
// 
// 
// 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 
// License ACDK-FreeLicense document enclosed in the distribution
// for more for more details.
// This file is part of the Artefaktur Component Development Kit:
//                         ACDK
// 
// Please refer to
// - http://www.acdk.de
// - http://www.artefaktur.com
// - http://acdk.sourceforge.net
// for more information.
// 
// $Header: /cvsroot/acdk/acdk/acdk_core/src/acdk/lang/Class.h,v 1.44 2005/04/09 19:26:48 kommer Exp $
#ifndef acdk_lang_Class_h
#define acdk_lang_Class_h

#include "dmi/ClazzInfo.h"
#include "dmi/MetaObject.h"

namespace acdk {
namespace lang {
namespace sys {
  //class ScriptVar;
}
namespace reflect {
  ACDK_DECL_CLASS(Field);
  ACDK_DECL_CLASS(Method);
  ACDK_DECL_CLASS();
  ACDK_DECL_CLASS(Unit);
}
}
}

#include <acdk/lang/reflect/reflect.h>
#include "Package.h"
#include "NoSuchMethodException.h"
#include "NoSuchFieldException.h"
#include "InstantiationException.h"
#include "ClassNotFoundException.h"

namespace acdk {
namespace lang {


ACDK_DECL_CLASS(ClassLoader);
ACDK_DECL_CLASS(Class);


using ::acdk::lang::reflect::Field;

/** 
  A class represents a ACDK Class definition.
  The implementation of Class bases on the information 
  generated by the metacompiler acdkmc. 
  Information about member, methods etc. is only available
  for standard ACDK methods which are not declared as foreign

  API: Mainly Java-Spec.<br>
  @author Roger Rene Kommer (mailto:kommer@artefaktur.com)
  @version $Revision: 1.44 $
  @date $Date: 2005/04/09 19:26:48 $
  @bug some of the methods regarded security and net are not implemented.
  Class is based on the underlying ClazzInfo structur, which will be generated
  by the metacompiler (acdkmc)
  @see ClazzInfo
*/
ACDK_CLASSATTRIBUTE(acdk.tools.mc.ClazzFlagAttribute(acdk.lang.dmi.MiNoDmiProxy)) 
class ACDK_CORE_PUBLIC Class
: extends acdk::lang::Object
, implements dmi::MetaObject
{
  ACDK_WITH_METAINFO(Class)
private:
  /**
    Class is just a wrapper to acdk::lang::dmi::ClazzInfo
  */
  foreign const dmi::ClazzInfo* _objectClazzInfo;
public:

  /**
    create Class with given clazzInfo
  */
  foreign Class(const dmi::ClazzInfo* clazzInfo);

  foreign virtual ~Class();
  virtual void finalize();

  /**
    @internal
    implemented interface for MetaObject
  */
  foreign virtual dmi::MetaInfo* getMetaInfo() 
        { return (dmi::MetaInfo*)_objectClazzInfo->loadFullClazzInfo(); }
  /**
    load full metainfo from  my_shared_lib_metainf.so/dll
    @throw exception if full meta info cannot be resolved
  */
  void resolve() { _objectClazzInfo->loadFullClazzInfo(); }
  /**
    different to Java this method always returns the system class loader.
  */
  RClassLoader getClassLoader();
  /**
    if this class represends an array it returns 
    the type of the elements of the array, otherwise
    Nil
  */
  virtual RClass getComponentType();
  /**
    return a constructor with given parameter types
    @throw NoSuchMethodException if no constructor can be found
  */
  ::acdk::lang::reflect::RConstructor getDeclaredConstructor(IN(RClassArray) parameterTypes) 
                                                                          THROWS1(RNoSuchMethodException);
  /**
    return all constructor of this class
  */
  ::acdk::lang::reflect::RConstructorArray getDeclaredConstructors();
  /**
    return the field declared in this class with given variable name
    @throw NoSuchFieldException if no field with given name is declared
  */
  ::acdk::lang::reflect::RField getDeclaredField(IN(RString) name) THROWS1(RNoSuchFieldException);
  /**
    return all fields declared in this class
  */
  ::acdk::lang::reflect::RFieldArray getDeclaredFields();
  /**
    return the method with given name and parameter types.
    @throw NoSuchMethodException if no such method is declared in this class
  */
  ::acdk::lang::reflect::RMethod getDeclaredMethod(IN(RString) name, IN(RClassArray) parameterTypes) THROWS1(RNoSuchMethodException);
  /**
    return all declared methods of this class
  */
  ::acdk::lang::reflect::RMethodArray getDeclaredMethods();
  /**
    return field declared in this class or one of its parents
    @throw NoSuchFieldException if no such field can be found
  */
  ::acdk::lang::reflect::RField getField(IN(RString) name) THROWS1(RNoSuchFieldException);
  /**
    return all fields declared in this class or one of its parent classes
  */
  ::acdk::lang::reflect::RFieldArray getFields();
  /**
    Java compatible reflection
    @param namedargs is not implemented yet!
  */
  ::acdk::lang::reflect::RMethod getMethod(IN(RString) name, IN(RClassArray) parameterTypes, IN(RStringArray) namedargs = Nil) THROWS1(RNoSuchMethodException);
  /**
    return all methods declared in this class or one of its parent classes
  */
  ::acdk::lang::reflect::RMethodArray getMethods();
  
  /**
    @deprecated Nested classes are not supported by ACDK
    @return always Nil
  */
  RClass getDeclaringClass();

  /**
    @deprecated Nested classes are not supported by ACDK
    @return always Array size == 0
  */
  
  RClassArray getClasses();
  /**
    @deprecated Nested classes are not supported by ACDK
    @return always Array size == 0
  */
  RClassArray getDeclaredClasses();
  /**
    returns the interface this class implements
  */
  RClassArray getInterfaces();
  /**
    returns the unit, this class resides.
    In case no Unit is defined for this class, it returns 0
  */
  ::acdk::lang::reflect::RUnit getUnit();
  /**
    return the clazz flags of this class
    @see acdk::lang::dmi::MetaInfoFlags
  */
  int getModifiers();
  
  /** @return fully qualified name name/space/Class */
  RString getName();
  
  /** @return only classname */
  RString getClassName();
  /**
    return the package in which this class is defined
    may return Nil
  */
  RPackage getPackage();
  /**
    return the super class of this class.
    may return Nil.
  */
  RClass getSuperclass();
  /**
    return all super classes (not including interfaces)
    at index 0 of the array always Object::GetClass()
  */
  RClassArray getSuperClasses();
  /**
    return the declared or calculated SerialVersionUID of this class
  */
  jlong getSerialVersionUID();

  /**
    return true if this class is a BasicArray or a ObjectArray
  */
  bool isArray();
  /**
    return the Array class, if this class is array
    If called on a non-array it returns Nil;
  */
  RClass getArrayElementClass();
  /**
    return true if this class is same as parameter
    or one of its super class or implemented interfaces
  */
  bool isAssignableFrom(IN(RClass) cls);
  /**
    return true if given obj is exactly type of this class
  */
  bool isInstance(IN(acdk::lang::Object) obj);
  /**
    return true if this class is an interface
  */
  bool isInterface();
  /**
    return true if this class is a primitive type (like bool, int, etc.)
  */
  bool isPrimitive();
  
  /**
    creates a new Instance of this Class
    Will only work if class has defined 
    the method 
    static acdk::lang::Object create_instance() 
    or has a default .
  */
  acdk::lang::Object newInstance() THROWS1(RInstantiationException);
  
  /**
    reimplemented from acdk::lang::Object
    @return for example "class acdk.lang.StringBuffer"
  */
  foreign RString toString();
  
  /**
    find in in current loaded modules the given class by name
    @param className name of the class in the form of "acdk/lang/StringBuffer"
    @throw ClassNotFoundException if given class cannot be found
  */
  static RClass forName(IN(RString) className) THROWS1(RClassNotFoundException);

  /**
    try to find the given class. Try to load the class with current classloader
    @param className name of the class in the form of "acdk/lang/StringBuffer"
    @param initialize will be ignored
    @throw ClassNotFoundException if given class cannot be found
  */
  static RClass forName(IN(RString) name, bool initialize) THROWS1(RClassNotFoundException); 
  
  /**
    Same as forName, but not throws an exception if a class cannot be found
    just return Nil;
  */
  static RClass findClass(IN(RString) name);
  /**
    try to find the given class. Try to load the class with current classloader
    @param className name of the class in the form of "acdk/lang/StringBuffer"
    @param initialize will be ignored
    @throw ClassNotFoundException if given class cannot be found
  */
  
  static RClass forName(IN(RString) name, bool initialize, IN(RClassLoader) loader);
  /**
    find in in current loaded modules the given class by name.
    @return Nil if class is not loaded
  */
  static RClass _forName(IN(RString) name); 
  /**
    @return the ClazzInfo held by this Class
  */
  foreign const dmi::ClazzInfo* objectClazzInfo() { return _objectClazzInfo; }
  
  
  foreign bool equals(IN(acdk::lang::Object) obj)
  {
    if (instanceof(obj, Class) == false)
      return false;
    return equals((RClass)obj);
  }
  
  bool equals(IN(RClass) oclass)
  {
    return objectClazzInfo() == oclass->objectClazzInfo();
  }
  
  /**
    @internal
    Create an ObjectArray of the Class component.
    Status: not tested
    @return a new constructed RObjectArrayImpl<TheTypeOfComponent>(length)
  */
  static acdk::lang::Object create_arrayInstance(IN(RClass) component, int length);

  /** 
    @internal
    little helper for the getting Class as singelton 
    @param ClazzInfo* clazzInfo the meta information
    @param acdk::lang::Object instance instance of given class. Use only for debugging purposes
  */
  foreign static RClass getSingeltonClass(const dmi::ClazzInfo* clazzInfo);
  
  /** 
    @internal
    little helper for the getting Class for Arrays as singelton.
    @param ClazzInfo* clazzInfo the meta information
  */
  foreign static RClass getSingeltonArrayClass(const dmi::ClazzInfo* elementinfo);
  foreign static dmi::ClazzInfo* getSingeltonArrayClazz(const dmi::ClazzInfo* elementinfo);
  
  /** 
    @internal
    this method may be called for main() in the initializers of ClazzInfo-mebers 
  */
  foreign static dmi::ClazzInfo* getUnInitializedSingeltonArrayClazz(const dmi::ClazzInfo* elementinfo);
  
  /**
    looking in ClazzInfo base for given Java-Signature
    API: ACDK
    @param RString sign full qualified name
  */
  static RClass getClassByJType(IN(RString) sign);

  /**
    Returns true if this class directly implements the acdk::io::Serializable interface
  */
  bool isSerializable();
  /**
    Returns true if given function is implemented in this class (not in any derivided).
    API: ACDK, Serialisation
  */
  bool hasWriteObject();
  
  /**
    Returns true if given function is implemented in this class (not in any derivided).
    API: ACDK, Serialisation
  */
  bool hasReadObject();

  /**
    Returns true if given function is implemented in this class (not in any derivided).
    API: ACDK, Serialisation
  */
  bool hasWriteReplace();

  /**
    Returns true if given function is implemented in this class (not in any derivided).
    API: ACDK, Serialisation
  */
  bool hasReadResolve();

  /**
    create proxy for dmi.
    @param proxies must initialized array. new proxies will be appended
    @param dmiTarget where to forward the call
    @param flags MiIvDeclared may set to create only proxy for this class and 
                 not for supers
    @return true if any new proxies are added to proxies
  */
  bool getDmiProxies(IN(RObjectArray) proxies, IN(acdk::lang::Object) dmiTarget, int flags);
  /**
    creates a DmiProxy from this class.
    @param dmiTarget the object where the calls will be forewarded via DMI
    @return Nil if no DMI-Proxy can be created. The return object will be a instance of this Class
    @code
      acdk::lang::Object scriptObject = getScriptObject(); // dummy code
      RStringBuffer sb = (RStringBuffer)StringBuffer::GetClass()->createDmiProxy(scriptObject);
    @endcode
  */
  acdk::lang::Object createDmiProxy(IN(acdk::lang::Object) dmiTarget);
  int compareTo(IN(RClass) other) { return toString()->compareTo(other->toString()); }
  int compareTo(IN(acdk::lang::Object) other) { return compareTo(RClass(other)); }
  
  virtual RString toTypeString(int format = acdk::lang::dmi::TpFtFormatStandard) { return objectClazzInfo()->toTypeString(format); }
protected:
  /**
    returns the member _object if not Nil, otherwise try to create a new instance
    API: ACDK
    Status: not tested
  */
  acdk::lang::Object _getInstance();
};


template <class T>
inline
T& getTypedObjectRef(::acdk::lang::dmi::ScriptVar& thissv)
  {
    ::acdk::lang::RObject& robj = thissv.getObjectRef();
    if (robj == Nil)
      return reinterpret_cast<T&>(robj);
    if (T::clazzInfo()->assignableFrom(robj->getClazzInfo()) == false)
      ::acdk::lang::dmi::ScriptVar::_throwWrongType(T::clazzInfo(), robj->getClazzInfo());
    return reinterpret_cast<T&>(robj);
  }


template <typename T>
inline
::acdk::lang::dmi::ScriptVar outOfAs(const RefHolder<T>& t,  IN(::acdk::lang::RClass) cls)
{
  return ::acdk::lang::dmi::ScriptVar((::acdk::lang::RObject*)const_cast<RefHolder<T>& >(t)._ref_this(),
                   ::acdk::lang::dmi::MiAiOut, cls->objectClazzInfo());
}

template <class T>
inline
::acdk::lang::dmi::ScriptVar inOfAs(T* t, IN(::acdk::lang::RClass) cls)
{
  return ::acdk::lang::dmi::ScriptVar(::acdk::lang::RObject(t), ::acdk::lang::dmi::MiAiIn, cls->objectClazzInfo());
}

template <typename T>
inline
::acdk::lang::dmi::ScriptVar inOfAs(const RefHolder<T>& t, IN(::acdk::lang::RClass) cls)
{
  return ::acdk::lang::dmi::ScriptVar(acdk::lang::Object(t),
                   ::acdk::lang::dmi::MiAiIn, cls->objectClazzInfo());
}

template <typename T>
inline
::acdk::lang::dmi::ScriptVar inOfAs(const InterfaceHolder<T>& t, IN(::acdk::lang::RClass) cls)
{
  return ::acdk::lang::dmi::ScriptVar(acdk::lang::Object(t), ::acdk::lang::dmi::MiAiIn, cls->objectClazzInfo());
}

template <typename T, typename S>
inline
::acdk::lang::dmi::ScriptVar inOfAs(const ThrowableHolder<T, S>& t,  IN(::acdk::lang::RClass) cls)
{
  return ::acdk::lang::dmi::ScriptVar(acdk::lang::Object(t), ::acdk::lang::dmi::MiAiIn, cls->objectClazzInfo());
}

template <typename T>
inline
::acdk::lang::dmi::ScriptVar outOfAs(const InterfaceHolder<T>& t,  IN(::acdk::lang::RClass) cls)
{
  return ::acdk::lang::dmi::ScriptVar((::acdk::lang::RObject*)const_cast<InterfaceHolder<T>& >(t)._ref_this(),
                   ::acdk::lang::dmi::MiAiOut, cls->objectClazzInfo());
}

} // lang
} // acdk
#include "BasicArrayInl.h"
#include "ObjectArrayBaseInl.h"

#endif //acdk_lang_Class_h