/* ====================================================================
 * Copyright (c) 2004-2006 Open Source Applications Foundation.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions: 
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software. 
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 * ====================================================================
 */

#include <gcj/cni.h>

#include <java/lang/Object.h>
#include <java/lang/Class.h>
#include <java/lang/ClassLoader.h>
#include <java/lang/Thread.h>
#include <java/lang/ThreadGroup.h>
#include <java/lang/Runnable.h>
#include <java/lang/String.h>
#include <java/lang/StringBuffer.h>
#include <java/lang/Throwable.h>
#include <java/lang/Comparable.h>
#include <java/lang/Runnable.h>
#include <java/lang/Integer.h>
#include <java/lang/Long.h>
#include <java/lang/Float.h>
#include <java/lang/Double.h>
#include <java/lang/ClassCastException.h>
#include <java/lang/Package.h>
#include <java/lang/Runtime.h>
#include <java/lang/Process.h>
#include <java/lang/System.h>
#include <java/io/StringWriter.h>
#include <java/io/PrintWriter.h>
#include <java/io/PrintStream.h>
#include <java/io/FilterOutputStream.h>
#include <java/io/OutputStream.h>
#include <java/io/Reader.h>
#include <java/io/StringReader.h>
#include <java/io/File.h>
#include <java/util/Map.h>
#include <java/util/IdentityHashMap.h>
#include <java/util/Dictionary.h>
#include <java/util/Hashtable.h>
#include <java/util/Properties.h>
#include <java/util/Iterator.h>
#include <java/util/Set.h>
#include <java/util/Enumeration.h>
#include <java/util/Locale.h>
#include <java/util/BitSet.h>
#include <java/util/Date.h>
#include <java/util/TimeZone.h>
#include <java/util/Calendar.h>
#include <java/util/GregorianCalendar.h>
#include <java/util/Collection.h>
#include <java/util/NoSuchElementException.h>
#include <java/text/Format.h>
#include <java/text/NumberFormat.h>
#include <java/text/DecimalFormat.h>
#include <java/text/DateFormat.h>
#include <java/text/SimpleDateFormat.h>

#ifdef GCJ_STATIC
#include <gnu/gcj/convert/Output_8859_1.h>
#include <gnu/gcj/convert/Output_ASCII.h>
#include <gnu/gcj/convert/Output_EUCJIS.h>
#include <gnu/gcj/convert/Output_iconv.h>
#include <gnu/gcj/convert/Output_JavaSrc.h>
#include <gnu/gcj/convert/Output_SJIS.h>
#include <gnu/gcj/convert/Output_UTF8.h>
#endif

#include <Python.h>
#include "structmember.h"

#include "cpp/PyLucene.h"
#include "macros.h"
#include "functions.h"
#include "converters.h"

#include "org/osafoundation/io/PythonReader.h"
#include "org/osafoundation/util/PythonException.h"
#include "org/osafoundation/util/PythonRunnable.h"
#include "java.h"


/* Object */

static void j_object_dealloc(j_object *self);
static PyObject *j_object_new(PyTypeObject *type,
                              PyObject *args, PyObject *kwds);
static int j_object_init(j_object *self, PyObject *args, PyObject *kwds);
static int j_object_hash(j_object *self);
static PyObject *j_object_richcmp(j_object *, PyObject *o2, int op);
static PyObject *j_object_str(j_object *self);
static PyObject *j_object_repr(j_object *self);
static PyObject *j_object_equals(j_object *self, PyObject *arg);
static PyObject *j_object_hashCode(j_object *self);
static PyObject *j_object_notify(j_object *self);
static PyObject *j_object_notifyAll(j_object *self);
static PyObject *j_object_wait(j_object *self, PyObject *args);
static PyObject *j_object_getClass(j_object *self);

static PyMemberDef j_object_members[] = {
    { NULL, 0, 0, 0, NULL }
};

static PyMethodDef j_object_methods[] = {
    { "toString", (PyCFunction) j_object_str, METH_NOARGS, "" },
    { "getClass", (PyCFunction) j_object_getClass, METH_NOARGS, "" },
    { "equals", (PyCFunction) j_object_equals, METH_O, "" },
    { "hashCode", (PyCFunction) j_object_hashCode, METH_NOARGS, "" },
    { "notify", (PyCFunction) j_object_notify, METH_NOARGS, "" },
    { "notifyAll", (PyCFunction) j_object_notifyAll, METH_NOARGS, "" },
    { "wait", (PyCFunction) j_object_wait, METH_VARARGS, "" },
    { NULL, NULL, 0, NULL }
};


PyTypeObject ObjectType = {
    PyObject_HEAD_INIT(NULL)
    0,                                   /* ob_size */
    "PyLucene.Object",                   /* tp_name */
    sizeof(j_object),                    /* tp_basicsize */
    0,                                   /* tp_itemsize */
    (destructor)j_object_dealloc,        /* tp_dealloc */
    0,                                   /* tp_print */
    0,                                   /* tp_getattr */
    0,                                   /* tp_setattr */
    0,                                   /* tp_compare */
    (reprfunc)j_object_repr,             /* tp_repr */
    0,                                   /* tp_as_number */
    0,                                   /* tp_as_sequence */
    0,                                   /* tp_as_mapping */
    (hashfunc)j_object_hash,             /* tp_hash  */
    0,                                   /* tp_call */
    (reprfunc)j_object_str,              /* tp_str */
    0,                                   /* tp_getattro */
    0,                                   /* tp_setattro */
    0,                                   /* tp_as_buffer */
    (Py_TPFLAGS_DEFAULT |
     Py_TPFLAGS_BASETYPE),               /* tp_flags */
    "j_object objects",                  /* tp_doc */
    0,                                   /* tp_traverse */
    0,                                   /* tp_clear */
    (richcmpfunc)j_object_richcmp,       /* tp_richcompare */
    0,                                   /* tp_weaklistoffset */
    0,                                   /* tp_iter */
    0,                                   /* tp_iternext */
    j_object_methods,                    /* tp_methods */
    j_object_members,                    /* tp_members */
    0,                                   /* tp_getset */
    0,                                   /* tp_base */
    0,                                   /* tp_dict */
    0,                                   /* tp_descr_get */
    0,                                   /* tp_descr_set */
    0,                                   /* tp_dictoffset */
    (initproc)j_object_init,             /* tp_init */
    0,                                   /* tp_alloc */
    (newfunc)j_object_new,               /* tp_new */
};

PyObject *wrap_Object(java::lang::Object *object)
{
    if (object)
    {
        if (java::lang::String::class$.isInstance(object))
            return j2p((jstring) object);

        j_object *self = (j_object *) ObjectType.tp_alloc(&ObjectType, 0);
        if (self)
            self->object = refObject(object);
        return (PyObject *) self;
    }
    Py_RETURN_NONE;
}

/* Throwable */

class j_throwable {
public:
    PyObject_HEAD
    java::lang::Throwable *object;
};

static int j_throwable_init(j_throwable *self, PyObject *args, PyObject *kwds);

static PyObject *j_throwable_getCause(j_throwable *self);
static PyObject *j_throwable_getLocalizedMessage(j_throwable *self);
static PyObject *j_throwable_getMessage(j_throwable *self);
static PyObject *j_throwable_printStackTrace(j_throwable *self);

static PyMethodDef j_throwable_methods[] = {
    DECLARE_METHOD(j_throwable, getCause, METH_NOARGS),
    DECLARE_METHOD(j_throwable, getLocalizedMessage, METH_NOARGS),
    DECLARE_METHOD(j_throwable, getMessage, METH_NOARGS),
    DECLARE_METHOD(j_throwable, printStackTrace, METH_NOARGS),
    { NULL, NULL, 0, NULL }
};

DECLARE_TYPE(Throwable, j_throwable, Object, java::lang::Throwable,
             j_throwable_init);

/* Class */

class j_class {
public:
    PyObject_HEAD
    java::lang::Class *object;
};

static PyObject *j_class_getName(j_class *self);
static PyObject *j_class_isArray(j_class *self);
static PyObject *j_class_isInterface(j_class *self);
static PyObject *j_class_isPrimitive(j_class *self);
static PyObject *j_class_isAssignableFrom(j_class *self, PyObject *arg);
static PyObject *j_class_isInstance(j_class *self, PyObject *arg);
static PyObject *j_class_getClassLoader(j_class *self);
static PyObject *j_class_forName(PyTypeObject *type, PyObject *args);

static PyMethodDef j_class_methods[] = {
    DECLARE_METHOD(j_class, getName, METH_NOARGS),
    DECLARE_METHOD(j_class, isArray, METH_NOARGS),
    DECLARE_METHOD(j_class, isInterface, METH_NOARGS),
    DECLARE_METHOD(j_class, isPrimitive, METH_NOARGS),
    DECLARE_METHOD(j_class, isAssignableFrom, METH_O),
    DECLARE_METHOD(j_class, isInstance, METH_O),
    DECLARE_METHOD(j_class, getClassLoader, METH_NOARGS),
    DECLARE_METHOD(j_class, forName, METH_VARARGS | METH_CLASS),
    { NULL, NULL, 0, NULL }
};

DECLARE_TYPE(Class, j_class, Object, java::lang::Class, abstract_init);


/* ClassLoader */

class j_classloader {
public:
    PyObject_HEAD
    java::lang::ClassLoader *object;
};

static PyObject *j_classloader_loadClass(j_classloader *self, PyObject *arg);
static PyObject *j_classloader_getSystemClassLoader(PyTypeObject *type);

static PyMethodDef j_classloader_methods[] = {
    DECLARE_METHOD(j_classloader, loadClass, METH_O),
    DECLARE_METHOD(j_classloader, getSystemClassLoader, METH_NOARGS | METH_CLASS),
    { NULL, NULL, 0, NULL }
};

DECLARE_TYPE(ClassLoader, j_classloader, Object, java::lang::ClassLoader,
             abstract_init);

/* Comparable */

class j_comparable {
public:
    PyObject_HEAD
    java::lang::Comparable *object;
};

static int j_comparable_init(j_comparable *self,
                             PyObject *args, PyObject *kwds);
static PyObject *j_comparable_compareTo(j_comparable *self, PyObject *arg);

static PyMethodDef j_comparable_methods[] = {
    DECLARE_METHOD(j_comparable, compareTo, METH_O),
    { NULL, NULL, 0, NULL }
};

DECLARE_TYPE(Comparable, j_comparable, Object, java::lang::Comparable,
             j_comparable_init);

int check_Comparable(PyObject *arg)
{
    return (PyInt_Check(arg) ||
            PyLong_Check(arg) ||
            PyFloat_Check(arg) ||
            PyString_Check(arg) ||
            PyUnicode_Check(arg) ||
            PyObject_HasAttrString(arg, "compareTo"));
}

java::lang::Comparable *make_Comparable(PyObject *arg)
{
    return pc2jc(arg);
}

/* Runnable */

class j_runnable {
public:
    PyObject_HEAD
    java::lang::Runnable *object;
};

static int j_runnable_init(j_runnable *self, PyObject *args, PyObject *kwds);
static PyObject *j_runnable_run(j_runnable *self);

static PyMethodDef j_runnable_methods[] = {
    DECLARE_METHOD(j_runnable, run, METH_NOARGS),
    { NULL, NULL, 0, NULL }
};

DECLARE_TYPE(Runnable, j_runnable, Object, java::lang::Runnable,
             j_runnable_init);

static int check_Runnable(PyObject *arg)
{
    return PyObject_HasAttrString(arg, "run");
}

static java::lang::Runnable *make_Runnable(PyObject *arg)
{
    jlong ptr; *(PyObject **) &ptr = arg;

    return (java::lang::Runnable *)
        new org::osafoundation::util::PythonRunnable(ptr);
}

/* Thread */

class j_thread {
public:
    PyObject_HEAD
    java::lang::Thread *object;
};

static int j_thread_init(j_thread *self, PyObject *args, PyObject *kwds);
static PyObject *j_thread_getName(j_thread *self);
static PyObject *j_thread_setName(j_thread *self, PyObject *arg);
static PyObject *j_thread_isAlive(j_thread *self);
static PyObject *j_thread_isDaemon(j_thread *self);
static PyObject *j_thread_setDaemon(j_thread *self, PyObject *arg);
static PyObject *j_thread_isInterrupted(j_thread *self);
static PyObject *j_thread_start(j_thread *self);
static PyObject *j_thread_join(j_thread *self, PyObject *args);

static PyMethodDef j_thread_methods[] = {
    DECLARE_METHOD(j_thread, getName, METH_NOARGS),
    DECLARE_METHOD(j_thread, setName, METH_O),
    DECLARE_METHOD(j_thread, isAlive, METH_NOARGS),
    DECLARE_METHOD(j_thread, isDaemon, METH_NOARGS),
    DECLARE_METHOD(j_thread, setDaemon, METH_O),
    DECLARE_METHOD(j_thread, isInterrupted, METH_NOARGS),
    DECLARE_METHOD(j_thread, start, METH_NOARGS),
    DECLARE_METHOD(j_thread, join, METH_VARARGS),
    { NULL, NULL, 0, NULL }
};

DECLARE_TYPE(Thread, j_thread, Object, java::lang::Thread, j_thread_init);

/* System */

class j_system {
public:
    PyObject_HEAD
    java::lang::System *object;
};

static PyObject *j_system_currentTimeMillis(PyTypeObject *type);
static PyObject *j_system_gc(PyTypeObject *type);
static PyObject *j_system_runFinalization(PyTypeObject *type);
static PyObject *j_system_getProperty(PyTypeObject *type, PyObject *args);
static PyObject *j_system_setProperty(PyTypeObject *type, PyObject *args);
static PyObject *j_system_getProperties(PyTypeObject *type);
static PyObject *j_system_load(PyTypeObject *type, PyObject *arg);
static PyObject *j_system_loadLibrary(PyTypeObject *type, PyObject *arg);
static PyObject *j_system_mapLibraryName(PyTypeObject *type, PyObject *arg);
static PyObject *j_system_identityHashCode(PyTypeObject *type, PyObject *arg);

static PyMethodDef j_system_methods[] = {
    DECLARE_METHOD(j_system, currentTimeMillis, METH_NOARGS | METH_CLASS),
    DECLARE_METHOD(j_system, gc, METH_NOARGS | METH_CLASS),
    DECLARE_METHOD(j_system, runFinalization, METH_NOARGS | METH_CLASS),
    DECLARE_METHOD(j_system, getProperty, METH_VARARGS | METH_CLASS),
    DECLARE_METHOD(j_system, setProperty, METH_VARARGS | METH_CLASS),
    DECLARE_METHOD(j_system, getProperties, METH_NOARGS | METH_CLASS),
    DECLARE_METHOD(j_system, load, METH_O | METH_CLASS),
    DECLARE_METHOD(j_system, loadLibrary, METH_O | METH_CLASS),
    DECLARE_METHOD(j_system, mapLibraryName, METH_O | METH_CLASS),
    DECLARE_METHOD(j_system, identityHashCode, METH_O | METH_CLASS),
    { NULL, NULL, 0, NULL }
};

DECLARE_TYPE(System, j_system, Object, java::lang::System, abstract_init);

/* Properties */

class j_properties {
public:
    PyObject_HEAD
    java::util::Properties *object;
};

static int j_properties_init(j_properties *self,
                             PyObject *args, PyObject *kwds);
static PyObject *j_properties_getProperty(j_properties *self, PyObject *args);
static PyObject *j_properties_setProperty(j_properties *self, PyObject *args);
static PyObject *j_properties_propertyNames(j_properties *self);
static PyObject *j_properties___contains__(j_properties *self, PyObject *arg);

static PyMethodDef j_properties_methods[] = {
    DECLARE_METHOD(j_properties, getProperty, METH_VARARGS),
    DECLARE_METHOD(j_properties, setProperty, METH_VARARGS),
    DECLARE_METHOD(j_properties, propertyNames, METH_NOARGS),
    DECLARE_METHOD(j_properties, __contains__, METH_O),
    { NULL, NULL, 0, NULL }
};

DECLARE_TYPE(Properties, j_properties, Object, java::util::Properties,
             j_properties_init);

static int j_properties_dict_length(j_properties *self);
static PyObject *j_properties_dict_get(j_properties *self, PyObject *key);
static int j_properties_dict_set(j_properties *self,
                                 PyObject *key, PyObject *value);

static PyMappingMethods j_properties_as_mapping = {
    (inquiry) j_properties_dict_length,
    (binaryfunc) j_properties_dict_get,
    (objobjargproc) j_properties_dict_set
};

/* Iterator */

class j_iterator {
public:
    PyObject_HEAD
    java::util::Iterator *object;
};

static PyObject *j_iterator_hasNext(j_iterator *self);
static PyObject *j_iterator_next(j_iterator *self);

static PyMethodDef j_iterator_methods[] = {
    DECLARE_METHOD(j_iterator, hasNext, METH_NOARGS),
    DECLARE_METHOD(j_iterator, next, METH_NOARGS),
    { NULL, NULL, 0, NULL }
};

DECLARE_TYPE(Iterator, j_iterator, Object, java::util::Iterator, abstract_init);

PyObject *j_iterator_iter(j_iterator *self);

/* Enumeration */

class j_enumeration {
public:
    PyObject_HEAD
    java::util::Enumeration *object;
};

static PyObject *j_enumeration_hasMoreElements(j_enumeration *self);
static PyObject *j_enumeration_nextElement(j_enumeration *self);
#define j_enumeration_next j_enumeration_nextElement

static PyMethodDef j_enumeration_methods[] = {
    DECLARE_METHOD(j_enumeration, hasMoreElements, METH_NOARGS),
    DECLARE_METHOD(j_enumeration, nextElement, METH_NOARGS),
    DECLARE_METHOD(j_enumeration, next, METH_NOARGS),
    { NULL, NULL, 0, NULL }
};

DECLARE_TYPE(Enumeration, j_enumeration, Object, java::util::Enumeration,
             abstract_init);

PyObject *j_enumeration_iter(j_enumeration *self);

/* StringEnumeration */

class j_stringenumeration {
public:
    PyObject_HEAD
    java::util::Enumeration *object;
};

static PyObject *j_stringenumeration_nextElement(j_enumeration *self);
#define j_stringenumeration_next j_stringenumeration_nextElement

static PyMethodDef j_stringenumeration_methods[] = {
    DECLARE_METHOD(j_enumeration, nextElement, METH_NOARGS),
    DECLARE_METHOD(j_enumeration, next, METH_NOARGS),
    { NULL, NULL, 0, NULL }
};

DECLARE_TYPE(StringEnumeration, j_stringenumeration, Enumeration,
             java::util::Enumeration, abstract_init);

/* PrintStream */

class j_printstream {
public:
    PyObject_HEAD
    java::io::PrintStream *object;
};

static PyObject *j_printstream_flush(j_printstream *self);
static PyObject *j_printstream_printString(j_printstream *self, PyObject *arg);
static PyObject *j_printstream_printObject(j_printstream *self, PyObject *arg);
static PyObject *j_printstream_println(j_printstream *self, PyObject *arg);

static PyMethodDef j_printstream_methods[] = {
    DECLARE_METHOD(j_printstream, flush, METH_NOARGS),
    DECLARE_METHOD(j_printstream, printString, METH_O),
    DECLARE_METHOD(j_printstream, printObject, METH_O),
    DECLARE_METHOD(j_printstream, println, METH_O),
    { NULL, NULL, 0, NULL }
};

DECLARE_TYPE(PrintStream, j_printstream, Object, java::io::PrintStream,
             abstract_init);

/* Process */

class j_process {
public:
    PyObject_HEAD
    java::lang::Process *object;
};

static PyObject *j_process_destroy(j_process *self);
static PyObject *j_process_exitValue(j_process *self);
static PyObject *j_process_waitFor(j_process *self);

static PyMethodDef j_process_methods[] = {
    DECLARE_METHOD(j_process, destroy, METH_NOARGS),
    DECLARE_METHOD(j_process, exitValue, METH_NOARGS),
    DECLARE_METHOD(j_process, waitFor, METH_NOARGS),
    { NULL, NULL, 0, NULL }
};

DECLARE_TYPE(Process, j_process, Object, java::lang::Process, abstract_init);

/* Runtime */

class j_runtime {
public:
    PyObject_HEAD
    java::lang::Runtime *object;
};

static PyObject *j_runtime_getRuntime(PyTypeObject *type);
static PyObject *j_runtime_freeMemory(j_runtime *self);
static PyObject *j_runtime_totalMemory(j_runtime *self);
static PyObject *j_runtime_maxMemory(j_runtime *self);
static PyObject *j_runtime_gc(j_runtime *self);
static PyObject *j_runtime_runFinalization(j_runtime *self);
static PyObject *j_runtime_availableProcessors(j_runtime *self);
static PyObject *j_runtime_addShutdownHook(j_runtime *self, PyObject *arg);
static PyObject *j_runtime_removeShutdownHook(j_runtime *self, PyObject *arg);
static PyObject *j_runtime_execute(j_runtime *self, PyObject *args);
static PyObject *j_runtime_traceInstructions(j_runtime *self, PyObject *arg);
static PyObject *j_runtime_traceMethodCalls(j_runtime *self, PyObject *arg);

static PyMethodDef j_runtime_methods[] = {
    DECLARE_METHOD(j_runtime, getRuntime, METH_NOARGS | METH_CLASS),
    DECLARE_METHOD(j_runtime, freeMemory, METH_NOARGS),
    DECLARE_METHOD(j_runtime, totalMemory, METH_NOARGS),
    DECLARE_METHOD(j_runtime, maxMemory, METH_NOARGS),
    DECLARE_METHOD(j_runtime, gc, METH_NOARGS),
    DECLARE_METHOD(j_runtime, runFinalization, METH_NOARGS),
    DECLARE_METHOD(j_runtime, availableProcessors, METH_NOARGS),
    DECLARE_METHOD(j_runtime, addShutdownHook, METH_O),
    DECLARE_METHOD(j_runtime, removeShutdownHook, METH_O),
    DECLARE_METHOD(j_runtime, execute, METH_VARARGS),
    DECLARE_METHOD(j_runtime, traceInstructions, METH_O),
    DECLARE_METHOD(j_runtime, traceMethodCalls, METH_O),
    { NULL, NULL, 0, NULL }
};

DECLARE_TYPE(Runtime, j_runtime, Object, java::lang::Runtime, abstract_init);

/* Package */

class j_package {
public:
    PyObject_HEAD
    java::lang::Package *object;
};

static PyObject *j_package_getPackage(PyTypeObject *type, PyObject *arg);
static PyObject *j_package_getImplementationTitle(j_package *self);
static PyObject *j_package_getImplementationVendor(j_package *self);
static PyObject *j_package_getImplementationVersion(j_package *self);
static PyObject *j_package_getName(j_package *self);
static PyObject *j_package_getSpecificationTitle(j_package *self);
static PyObject *j_package_getSpecificationVendor(j_package *self);
static PyObject *j_package_getSpecificationVersion(j_package *self);
static PyObject *j_package_isCompatibleWith(j_package *self, PyObject *arg);
static PyObject *j_package_isSealed(j_package *self);

static PyMethodDef j_package_methods[] = {
    DECLARE_METHOD(j_package, getPackage, METH_O | METH_CLASS),
    DECLARE_METHOD(j_package, getImplementationTitle, METH_NOARGS),
    DECLARE_METHOD(j_package, getImplementationVendor, METH_NOARGS),
    DECLARE_METHOD(j_package, getImplementationVersion, METH_NOARGS),
    DECLARE_METHOD(j_package, getName, METH_NOARGS),
    DECLARE_METHOD(j_package, getSpecificationTitle, METH_NOARGS),
    DECLARE_METHOD(j_package, getSpecificationVendor, METH_NOARGS),
    DECLARE_METHOD(j_package, getSpecificationVersion, METH_NOARGS),
    DECLARE_METHOD(j_package, isCompatibleWith, METH_O),
    DECLARE_METHOD(j_package, isSealed, METH_NOARGS),
    { NULL, NULL, 0, NULL }
};

DECLARE_TYPE(Package, j_package, Object, java::lang::Package, abstract_init);

/* Reader */

class j_reader {
public:
    PyObject_HEAD
    java::io::Reader *object;
};

static int j_reader_init(j_reader *self, PyObject *args, PyObject *kwds);

static PyObject *j_reader_close(j_reader *self);
static PyObject *j_reader_read(j_reader *self, PyObject *args);

static PyMethodDef j_reader_methods[] = {
    DECLARE_METHOD(j_reader, close, METH_NOARGS),
    DECLARE_METHOD(j_reader, read, METH_VARARGS),
    { NULL, NULL, 0, NULL }
};

DECLARE_TYPE(Reader, j_reader, Object, java::io::Reader, j_reader_init);

int check_Reader(PyObject *arg)
{
    return PyObject_HasAttrString(arg, "read");
}

java::io::Reader *make_Reader(PyObject *arg)
{
    jlong ptr; *(PyObject **) &ptr = arg;

    return (java::io::Reader *)
        new org::osafoundation::io::PythonReader(ptr);
}

/* StringReader */

class j_stringreader {
public:
    PyObject_HEAD
    java::io::StringReader *object;
};

static int j_stringreader_init(j_stringreader *self,
                               PyObject *args, PyObject *kwds);

static PyMethodDef j_stringreader_methods[] = {
    { NULL, NULL, 0, NULL }
};

DECLARE_TYPE(StringReader, j_stringreader, Reader, java::io::StringReader,
             j_stringreader_init);

/* Locale */

class j_locale {
public:
    PyObject_HEAD
    java::util::Locale *object;
};

static int j_locale_init(j_locale *self, PyObject *args, PyObject *kwds);
static PyObject *j_locale_getDefault(PyTypeObject *type);
static PyObject *j_locale_setDefault(PyTypeObject *type, PyObject *arg);
static PyObject *j_locale_getAvailableLocales(PyTypeObject *type);
static PyObject *j_locale_getISOCountries(PyTypeObject *type);
static PyObject *j_locale_getISOLanguages(PyTypeObject *type);
static PyObject *j_locale_getLanguage(j_locale *self);
static PyObject *j_locale_getCountry(j_locale *self);
static PyObject *j_locale_getVariant(j_locale *self);
static PyObject *j_locale_getISO3Language(j_locale *self);
static PyObject *j_locale_getISO3Country(j_locale *self);
static PyObject *j_locale_getDisplayLanguage(j_locale *self, PyObject *args);
static PyObject *j_locale_getDisplayCountry(j_locale *self, PyObject *args);
static PyObject *j_locale_getDisplayVariant(j_locale *self, PyObject *args);
static PyObject *j_locale_getDisplayName(j_locale *self, PyObject *args);

static PyMethodDef j_locale_methods[] = {
    DECLARE_METHOD(j_locale, getDefault, METH_NOARGS | METH_CLASS),
    DECLARE_METHOD(j_locale, setDefault, METH_O | METH_CLASS),
    DECLARE_METHOD(j_locale, getAvailableLocales, METH_NOARGS | METH_CLASS),
    DECLARE_METHOD(j_locale, getISOCountries, METH_NOARGS | METH_CLASS),
    DECLARE_METHOD(j_locale, getISOLanguages, METH_NOARGS | METH_CLASS),
    DECLARE_METHOD(j_locale, getLanguage, METH_NOARGS),
    DECLARE_METHOD(j_locale, getCountry, METH_NOARGS),
    DECLARE_METHOD(j_locale, getVariant, METH_NOARGS),
    DECLARE_METHOD(j_locale, getISO3Language, METH_NOARGS),
    DECLARE_METHOD(j_locale, getISO3Country, METH_NOARGS),
    DECLARE_METHOD(j_locale, getDisplayLanguage, METH_VARARGS),
    DECLARE_METHOD(j_locale, getDisplayCountry, METH_VARARGS),
    DECLARE_METHOD(j_locale, getDisplayVariant, METH_VARARGS),
    DECLARE_METHOD(j_locale, getDisplayName, METH_VARARGS),
    { NULL, NULL, 0, NULL }
};

DECLARE_TYPE(Locale, j_locale, Object, java::util::Locale, j_locale_init);


/* BitSet */

class j_bitset {
public:
    PyObject_HEAD
    java::util::BitSet *object;
};

static int j_bitset_init(j_bitset *self, PyObject *args, PyObject *kwds);
static PyObject *j_bitset_andSet(j_bitset *self, PyObject *arg);
static PyObject *j_bitset_andNot(j_bitset *self, PyObject *arg);
static PyObject *j_bitset_cardinality(j_bitset *self);
static PyObject *j_bitset_clear(j_bitset *self, PyObject *args);
static PyObject *j_bitset_flip(j_bitset *self, PyObject *args);
static PyObject *j_bitset_get(j_bitset *self, PyObject *args);
static PyObject *j_bitset_intersects(j_bitset *self, PyObject *arg);
static PyObject *j_bitset_isEmpty(j_bitset *self);
static PyObject *j_bitset_length(j_bitset *self);
static PyObject *j_bitset_nextClearBit(j_bitset *self, PyObject *arg);
static PyObject *j_bitset_nextSetBit(j_bitset *self, PyObject *arg);
static PyObject *j_bitset_orSet(j_bitset *self, PyObject *arg);
static PyObject *j_bitset_set(j_bitset *self, PyObject *args);
static PyObject *j_bitset_size(j_bitset *self);
static PyObject *j_bitset_xorSet(j_bitset *self, PyObject *arg);

static PyMethodDef j_bitset_methods[] = {
    DECLARE_METHOD(j_bitset, andSet, METH_O),
    DECLARE_METHOD(j_bitset, andNot, METH_O),
    DECLARE_METHOD(j_bitset, cardinality, METH_NOARGS),
    DECLARE_METHOD(j_bitset, clear, METH_VARARGS),
    DECLARE_METHOD(j_bitset, flip, METH_VARARGS),
    DECLARE_METHOD(j_bitset, get, METH_VARARGS),
    DECLARE_METHOD(j_bitset, intersects, METH_O),
    DECLARE_METHOD(j_bitset, isEmpty, METH_NOARGS),
    DECLARE_METHOD(j_bitset, length, METH_NOARGS),
    DECLARE_METHOD(j_bitset, nextClearBit, METH_O),
    DECLARE_METHOD(j_bitset, nextSetBit, METH_O),
    DECLARE_METHOD(j_bitset, orSet, METH_O),
    DECLARE_METHOD(j_bitset, set, METH_VARARGS),
    DECLARE_METHOD(j_bitset, size, METH_NOARGS),
    DECLARE_METHOD(j_bitset, xorSet, METH_O),
    { NULL, NULL, 0, NULL }
};

DECLARE_TYPE(BitSet, j_bitset, Object, java::util::BitSet, j_bitset_init);

/* Date */

class j_date {
public:
    PyObject_HEAD
    java::util::Date *object;
};

static int j_date_init(j_date *self, PyObject *args, PyObject *kwds);
static PyObject *j_date_after(j_date *self, PyObject *arg);
static PyObject *j_date_before(j_date *self, PyObject *arg);
static PyObject *j_date_compareTo(j_date *self, PyObject *arg);
static PyObject *j_date_getTime(j_date *self);
static PyObject *j_date_setTime(j_date *self, PyObject *arg);

static PyMethodDef j_date_methods[] = {
    DECLARE_METHOD(j_date, after, METH_O),
    DECLARE_METHOD(j_date, before, METH_O),
    DECLARE_METHOD(j_date, compareTo, METH_O),
    DECLARE_METHOD(j_date, getTime, METH_NOARGS),
    DECLARE_METHOD(j_date, setTime, METH_O),
    { NULL, NULL, 0, NULL }
};

DECLARE_TYPE(Date, j_date, Object, java::util::Date, j_date_init);

/* Calendar */

class j_calendar {
public:
    PyObject_HEAD
    java::util::Calendar *object;
};

static PyObject *j_calendar_getInstance(PyTypeObject *type, PyObject *args);
static PyObject *j_calendar_getAvailableLocales(PyTypeObject *type);
static PyObject *j_calendar_getTime(j_calendar *self);
static PyObject *j_calendar_setTime(j_calendar *self, PyObject *arg);
static PyObject *j_calendar_getTimeInMillis(j_calendar *self);
static PyObject *j_calendar_setTimeInMillis(j_calendar *self, PyObject *arg);
static PyObject *j_calendar_getTimeZone(j_calendar *self);
static PyObject *j_calendar_setTimeZone(j_calendar *self, PyObject *arg);
static PyObject *j_calendar_get(j_calendar *self, PyObject *arg);
static PyObject *j_calendar_set(j_calendar *self, PyObject *args);
static PyObject *j_calendar_clear(j_calendar *self, PyObject *args);
static PyObject *j_calendar_isSet(j_calendar *self, PyObject *arg);
static PyObject *j_calendar_before(j_calendar *self, PyObject *arg);
static PyObject *j_calendar_after(j_calendar *self, PyObject *arg);
static PyObject *j_calendar_add(j_calendar *self, PyObject *args);
static PyObject *j_calendar_roll(j_calendar *self, PyObject *args);
static PyObject *j_calendar_setLenient(j_calendar *self, PyObject *arg);
static PyObject *j_calendar_isLenient(j_calendar *self);
static PyObject *j_calendar_setFirstDayOfWeek(j_calendar *self, PyObject *arg);
static PyObject *j_calendar_getFirstDayOfWeek(j_calendar *self);
static PyObject *j_calendar_setMinimalDaysInFirstWeek(j_calendar *self,
                                                      PyObject *arg);
static PyObject *j_calendar_getMinimalDaysInFirstWeek(j_calendar *self);
static PyObject *j_calendar_getMinimum(j_calendar *self, PyObject *arg);
static PyObject *j_calendar_getMaximum(j_calendar *self, PyObject *arg);
static PyObject *j_calendar_getGreatestMinimum(j_calendar *self, PyObject *arg);
static PyObject *j_calendar_getLeastMaximum(j_calendar *self, PyObject *arg);
static PyObject *j_calendar_getActualMinimum(j_calendar *self, PyObject *arg);
static PyObject *j_calendar_getActualMaximum(j_calendar *self, PyObject *arg);
DECLARE_DOWNCAST(j_calendar, GregorianCalendar);

static PyMethodDef j_calendar_methods[] = {
    DECLARE_METHOD(j_calendar, getInstance, METH_VARARGS | METH_CLASS),
    DECLARE_METHOD(j_calendar, getAvailableLocales, METH_NOARGS | METH_CLASS),
    DECLARE_METHOD(j_calendar, getTime, METH_NOARGS),
    DECLARE_METHOD(j_calendar, setTime, METH_O),
    DECLARE_METHOD(j_calendar, getTimeInMillis, METH_NOARGS),
    DECLARE_METHOD(j_calendar, setTimeInMillis, METH_O),
    DECLARE_METHOD(j_calendar, getTimeZone, METH_NOARGS),
    DECLARE_METHOD(j_calendar, setTimeZone, METH_O),
    DECLARE_METHOD(j_calendar, get, METH_O),
    DECLARE_METHOD(j_calendar, set, METH_VARARGS),
    DECLARE_METHOD(j_calendar, clear, METH_VARARGS),
    DECLARE_METHOD(j_calendar, isSet, METH_O),
    DECLARE_METHOD(j_calendar, before, METH_O),
    DECLARE_METHOD(j_calendar, after, METH_O),
    DECLARE_METHOD(j_calendar, add, METH_VARARGS),
    DECLARE_METHOD(j_calendar, roll, METH_VARARGS),
    DECLARE_METHOD(j_calendar, setLenient, METH_O),
    DECLARE_METHOD(j_calendar, isLenient, METH_NOARGS),
    DECLARE_METHOD(j_calendar, setFirstDayOfWeek, METH_O),
    DECLARE_METHOD(j_calendar, getFirstDayOfWeek, METH_NOARGS),
    DECLARE_METHOD(j_calendar, setMinimalDaysInFirstWeek, METH_O),
    DECLARE_METHOD(j_calendar, getMinimalDaysInFirstWeek, METH_NOARGS),
    DECLARE_METHOD(j_calendar, getMinimum, METH_O),
    DECLARE_METHOD(j_calendar, getMaximum, METH_O),
    DECLARE_METHOD(j_calendar, getGreatestMinimum, METH_O),
    DECLARE_METHOD(j_calendar, getLeastMaximum, METH_O),
    DECLARE_METHOD(j_calendar, getActualMinimum, METH_O),
    DECLARE_METHOD(j_calendar, getActualMaximum, METH_O),
    DECLARE_DOWNCAST_METHODS(j_calendar, GregorianCalendar),
    { NULL, NULL, 0, NULL }
};

DECLARE_TYPE(Calendar, j_calendar, Object, java::util::Calendar, abstract_init);

/* GregorianCalendar */

class j_gregoriancalendar {
public:
    PyObject_HEAD
    java::util::GregorianCalendar *object;
};

static int j_gregoriancalendar_init(j_gregoriancalendar *self, PyObject *args, PyObject *kwds);
static PyObject *j_gregoriancalendar_getGregorianChange(j_gregoriancalendar *self);
static PyObject *j_gregoriancalendar_setGregorianChange(j_gregoriancalendar *self, PyObject *arg);
static PyObject *j_gregoriancalendar_isLeapYear(j_gregoriancalendar *self, PyObject *arg);

static PyMethodDef j_gregoriancalendar_methods[] = {
    DECLARE_METHOD(j_gregoriancalendar, getGregorianChange, METH_NOARGS),
    DECLARE_METHOD(j_gregoriancalendar, setGregorianChange, METH_O),
    DECLARE_METHOD(j_gregoriancalendar, isLeapYear, METH_O),
    { NULL, NULL, 0, NULL }
};

DECLARE_TYPE(GregorianCalendar, j_gregoriancalendar, Calendar,
             java::util::GregorianCalendar, j_gregoriancalendar_init);

/* Format */

class j_format {
public:
    PyObject_HEAD
    java::text::Format *object;
};

static PyObject *j_format_format(j_format *self, PyObject *arg);

static PyMethodDef j_format_methods[] = {
    DECLARE_METHOD(j_format, format, METH_O),
    { NULL, NULL, 0, NULL }
};

DECLARE_TYPE(Format, j_format, Object, java::text::Format, abstract_init);

/* NumberFormat */

class j_numberformat {
public:
    PyObject_HEAD
    java::text::NumberFormat *object;
};

static PyObject *j_numberformat_getAvailableLocales(PyTypeObject *type);
static PyObject *j_numberformat_getCurrencyInstance(PyTypeObject *type,
                                                    PyObject *args);
static PyObject *j_numberformat_getInstance(PyTypeObject *type, PyObject *args);
static PyObject *j_numberformat_getNumberInstance(PyTypeObject *type,
                                                  PyObject *args);
static PyObject *j_numberformat_getIntegerInstance(PyTypeObject *type,
                                                   PyObject *args);
static PyObject *j_numberformat_getPercentInstance(PyTypeObject *type,
                                                   PyObject *args);
static PyObject *j_numberformat_format(j_numberformat *self, PyObject *arg);
static PyObject *j_numberformat_getMaximumFractionDigits(j_numberformat *self);
static PyObject *j_numberformat_getMaximumIntegerDigits(j_numberformat *self);
static PyObject *j_numberformat_getMinimumFractionDigits(j_numberformat *self);
static PyObject *j_numberformat_getMinimumIntegerDigits(j_numberformat *self);
static PyObject *j_numberformat_isGroupingUsed(j_numberformat *self);
static PyObject *j_numberformat_isParseIntegerOnly(j_numberformat *self);
static PyObject *j_numberformat_setGroupingUsed(j_numberformat *self, PyObject *arg);
static PyObject *j_numberformat_setMaximumFractionDigits(j_numberformat *self, PyObject *arg);
static PyObject *j_numberformat_setMaximumIntegerDigits(j_numberformat *self, PyObject *arg);
static PyObject *j_numberformat_setMinimumFractionDigits(j_numberformat *self, PyObject *arg);
static PyObject *j_numberformat_setMinimumIntegerDigits(j_numberformat *self, PyObject *arg);
static PyObject *j_numberformat_setParseIntegerOnly(j_numberformat *self, PyObject *arg);

static PyMethodDef j_numberformat_methods[] = {
    DECLARE_METHOD(j_numberformat, getAvailableLocales, METH_NOARGS | METH_CLASS),
    DECLARE_METHOD(j_numberformat, getCurrencyInstance, METH_VARARGS | METH_CLASS),
    DECLARE_METHOD(j_numberformat, getNumberInstance, METH_VARARGS | METH_CLASS),
    DECLARE_METHOD(j_numberformat, getIntegerInstance, METH_VARARGS | METH_CLASS),
    DECLARE_METHOD(j_numberformat, getPercentInstance, METH_VARARGS | METH_CLASS),
    DECLARE_METHOD(j_numberformat, format, METH_O),
    DECLARE_METHOD(j_numberformat, getMaximumFractionDigits, METH_NOARGS),
    DECLARE_METHOD(j_numberformat, getMaximumIntegerDigits, METH_NOARGS),
    DECLARE_METHOD(j_numberformat, getMinimumFractionDigits, METH_NOARGS),
    DECLARE_METHOD(j_numberformat, getMinimumIntegerDigits, METH_NOARGS),
    DECLARE_METHOD(j_numberformat, isGroupingUsed, METH_NOARGS),
    DECLARE_METHOD(j_numberformat, isParseIntegerOnly, METH_NOARGS),
    DECLARE_METHOD(j_numberformat, setGroupingUsed, METH_O),
    DECLARE_METHOD(j_numberformat, setMaximumFractionDigits, METH_O),
    DECLARE_METHOD(j_numberformat, setMaximumIntegerDigits, METH_O),
    DECLARE_METHOD(j_numberformat, setMinimumFractionDigits, METH_O),
    DECLARE_METHOD(j_numberformat, setMinimumIntegerDigits, METH_O),
    DECLARE_METHOD(j_numberformat, setParseIntegerOnly, METH_O),
    { NULL, NULL, 0, NULL }
};

DECLARE_TYPE(NumberFormat, j_numberformat, Format, java::text::NumberFormat,
             abstract_init);

/* TimeZone */

class j_timezone {
public:
    PyObject_HEAD
    java::util::TimeZone *object;
};

static PyObject *j_timezone_getAvailableIDs(PyTypeObject *type, PyObject *args);
static PyObject *j_timezone_getDefault(PyTypeObject *type);
static PyObject *j_timezone_setDefault(PyTypeObject *type, PyObject *arg);
static PyObject *j_timezone_getTimeZone(PyTypeObject *type, PyObject *arg);
static PyObject *j_timezone_getDisplayName(j_timezone *self, PyObject *args);
static PyObject *j_timezone_getDSTSavings(j_timezone *self);
static PyObject *j_timezone_getID(j_timezone *self);
static PyObject *j_timezone_setID(j_timezone *self, PyObject *arg);
static PyObject *j_timezone_getOffset(j_timezone *self, PyObject *args);
static PyObject *j_timezone_getRawOffset(j_timezone *self);
static PyObject *j_timezone_setRawOffset(j_timezone *self, PyObject *arg);
static PyObject *j_timezone_hasSameRules(j_timezone *self, PyObject *arg);
static PyObject *j_timezone_inDaylightTime(j_timezone *self, PyObject *arg);
static PyObject *j_timezone_useDaylightTime(j_timezone *self);

static PyMethodDef j_timezone_methods[] = {
    DECLARE_METHOD(j_timezone, getAvailableIDs, METH_VARARGS | METH_CLASS),
    DECLARE_METHOD(j_timezone, getDefault, METH_NOARGS | METH_CLASS),
    DECLARE_METHOD(j_timezone, setDefault, METH_O | METH_CLASS),
    DECLARE_METHOD(j_timezone, getTimeZone, METH_O | METH_CLASS),
    DECLARE_METHOD(j_timezone, getDisplayName, METH_VARARGS),
    DECLARE_METHOD(j_timezone, getDSTSavings, METH_NOARGS),
    DECLARE_METHOD(j_timezone, getID, METH_NOARGS),
    DECLARE_METHOD(j_timezone, setID, METH_O),
    DECLARE_METHOD(j_timezone, getOffset, METH_VARARGS),
    DECLARE_METHOD(j_timezone, getRawOffset, METH_NOARGS),
    DECLARE_METHOD(j_timezone, setRawOffset, METH_O),
    DECLARE_METHOD(j_timezone, hasSameRules, METH_O),
    DECLARE_METHOD(j_timezone, inDaylightTime, METH_O),
    DECLARE_METHOD(j_timezone, useDaylightTime, METH_NOARGS),
    { NULL, NULL, 0, NULL }
};

DECLARE_TYPE(TimeZone, j_timezone, Object, java::util::TimeZone, abstract_init);

/* DateFormat */

class j_dateformat {
public:
    PyObject_HEAD
    java::text::DateFormat *object;
};

static PyObject *j_dateformat_getAvailableLocales(PyTypeObject *type);
static PyObject *j_dateformat_getDateInstance(PyTypeObject *type,
                                              PyObject *args);
static PyObject *j_dateformat_getTimeInstance(PyTypeObject *type,
                                              PyObject *args);
static PyObject *j_dateformat_getDateTimeInstance(PyTypeObject *type,
                                                  PyObject *args);
static PyObject *j_dateformat_getInstance(PyTypeObject *type);
static PyObject *j_dateformat_getNumberFormat(j_dateformat *self);
static PyObject *j_dateformat_setNumberFormat(j_dateformat *self, PyObject *arg);
static PyObject *j_dateformat_getCalendar(j_dateformat *self);
static PyObject *j_dateformat_setCalendar(j_dateformat *self, PyObject *arg);
static PyObject *j_dateformat_isLenient(j_dateformat *self);
static PyObject *j_dateformat_setLenient(j_dateformat *self, PyObject *arg);
static PyObject *j_dateformat_format(j_dateformat *self, PyObject *arg);
static PyObject *j_dateformat_parse(j_dateformat *self, PyObject *arg);

static PyMethodDef j_dateformat_methods[] = {
    DECLARE_METHOD(j_dateformat, getAvailableLocales, METH_NOARGS | METH_CLASS),
    DECLARE_METHOD(j_dateformat, getDateInstance, METH_VARARGS | METH_CLASS),
    DECLARE_METHOD(j_dateformat, getTimeInstance, METH_VARARGS | METH_CLASS),
    DECLARE_METHOD(j_dateformat, getDateTimeInstance, METH_VARARGS | METH_CLASS),
    DECLARE_METHOD(j_dateformat, getInstance, METH_NOARGS | METH_CLASS),
    DECLARE_METHOD(j_dateformat, getNumberFormat, METH_NOARGS),
    DECLARE_METHOD(j_dateformat, setNumberFormat, METH_O),
    DECLARE_METHOD(j_dateformat, getCalendar, METH_NOARGS),
    DECLARE_METHOD(j_dateformat, setCalendar, METH_O),
    DECLARE_METHOD(j_dateformat, isLenient, METH_NOARGS),
    DECLARE_METHOD(j_dateformat, setLenient, METH_O),
    DECLARE_METHOD(j_dateformat, format, METH_O),
    DECLARE_METHOD(j_dateformat, parse, METH_O),
    { NULL, NULL, 0, NULL }
};

DECLARE_TYPE(DateFormat, j_dateformat, Format, java::text::DateFormat,
             abstract_init);

/* DecimalFormat */

class j_decimalformat {
public:
    PyObject_HEAD
    java::text::DecimalFormat *object;
};

static int j_decimalformat_init(j_decimalformat *self, PyObject *args, PyObject *kwds);
static PyObject *j_decimalformat_applyLocalizedPattern(j_decimalformat *self, PyObject *arg);
static PyObject *j_decimalformat_applyPattern(j_decimalformat *self, PyObject *arg);
static PyObject *j_decimalformat_getGroupingSize(j_decimalformat *self);
static PyObject *j_decimalformat_setGroupingSize(j_decimalformat *self, PyObject *arg);
static PyObject *j_decimalformat_getMultiplier(j_decimalformat *self);
static PyObject *j_decimalformat_setMultiplier(j_decimalformat *self, PyObject *arg);
static PyObject *j_decimalformat_getNegativePrefix(j_decimalformat *self);
static PyObject *j_decimalformat_getNegativeSuffix(j_decimalformat *self);
static PyObject *j_decimalformat_setNegativePrefix(j_decimalformat *self, PyObject *arg);
static PyObject *j_decimalformat_setNegativeSuffix(j_decimalformat *self, PyObject *arg);
static PyObject *j_decimalformat_isDecimalSeparatorAlwaysShown(j_decimalformat *self);
static PyObject *j_decimalformat_setDecimalSeparatorAlwaysShown(j_decimalformat *self, PyObject *arg);
static PyObject *j_decimalformat_toLocalizedPattern(j_decimalformat *self);
static PyObject *j_decimalformat_toPattern(j_decimalformat *self);

static PyMethodDef j_decimalformat_methods[] = {
    DECLARE_METHOD(j_decimalformat, applyLocalizedPattern, METH_O),
    DECLARE_METHOD(j_decimalformat, applyPattern, METH_O),
    DECLARE_METHOD(j_decimalformat, getGroupingSize, METH_NOARGS),
    DECLARE_METHOD(j_decimalformat, setGroupingSize, METH_O),
    DECLARE_METHOD(j_decimalformat, getMultiplier, METH_NOARGS),
    DECLARE_METHOD(j_decimalformat, setMultiplier, METH_O),
    DECLARE_METHOD(j_decimalformat, getNegativePrefix, METH_NOARGS),
    DECLARE_METHOD(j_decimalformat, getNegativeSuffix, METH_NOARGS),
    DECLARE_METHOD(j_decimalformat, setNegativePrefix, METH_O),
    DECLARE_METHOD(j_decimalformat, setNegativeSuffix, METH_O),
    DECLARE_METHOD(j_decimalformat, isDecimalSeparatorAlwaysShown, METH_NOARGS),
    DECLARE_METHOD(j_decimalformat, setDecimalSeparatorAlwaysShown, METH_O),
    DECLARE_METHOD(j_decimalformat, toLocalizedPattern, METH_NOARGS),
    DECLARE_METHOD(j_decimalformat, toPattern, METH_NOARGS),
    { NULL, NULL, 0, NULL }
};

DECLARE_TYPE(DecimalFormat, j_decimalformat, NumberFormat,
             java::text::DecimalFormat, j_decimalformat_init);

/* SimpleDateFormat */

class j_simpledateformat {
public:
    PyObject_HEAD
    java::text::SimpleDateFormat *object;
};

static int j_simpledateformat_init(j_simpledateformat *self, PyObject *args, PyObject *kwds);
static PyObject *j_simpledateformat_applyLocalizedPattern(j_simpledateformat *self, PyObject *arg);
static PyObject *j_simpledateformat_applyPattern(j_simpledateformat *self, PyObject *arg);
static PyObject *j_simpledateformat_get2DigitYearStart(j_simpledateformat *self);
static PyObject *j_simpledateformat_toLocalizedPattern(j_simpledateformat *self);
static PyObject *j_simpledateformat_toPattern(j_simpledateformat *self);

static PyMethodDef j_simpledateformat_methods[] = {
    DECLARE_METHOD(j_simpledateformat, applyLocalizedPattern, METH_O),
    DECLARE_METHOD(j_simpledateformat, applyPattern, METH_O),
    DECLARE_METHOD(j_simpledateformat, get2DigitYearStart, METH_NOARGS),
    DECLARE_METHOD(j_simpledateformat, toLocalizedPattern, METH_NOARGS),
    DECLARE_METHOD(j_simpledateformat, toPattern, METH_NOARGS),
    { NULL, NULL, 0, NULL }
};

DECLARE_TYPE(SimpleDateFormat, j_simpledateformat, DateFormat,
             java::text::SimpleDateFormat, j_simpledateformat_init);

/* Charset */

class j_charset {
public:
    PyObject_HEAD
    JArray<jchar> *object;
};

static int j_charset_init(j_charset *self, PyObject *args, PyObject *kwds);

static PyMethodDef j_charset_methods[] = {
    { NULL, NULL, 0, NULL }
};

DECLARE_TYPE(Charset, j_charset, Object, JArray<jchar>, j_charset_init);

static int j_charset_length(j_charset *self)
{
    return JvGetArrayLength(self->object);
}

static PyObject *j_charset_getitem(j_charset *self, int i)
{
    int len = JvGetArrayLength(self->object);

    if (i < 0)
        i += len;

    if (i >= 0 && i < len)
    {
        Py_UNICODE u = elements(self->object)[i];
        return PyUnicode_FromUnicode(&u, 1);
    }
    else
    {
        PyObject *index = PyInt_FromLong(i);

        PyErr_SetObject(PyExc_IndexError, index);
        Py_DECREF(index);
        return NULL;
    }
}

static int j_charset_setitem(j_charset *self, int i, PyObject *obj)
{
    if (PyUnicode_Check(obj))
    {
        if (PyUnicode_GET_SIZE(obj) != 1)
        {
            PyErr_SetObject(PyExc_ValueError, obj);
            return -1;
        }

        int len = JvGetArrayLength(self->object);

        if (i < 0)
            i += len;

        if (i >= 0 && i < len)
        {
            Py_UNICODE *u = PyUnicode_AS_UNICODE(obj);
            elements(self->object)[i] = u[0];
            return 0;
        }
        else
        {
            PyObject *index = PyInt_FromLong(i);

            PyErr_SetObject(PyExc_IndexError, index);
            Py_DECREF(index);
            return -1;
        }
    }
    else
    {
        PyErr_SetObject(PyExc_TypeError, obj);
        return -1;
    }
}

static PySequenceMethods j_charset_as_sequence = {
    (inquiry)j_charset_length,              /* sq_length */
    (binaryfunc)NULL,                       /* sq_concat */
    (intargfunc)NULL,                       /* sq_repeat */
    (intargfunc)j_charset_getitem,          /* sq_item   */
    (intintargfunc)NULL,                    /* sq_slice  */
    (intobjargproc)j_charset_setitem,       /* sq_ass_item */
    (intintobjargproc)NULL,                 /* sq_ass_slice */
    (objobjproc)NULL,                       /* sq_contains */
    (binaryfunc)NULL,                       /* sq_inplace_concat */
    (intargfunc)NULL,                       /* sq_inplace_repeat */
};


int check_Charset(PyObject *arg)
{
    return PyString_Check(arg) || PyUnicode_Check(arg);
}

JArray<jchar> *make_Charset(PyObject *arg)
{
    jstring string = p2j(arg);
    
    if (!string && PyErr_Occurred())
        return NULL;

    return string->toCharArray();
}

/* Object */

static void j_object_dealloc(j_object *self)
{
    if (self->object)
    {
        unrefObject(self->object);
        self->object = NULL;
    }

    self->ob_type->tp_free((PyObject *) self);
}

static PyObject *j_object_new(PyTypeObject *type,
                              PyObject *args, PyObject *kwds)
{
    j_object *self = (j_object *) type->tp_alloc(type, 0);

    if (self)
        self->object = NULL;

    return (PyObject *) self;
}

static int j_object_init(j_object *self, PyObject *args, PyObject *kwds)
{
    self->object = new java::lang::Object();

    if (self->object)
        refObject(self->object);

    return 0;
}

static int j_object_hash(j_object *self)
{
    return self->object->hashCode();
}

static PyObject *j_object_richcmp(j_object *self, PyObject *arg, int op)
{
    jboolean b = 0;

    switch (op) {
      case Py_EQ:
      case Py_NE:
        if (PyObject_TypeCheck(arg, &ObjectType))
            OBJ_CALL(b = self->object->equals(((j_object *) arg)->object));
        if (op == Py_EQ)
            Py_RETURN_BOOL(b);
        Py_RETURN_BOOL(!b);
      case Py_LT:
        PyErr_SetString(PyExc_NotImplementedError, "<");
        return NULL;
      case Py_LE:
        PyErr_SetString(PyExc_NotImplementedError, "<=");
        return NULL;
      case Py_GT:
        PyErr_SetString(PyExc_NotImplementedError, ">");
        return NULL;
      case Py_GE:
        PyErr_SetString(PyExc_NotImplementedError, ">=");
        return NULL;
    }

    return NULL;
}

static PyObject *j_object_str(j_object *self)
{
    jstring s;

    if (self->object)
    {
        OBJ_CALL(s = self->object->toString());
        return j2p(s);
    }

    return PyString_FromString("<null>");
}

static PyObject *j_object_repr(j_object *self)
{
    PyObject *name = PyObject_GetAttrString((PyObject *) self->ob_type,
                                            "__name__");
    PyObject *str = j_object_str(self);
#if PY_VERSION_HEX < 0x02040000
    PyObject *args = PyTuple_New(2);
    PyTuple_SET_ITEM(args, 0, name);
    PyTuple_SET_ITEM(args, 1, str);
#else
    PyObject *args = PyTuple_Pack(2, name, str);
#endif
    PyObject *format = PyString_FromString("<%s: %s>");
    PyObject *repr = PyString_Format(format, args);

    Py_DECREF(name);
    Py_DECREF(str);
    Py_DECREF(args);
    Py_DECREF(format);

    return repr;
}

static PyObject *j_object_getClass(j_object *self)
{
    jclass cls;

    OBJ_CALL(cls = self->object->getClass());
    return wrap_Class(cls);
}

static PyObject *j_object_equals(j_object *self, PyObject *arg)
{
    jboolean b = 0;

    if (PyObject_TypeCheck(arg, &ObjectType))
        OBJ_CALL(b = self->object->equals(((j_object *) arg)->object));

    Py_RETURN_BOOL(b);
}

static PyObject *j_object_hashCode(j_object *self)
{
    return PyInt_FromLong(self->object->hashCode());
}

static PyObject *j_object_notify(j_object *self)
{
    SYNC_OBJ_CALL(self->object, self->object->notify());
    Py_RETURN_NONE;
}

static PyObject *j_object_notifyAll(j_object *self)
{
    SYNC_OBJ_CALL(self->object, self->object->notifyAll());
    Py_RETURN_NONE;
}

static PyObject *j_object_wait(j_object *self, PyObject *args)
{
    switch (PyTuple_GET_SIZE(args)) {
      case 0:
      {
          SYNC_OBJ_CALL(self->object, self->object->wait());
          Py_RETURN_NONE;
      }
      case 1:
      {
          long long timeout;

          if (!PyArg_ParseTuple(args, "L", &timeout))
              return NULL;

          SYNC_OBJ_CALL(self->object, self->object->wait(timeout));
          Py_RETURN_NONE;
      }
      case 2:
      {
          long long timeout;
          int nanos;

          if (!PyArg_ParseTuple(args, "Li", &timeout, &nanos))
              return NULL;

          SYNC_OBJ_CALL(self->object, self->object->wait(timeout, nanos));
          Py_RETURN_NONE;
      }
    }

    return PyErr_SetArgsError((PyObject *) self, "wait", args);
}


/* Throwable */

static int j_throwable_init(j_throwable *self, PyObject *args, PyObject *kwds)
{
    java::lang::Throwable *cause;
    jstring message;

    switch (PyTuple_Size(args)) {
      case 0:
        INT_CALL(self->object = new java::lang::Throwable());
        break;
      case 1:
        if (!parseArgs(args, "J", &java::lang::Throwable::class$, &cause))
        {
            INT_CALL(self->object = new java::lang::Throwable(cause));
            break;
        }
        else if (!parseArgs(args, "s", &message))
        {
            INT_CALL(self->object = new java::lang::Throwable(message));
            break;
        }
        PyErr_SetArgsError((PyObject *) self, "__init__", args);
        return -1;
      case 2:
        if (!parseArgs(args, "sJ", &java::lang::Throwable::class$,
                       &message, &cause))
        {
            INT_CALL(self->object = new java::lang::Throwable(message, cause));
            break;
        }
        PyErr_SetArgsError((PyObject *) self, "__init__", args);
        return -1;
      default:
        PyErr_SetArgsError((PyObject *) self, "__init__", args);
        return -1;
    }
        
    if (self->object)
    {
        refObject(self->object);
        return 0;
    }

    return -1;
}

static PyObject *j_throwable_getCause(j_throwable *self)
{
    java::lang::Throwable *cause;

    OBJ_CALL(cause = self->object->getCause());
    return wrap_Throwable(cause);
}

static PyObject *j_throwable_getLocalizedMessage(j_throwable *self)
{
    jstring str;

    OBJ_CALL(str = self->object->getLocalizedMessage());
    return j2p(str);
}

static PyObject *j_throwable_getMessage(j_throwable *self)
{
    jstring str;

    OBJ_CALL(str = self->object->getMessage());
    return j2p(str);
}

static PyObject *j_throwable_printStackTrace(j_throwable *self)
{
    OBJ_CALL(self->object->printStackTrace());
    Py_RETURN_NONE;
}


/* Class */

static PyObject *j_class_getName(j_class *self)
{
    jstring str;
    OBJ_CALL(str = self->object->getName());
    return j2p(str);
}

static PyObject *j_class_isArray(j_class *self)
{
    jboolean b;

    OBJ_CALL(b = self->object->isArray());
    Py_RETURN_BOOL(b);
}

static PyObject *j_class_isInterface(j_class *self)
{
    jboolean b;

    OBJ_CALL(b = self->object->isInterface());
    Py_RETURN_BOOL(b);
}

static PyObject *j_class_isPrimitive(j_class *self)
{
    jboolean b;

    OBJ_CALL(b = self->object->isPrimitive());
    Py_RETURN_BOOL(b);
}

static PyObject *j_class_isAssignableFrom(j_class *self, PyObject *arg)
{
    jclass cls;

    if (!parseArg(arg, "J", &java::lang::Class::class$, &cls))
    {
        jboolean b;

        OBJ_CALL(b = self->object->isAssignableFrom(cls));
        Py_RETURN_BOOL(b);
    }

    return PyErr_SetArgsError((PyObject *) self, "isAssignableFrom", arg);
}

static PyObject *j_class_isInstance(j_class *self, PyObject *arg)
{
    jclass cls;

    if (PyObject_TypeCheck(arg, &ObjectType))
    {
        jboolean b;

        OBJ_CALL(b = self->object->isInstance(((j_object *) arg)->object));
        Py_RETURN_BOOL(b);
    }
    
    Py_RETURN_FALSE;
}

static PyObject *j_class_getClassLoader(j_class *self)
{
    java::lang::ClassLoader *loader;

    OBJ_CALL(loader = self->object->getClassLoader());
    return wrap_ClassLoader(loader);
}

static PyObject *j_class_forName(PyTypeObject *type, PyObject *args)
{
    jstring name;
    jclass cls;

    switch (PyTuple_GET_SIZE(args)) {
      case 1:
        if (!parseArgs(args, "s", &name))
        {
            OBJ_CALL(cls = java::lang::Class::forName(name));
            return wrap_Class(cls);
        }
        break;
      case 3:
        jboolean initialize;
        java::lang::ClassLoader *loader;
        if (!parseArgs(args, "sbJ", &java::lang::ClassLoader::class$,
                       &name, &initialize, &loader))
        {
            OBJ_CALL(cls = java::lang::Class::forName(name, initialize,
                                                      loader));
            return wrap_Class(cls);
        }            
            
        break;
    }

    return PyErr_SetArgsError(type, "forName", args);
}


/* ClassLoader */

static PyObject *j_classloader_loadClass(j_classloader *self, PyObject *arg)
{
    jstring name;

    if (!parseArg(arg, "s", &name))
    {
        jclass cls;

        OBJ_CALL(cls = self->object->loadClass(name));
        return wrap_Class(cls);
    }

    return PyErr_SetArgsError((PyObject *) self, "forName", arg);
}

static PyObject *j_classloader_getSystemClassLoader(PyTypeObject *type)
{
    java::lang::ClassLoader *loader;

    OBJ_CALL(loader = java::lang::ClassLoader::getSystemClassLoader());
    return wrap_ClassLoader(loader);
}


/* Comparable */

static int j_comparable_init(j_comparable *self,
                             PyObject *args, PyObject *kwds)
{
    java::lang::Comparable *comparable;

    if (!parseArgs(args, "P", &java::lang::Comparable::class$, check_Comparable,
                   &comparable, make_Comparable))
    {
        if (comparable)
        {
            self->object = comparable;
            refObject(self->object);
            return 0;
        }
    }

    PyErr_SetArgsError((PyObject *) self, "__init__", args);
    return -1;
}

static PyObject *j_comparable_compareTo(j_comparable *self, PyObject *arg)
{
    java::lang::Comparable *comparable;
    jint cmp;

    if (!parseArg(arg, "P", &java::lang::Comparable::class$, check_Comparable,
                  &comparable, make_Comparable))
    {
        OBJ_CALL(cmp = self->object->compareTo(comparable));
        return PyInt_FromLong(cmp);
    }
    
    return PyErr_SetArgsError((PyObject *) self, "compareTo", arg);
}


/* Runnable */

static int j_runnable_init(j_runnable *self, PyObject *args, PyObject *kwds)
{
    java::lang::Runnable *runnable;

    if (!parseArgs(args, "P", &java::lang::Runnable::class$, check_Runnable,
                   &runnable, make_Runnable))
    {
        if (runnable)
        {
            self->object = runnable;
            refObject(self->object);
            return 0;
        }
    }

    PyErr_SetArgsError((PyObject *) self, "__init__", args);
    return -1;
}

static PyObject *j_runnable_run(j_runnable *self)
{
    OBJ_CALL(self->object->run());
    Py_RETURN_NONE;
}


/* Thread */

static int j_thread_init(j_thread *self, PyObject *args, PyObject *kwds)
{
    java::lang::Runnable *runnable;

    switch (PyTuple_GET_SIZE(args)) {
      case 1:
        if (!parseArgs(args, "P",
                       &java::lang::Runnable::class$, check_Runnable,
                       &runnable, make_Runnable))
        {
            INT_CALL(self->object = new java::lang::Thread(runnable));
            break;
        }
        PyErr_SetArgsError((PyObject *) self, "__init__", args);
        return -1;
      case 2:
        jstring name;
        if (!parseArgs(args, "Ps",
                       &java::lang::Runnable::class$, check_Runnable,
                       &runnable, make_Runnable, &name))
        {
            INT_CALL(self->object = new java::lang::Thread(runnable, name));
            break;
        }
        PyErr_SetArgsError((PyObject *) self, "__init__", args);
        return -1;
        break;
    }

    if (self->object)
    {
        refObject(self->object);
        return 0;
    }
    
    return -1;
}

static PyObject *j_thread_getName(j_thread *self)
{
    jstring str;

    OBJ_CALL(str = self->object->getName());
    return j2p(str);
}

static PyObject *j_thread_setName(j_thread *self, PyObject *arg)
{
    jstring name;

    if (!parseArg(arg, "s", &name))
    {
        OBJ_CALL(self->object->setName(name));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError((PyObject *) self, "setName", arg);
}

static PyObject *j_thread_isAlive(j_thread *self)
{
    jboolean b;

    OBJ_CALL(b = self->object->isAlive());
    Py_RETURN_BOOL(b);
}

static PyObject *j_thread_isDaemon(j_thread *self)
{
    jboolean b;

    OBJ_CALL(b = self->object->isDaemon());
    Py_RETURN_BOOL(b);
}

static PyObject *j_thread_setDaemon(j_thread *self, PyObject *arg)
{
    jboolean b;

    if (!parseArg(arg, "b", &b))
    {
        OBJ_CALL(self->object->setDaemon(b));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError((PyObject *) self, "setDaemon", arg);
}

static PyObject *j_thread_isInterrupted(j_thread *self)
{
    jboolean b;

    OBJ_CALL(b = self->object->isInterrupted());
    Py_RETURN_BOOL(b);
}

static PyObject *j_thread_start(j_thread *self)
{
    OBJ_CALL(self->object->start());
    Py_RETURN_NONE;
}

static PyObject *j_thread_join(j_thread *self, PyObject *args)
{
    switch (PyTuple_GET_SIZE(args)) {
      case 0:
      {
          OBJ_CALL(self->object->join());
          Py_RETURN_NONE;
      }
      case 1:
      {
          long long timeout;

          if (!PyArg_ParseTuple(args, "L", &timeout))
              return NULL;

          OBJ_CALL(self->object->join(timeout));
          Py_RETURN_NONE;
      }
      case 2:
      {
          long long timeout;
          int nanos;

          if (!PyArg_ParseTuple(args, "Li", &timeout, &nanos))
              return NULL;

          OBJ_CALL(self->object->join(timeout, nanos));
          Py_RETURN_NONE;
      }
    }

    return PyErr_SetArgsError((PyObject *) self, "join", args);
}


/* System */

static PyObject *j_system_currentTimeMillis(PyTypeObject *type)
{
    jlong millis;

    OBJ_CALL(millis = java::lang::System::currentTimeMillis());
    return PyLong_FromLongLong(millis);
}

static PyObject *j_system_gc(PyTypeObject *type)
{
    OBJ_CALL(java::lang::System::gc());
    Py_RETURN_NONE;
}

static PyObject *j_system_runFinalization(PyTypeObject *type)
{
    OBJ_CALL(java::lang::System::runFinalization());
    Py_RETURN_NONE;
}

static PyObject *j_system_getProperty(PyTypeObject *type, PyObject *args)
{
    jstring value, name, deflt;

    switch (PyTuple_GET_SIZE(args)) {
      case 1:
        if (!parseArgs(args, "s", &name))
        {
            OBJ_CALL(value = java::lang::System::getProperty(name));
            return j2p(value);
        }
        break;
      case 2:
        if (!parseArgs(args, "ss", &name, &deflt))
        {
            OBJ_CALL(value = java::lang::System::getProperty(name, deflt));
            return j2p(value);
        }
        break;
    }

    return PyErr_SetArgsError(type, "getProperty", args);
}

static PyObject *j_system_setProperty(PyTypeObject *type, PyObject *args)
{
    jstring name, value;

    if (!parseArgs(args, "ss", &name, &value))
    {
        OBJ_CALL(value = java::lang::System::setProperty(name, value));
        return j2p(value);
    }

    return PyErr_SetArgsError(type, "setProperty", args);
}

static PyObject *j_system_getProperties(PyTypeObject *type)
{
    java::util::Properties *properties;

    OBJ_CALL(properties = java::lang::System::getProperties());
    return wrap_Properties(properties);
}

static PyObject *j_system_load(PyTypeObject *type, PyObject *arg)
{
    jstring filename;

    if (!parseArg(arg, "s", &filename))
    {
        OBJ_CALL(java::lang::System::load(filename));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError(type, "load", arg);
}

static PyObject *j_system_loadLibrary(PyTypeObject *type, PyObject *arg)
{
    jstring libname;

    if (!parseArg(arg, "s", &libname))
    {
        OBJ_CALL(java::lang::System::loadLibrary(libname));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError(type, "loadLibrary", arg);
}

static PyObject *j_system_mapLibraryName(PyTypeObject *type, PyObject *arg)
{
    jstring libname;

    if (!parseArg(arg, "s", &libname))
    {
        OBJ_CALL(libname = java::lang::System::mapLibraryName(libname));
        return j2p(libname);
    }

    return PyErr_SetArgsError(type, "mapLibraryName", arg);
}

static PyObject *j_system_identityHashCode(PyTypeObject *type, PyObject *arg)
{
    jint code;

    if (PyObject_TypeCheck(arg, &ObjectType))
    {
        OBJ_CALL(code = java::lang::System::identityHashCode(((j_object *) arg)->object));
        return PyInt_FromLong(code);
    }

    return PyErr_SetArgsError(type, "identityHashCode", arg);
}


/* Properties */

static int j_properties_init(j_properties *self,
                             PyObject *args, PyObject *kwds)
{
    java::util::Properties *properties;

    switch (PyTuple_GET_SIZE(args)) {
      case 0:
        INT_CALL(properties = new java::util::Properties());
        self->object = properties;
        break;
      default:
        PyErr_SetArgsError((PyObject *) self, "__init__", args);
        return -1;
    }

    if (self->object)
    {
        refObject(self->object);
        return 0;
    }
    
    return -1;
}

static PyObject *j_properties_getProperty(j_properties *self, PyObject *args)
{
    jstring value, name, deflt;

    switch (PyTuple_GET_SIZE(args)) {
      case 1:
        if (!parseArgs(args, "s", &name))
        {
            OBJ_CALL(value = self->object->getProperty(name));
            return j2p(value);
        }
        break;
      case 2:
        if (!parseArgs(args, "ss", &name, &deflt))
        {
            OBJ_CALL(value = self->object->getProperty(name, deflt));
            return j2p(value);
        }
        break;
    }

    return PyErr_SetArgsError((PyObject *) self, "getProperty", args);
}

static PyObject *j_properties_setProperty(j_properties *self, PyObject *args)
{
    jstring name, strValue;
    jobject value;

    if (!parseArgs(args, "ss", &name, &strValue))
    {
        OBJ_CALL(value = self->object->setProperty(name, strValue));
        if (java::lang::String::class$.isInstance(value))
            return j2p((jstring) value);
        return wrap_Object(value);
    }

    return PyErr_SetArgsError((PyObject *) self, "setProperty", args);
}

static PyObject *j_properties_propertyNames(j_properties *self)
{
    java::util::Enumeration *names;

    OBJ_CALL(names = self->object->propertyNames());
    return wrap_StringEnumeration(names);
}

static PyObject *j_properties___contains__(j_properties *self, PyObject *arg)
{
    jstring key;
    jboolean b;

    if (!parseArg(arg, "s", &key))
    {
        OBJ_CALL(b = self->object->containsKey(key));
        Py_RETURN_BOOL(b);
    }

    return PyErr_SetArgsError((PyObject *) self, "__contains__", arg);
}

static int j_properties_dict_length(j_properties *self)
{
    INT_CALL(return self->object->size());
}

static PyObject *j_properties_dict_get(j_properties *self, PyObject *key)
{
    jstring strKey, value = NULL;

    if (!parseArg(key, "s", &strKey))
    {
        OBJ_CALL(if (self->object->containsKey(strKey))
                     value = self->object->getProperty(strKey));
        if (value)
            return j2p(value);
        
        PyErr_SetObject(PyExc_KeyError, key);
        return NULL;
    }

    return PyErr_SetArgsError((PyObject *) self, "__getitem__", key);
}

static int j_properties_dict_set(j_properties *self,
                                 PyObject *key, PyObject *value)
{
    jstring strKey, strValue;

    if (!parseArg(key, "s", &strKey) && !parseArg(value, "s", &strValue))
    {
        INT_CALL(self->object->setProperty(strKey, strValue));
        return 0;
    }

    PyErr_SetArgsError((PyObject *) self, "__setitem__", key);
    return -1;
}


/* Iterator */

static PyObject *j_iterator_hasNext(j_iterator *self)
{
    jboolean b;

    OBJ_CALL(b = self->object->hasNext());
    Py_RETURN_BOOL(b);
}

static PyObject *j_iterator_next(j_iterator *self)
{
    jobject obj;

    EXC_OBJ_CALL(obj = self->object->next(),
                 java::util::NoSuchElementException,
                 PyErr_SetNone(PyExc_StopIteration); return NULL);

    return wrap_Object(obj);
}

PyObject *j_iterator_iter(j_iterator *self)
{
    Py_INCREF(self);
    return (PyObject *) self;
}


/* Enumeration */

static PyObject *j_enumeration_hasMoreElements(j_enumeration *self)
{
    jboolean b;

    OBJ_CALL(b = self->object->hasMoreElements());
    Py_RETURN_BOOL(b);
}

static PyObject *j_enumeration_nextElement(j_enumeration *self)
{
    jobject obj;

    EXC_OBJ_CALL(obj = self->object->nextElement(),
                 java::util::NoSuchElementException,
                 PyErr_SetNone(PyExc_StopIteration); return NULL);

    return wrap_Object(obj);
}

PyObject *j_enumeration_iter(j_enumeration *self)
{
    Py_INCREF(self);
    return (PyObject *) self;
}


/* StringEnumeration */

static PyObject *j_stringenumeration_nextElement(j_enumeration *self)
{
    jstring s;

    EXC_OBJ_CALL(s = (jstring) self->object->nextElement(),
                 java::util::NoSuchElementException,
                 PyErr_SetNone(PyExc_StopIteration); return NULL);

    return j2p(s);
}


/* PrintStream */
static PyObject *j_printstream_flush(j_printstream *self)
{
    OBJ_CALL(self->object->flush());
    Py_RETURN_NONE;
}

static PyObject *j_printstream_printString(j_printstream *self, PyObject *arg)
{
    jstring str;

    if (!parseArg(arg, "s", &str))
    {
        OBJ_CALL(self->object->print(str));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError((PyObject *) self, "printString", arg);
}

static PyObject *j_printstream_printObject(j_printstream *self, PyObject *arg)
{
    if (PyObject_TypeCheck(arg, &ObjectType))
    {
        OBJ_CALL(self->object->println(((j_object *) arg)->object));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError((PyObject *) self, "printObject", arg);
}

static PyObject *j_printstream_println(j_printstream *self, PyObject *arg)
{
    jstring str;

    if (PyObject_TypeCheck(arg, &ObjectType))
    {
        OBJ_CALL(self->object->println(((j_object *) arg)->object));
        Py_RETURN_NONE;
    }

    if (!parseArg(arg, "s", &str))
    {
        OBJ_CALL(self->object->println(str));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError((PyObject *) self, "println", arg);
}


/* Process */

static PyObject *j_process_destroy(j_process *self)
{
    OBJ_CALL(self->object->destroy());
    Py_RETURN_NONE;
}

static PyObject *j_process_exitValue(j_process *self)
{
    jint value;

    OBJ_CALL(value = self->object->exitValue());
    return PyInt_FromLong(value);
}

static PyObject *j_process_waitFor(j_process *self)
{
    OBJ_CALL(self->object->waitFor());
    Py_RETURN_NONE;
}


/* Runtime */

static PyObject *j_runtime_getRuntime(PyTypeObject *type)
{
    java::lang::Runtime *runtime;

    OBJ_CALL(runtime = java::lang::Runtime::getRuntime());
    return wrap_Runtime(runtime);
}

static PyObject *j_runtime_freeMemory(j_runtime *self)
{
    jlong ram;

    OBJ_CALL(ram = self->object->freeMemory());
    return PyLong_FromLongLong(ram);
}

static PyObject *j_runtime_totalMemory(j_runtime *self)
{
    jlong ram;

    OBJ_CALL(ram = self->object->totalMemory());
    return PyLong_FromLongLong(ram);
}

static PyObject *j_runtime_maxMemory(j_runtime *self)
{
    jlong ram;

    OBJ_CALL(ram = self->object->maxMemory());
    return PyLong_FromLongLong(ram);
}

static PyObject *j_runtime_gc(j_runtime *self)
{
    OBJ_CALL(self->object->gc());
    Py_RETURN_NONE;
}

static PyObject *j_runtime_runFinalization(j_runtime *self)
{
    OBJ_CALL(self->object->runFinalization());
    Py_RETURN_NONE;
}

static PyObject *j_runtime_availableProcessors(j_runtime *self)
{
    jint processors;

    OBJ_CALL(processors = self->object->availableProcessors());
    return PyInt_FromLong(processors);
}

static PyObject *j_runtime_addShutdownHook(j_runtime *self, PyObject *arg)
{
    java::lang::Thread *thread;

    if (!parseArg(arg, "J", &java::lang::Thread::class$, &thread))
    {
        OBJ_CALL(self->object->addShutdownHook(thread));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError((PyObject *) self, "addShutdownHook", arg);
}

static PyObject *j_runtime_removeShutdownHook(j_runtime *self, PyObject *arg)
{
    java::lang::Thread *thread;

    if (!parseArg(arg, "J", &java::lang::Thread::class$, &thread))
    {
        OBJ_CALL(self->object->removeShutdownHook(thread));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError((PyObject *) self, "removeShutdownHook", arg);
}

static PyObject *j_runtime_execute(j_runtime *self, PyObject *args)
{
    java::lang::Process *process;
    jstring cmd;
    jstringArray cmdArray, envp;

    switch (PyTuple_GET_SIZE(args)) {
      case 1:
        if (!parseArgs(args, "s", &cmd))
        {
            OBJ_CALL(process = self->object->exec(cmd));
            return wrap_Process(process);
        }
        if (!parseArgs(args, "S", &cmdArray))
        {
            OBJ_CALL(process = self->object->exec(cmdArray));
            return wrap_Process(process);
        }
        break;
      case 2:
        if (!parseArgs(args, "sS", &cmd, &envp))
        {
            OBJ_CALL(process = self->object->exec(cmd, envp));
            return wrap_Process(process);
        }
        if (!parseArgs(args, "SS", &cmdArray, &envp))
        {
            OBJ_CALL(process = self->object->exec(cmdArray, envp));
            return wrap_Process(process);
        }
        break;
    }

    return PyErr_SetArgsError((PyObject *) self, "execute", args);
}

static PyObject *j_runtime_traceInstructions(j_runtime *self, PyObject *arg)
{
    jboolean b;

    if (!parseArg(arg, "b", &b))
    {
        OBJ_CALL(self->object->traceInstructions(b));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError((PyObject *) self, "traceInstructions", arg);
}

static PyObject *j_runtime_traceMethodCalls(j_runtime *self, PyObject *arg)
{
    jboolean b;

    if (!parseArg(arg, "b", &b))
    {
        OBJ_CALL(self->object->traceMethodCalls(b));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError((PyObject *) self, "traceMethodCalls", arg);
}


/* Package */

static PyObject *j_package_getPackage(PyTypeObject *type, PyObject *arg)
{
    java::lang::Package *package;
    jstring name;
    
    if (!parseArg(arg, "s", &name))
    {
        OBJ_CALL(package = java::lang::Package::getPackage(name));
        return wrap_Package(package);
    }

    return PyErr_SetArgsError(type, "getPackage", arg);
}

static PyObject *j_package_getImplementationTitle(j_package *self)
{
    jstring title;

    OBJ_CALL(title = self->object->getImplementationTitle());
    return j2p(title);
}

static PyObject *j_package_getImplementationVendor(j_package *self)
{
    jstring vendor;

    OBJ_CALL(vendor = self->object->getImplementationVendor());
    return j2p(vendor);
}

static PyObject *j_package_getImplementationVersion(j_package *self)
{
    jstring version;

    OBJ_CALL(version = self->object->getImplementationVersion());
    return j2p(version);
}

static PyObject *j_package_getName(j_package *self)
{
    jstring name;

    OBJ_CALL(name = self->object->getName());
    return j2p(name);
}

static PyObject *j_package_getSpecificationTitle(j_package *self)
{
    jstring title;

    OBJ_CALL(title = self->object->getSpecificationTitle());
    return j2p(title);
}

static PyObject *j_package_getSpecificationVendor(j_package *self)
{
    jstring vendor;

    OBJ_CALL(vendor = self->object->getSpecificationVendor());
    return j2p(vendor);
}

static PyObject *j_package_getSpecificationVersion(j_package *self)
{
    jstring version;

    OBJ_CALL(version = self->object->getSpecificationVersion());
    return j2p(version);
}

static PyObject *j_package_isCompatibleWith(j_package *self, PyObject *arg)
{
    jstring name;
    jboolean b;

    if (!parseArg(arg, "s", &name))
    {
        OBJ_CALL(b = self->object->isCompatibleWith(name));
        Py_RETURN_BOOL(b);
    }

    return PyErr_SetArgsError((PyObject *) self, "isCompatibleWith", arg);
}

static PyObject *j_package_isSealed(j_package *self)
{
    jboolean b;

    OBJ_CALL(b = self->object->isSealed());
    Py_RETURN_BOOL(b);
}


/* Reader */

static int j_reader_init(j_reader *self, PyObject *args, PyObject *kwds)
{
    java::io::Reader *reader;

    if (!parseArgs(args, "P", &java::io::Reader::class$, check_Reader,
                   &reader, make_Reader))
    {
        if (reader)
        {
            self->object = reader;
            refObject(self->object);
            return 0;
        }
    }

    PyErr_SetArgsError((PyObject *) self, "__init__", args);
    return -1;
}

static PyObject *j_reader_close(j_reader *self)
{
    OBJ_CALL(self->object->close());
    Py_RETURN_NONE;
}

static PyObject *j_reader_read(j_reader *self, PyObject *args)
{
    switch (PyTuple_GET_SIZE(args)) {
      case 0:
      {
          jstring data;

          OBJ_CALL(
              {
                  java::lang::StringBuffer *buffer =
                      new java::lang::StringBuffer();
                  jcharArray chars = JvNewCharArray(1024);
                  int len;
                  while ((len = self->object->read(chars)) >= 0)
                      buffer->append(chars, 0, len);
                  data = buffer->toString();
              });

          return j2p(data);
      }
      case 1:
      {
          jint len;

          if (!parseArgs(args, "i", &len))
          {
              jstring data;
          
              OBJ_CALL(
                  {
                      JArray<jchar> *chars = JvNewCharArray(len);
                      len = self->object->read(chars);
                      if (len < 0)
                          Py_RETURN_NONE;
                      data = new java::lang::String(chars, 0, len);
                  });

              return j2p(data);
          }
          break;
      }
    }

    return PyErr_SetArgsError((PyObject *) self, "read", args);
}


/* StringReader */

static int j_stringreader_init(j_stringreader *self,
                               PyObject *args, PyObject *kwds)
{
    java::io::StringReader *reader;
    jstring str;

    switch (PyTuple_GET_SIZE(args)) {
      case 1:
        if (!parseArgs(args, "s", &str))
        {
            INT_CALL(reader = new java::io::StringReader(str));
            self->object = reader;
            break;
        }
        PyErr_SetArgsError((PyObject *) self, "__init__", args);
        return -1;
      default:
        PyErr_SetArgsError((PyObject *) self, "__init__", args);
        return -1;
    }

    if (self->object)
    {
        refObject(self->object);
        return 0;
    }
    
    return -1;
}


/* Locale */

static int j_locale_init(j_locale *self, PyObject *args, PyObject *kwds)
{
    jstring language, country, variant;
    java::util::Locale *locale;

    switch (PyTuple_GET_SIZE(args)) {
      case 1:
        if (!parseArgs(args, "s", &language))
        {
            INT_CALL(locale = new java::util::Locale(language));
            self->object = locale;
            break;
        }
        PyErr_SetArgsError((PyObject *) self, "__init__", args);
        return -1;
      case 2:
        if (!parseArgs(args, "ss", &language, &country))
        {
            INT_CALL(locale = new java::util::Locale(language, country));
            self->object = locale;
            break;
        }
        PyErr_SetArgsError((PyObject *) self, "__init__", args);
        return -1;
      case 3:
        if (!parseArgs(args, "sss", &language, &country, &variant))
        {
            INT_CALL(locale = new java::util::Locale(language, country, variant));
            self->object = locale;
            break;
        }
        PyErr_SetArgsError((PyObject *) self, "__init__", args);
        return -1;
      default:
        PyErr_SetArgsError((PyObject *) self, "__init__", args);
        return -1;
    }

    if (self->object)
    {
        refObject(self->object);
        return 0;
    }
    
    return -1;
}

static PyObject *j_locale_getDefault(PyTypeObject *type)
{
    java::util::Locale *locale;

    OBJ_CALL(locale = java::util::Locale::getDefault());
    return wrap_Locale(locale);
}

static PyObject *j_locale_setDefault(PyTypeObject *type, PyObject *arg)
{
    java::util::Locale *locale;
 
    if (!parseArg(arg, "J", &java::util::Locale::class$, &locale))
    {
        OBJ_CALL(java::util::Locale::setDefault(locale));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError(type, "setDefault", arg);
}

static PyObject *j_locale_getAvailableLocales(PyTypeObject *type)
{
    JArray<java::util::Locale *> *locales;
    
    OBJ_CALL(locales = java::util::Locale::getAvailableLocales());
    return ja2pl((jobjectArray) locales, (PyObject *(*)(jobject)) wrap_Locale);
}

static PyObject *j_locale_getISOCountries(PyTypeObject *type)
{
    jstringArray countries;

    OBJ_CALL(countries = java::util::Locale::getISOCountries());
    return jsa2psl(countries);
}

static PyObject *j_locale_getISOLanguages(PyTypeObject *type)
{
    jstringArray languages;

    OBJ_CALL(languages = java::util::Locale::getISOLanguages());
    return jsa2psl(languages);
}

static PyObject *j_locale_getLanguage(j_locale *self)
{
    jstring language;

    OBJ_CALL(language = self->object->getLanguage());
    return j2p(language);
}

static PyObject *j_locale_getCountry(j_locale *self)
{
    jstring country;

    OBJ_CALL(country = self->object->getCountry());
    return j2p(country);
}

static PyObject *j_locale_getVariant(j_locale *self)
{
    jstring variant;

    OBJ_CALL(variant = self->object->getVariant());
    return j2p(variant);
}

static PyObject *j_locale_getISO3Language(j_locale *self)
{
    jstring language;

    OBJ_CALL(language = self->object->getISO3Language());
    return j2p(language);
}

static PyObject *j_locale_getISO3Country(j_locale *self)
{
    jstring country;

    OBJ_CALL(country = self->object->getISO3Country());
    return j2p(country);
}

static PyObject *j_locale_getDisplayLanguage(j_locale *self, PyObject *args)
{
    java::util::Locale *locale;
    jstring language;

    switch (PyTuple_GET_SIZE(args)) {
      case 0:
        OBJ_CALL(language = self->object->getDisplayLanguage());
        break;
      case 1:
        if (!parseArgs(args, "J", &java::util::Locale::class$, &locale))
        {
            OBJ_CALL(language = self->object->getDisplayLanguage(locale));
            break;
        }
      default:
        return PyErr_SetArgsError((PyObject *) self, "getDisplayLanguage",
                                  args);
    }

    return j2p(language);
}

static PyObject *j_locale_getDisplayCountry(j_locale *self, PyObject *args)
{
    java::util::Locale *locale;
    jstring country;

    switch (PyTuple_GET_SIZE(args)) {
      case 0:
        OBJ_CALL(country = self->object->getDisplayCountry());
        break;
      case 1:
        if (!parseArgs(args, "J", &java::util::Locale::class$, &locale))
        {
            OBJ_CALL(country = self->object->getDisplayCountry(locale));
            break;
        }
      default:
        return PyErr_SetArgsError((PyObject *) self, "getDisplayCountry",
                                  args);
    }

    return j2p(country);
}

static PyObject *j_locale_getDisplayVariant(j_locale *self, PyObject *args)
{
    java::util::Locale *locale;
    jstring variant;

    switch (PyTuple_GET_SIZE(args)) {
      case 0:
        OBJ_CALL(variant = self->object->getDisplayVariant());
        break;
      case 1:
        if (!parseArgs(args, "J", &java::util::Locale::class$, &locale))
        {
            OBJ_CALL(variant = self->object->getDisplayVariant(locale));
            break;
        }
      default:
        return PyErr_SetArgsError((PyObject *) self, "getDisplayVariant",
                                  args);
    }

    return j2p(variant);
}

static PyObject *j_locale_getDisplayName(j_locale *self, PyObject *args)
{
    java::util::Locale *locale;
    jstring name;

    switch (PyTuple_GET_SIZE(args)) {
      case 0:
        OBJ_CALL(name = self->object->getDisplayName());
        break;
      case 1:
        if (!parseArgs(args, "J", &java::util::Locale::class$, &locale))
        {
            OBJ_CALL(name = self->object->getDisplayName(locale));
            break;
        }
      default:
        return PyErr_SetArgsError((PyObject *) self, "getDisplayName", args);
    }

    return j2p(name);
}


/* BitSet */

static int j_bitset_init(j_bitset *self, PyObject *args, PyObject *kwds)
{
    jint nbits;
    java::util::BitSet *bitset;

    switch (PyTuple_GET_SIZE(args)) {
      case 0:
        {
            INT_CALL(bitset = new java::util::BitSet());
            self->object = bitset;
            break;
        }
        PyErr_SetArgsError((PyObject *) self, "__init__", args);
        return -1;
      case 1:
        if (PyArg_ParseTuple(args, "i", &nbits))
        {
            INT_CALL(bitset = new java::util::BitSet(nbits));
            self->object = bitset;
            break;
        }
        PyErr_SetArgsError((PyObject *) self, "__init__", args);
        return -1;
      default:
        PyErr_SetArgsError((PyObject *) self, "__init__", args);
        return -1;
    }

    if (self->object)
    {
        refObject(self->object);
        return 0;
    }
    
    return -1;
}

static PyObject *j_bitset_andSet(j_bitset *self, PyObject *arg)
{
    java::util::BitSet *bitset;

    if (!parseArg(arg, "J", &java::util::BitSet::class$, &bitset))
    {
        OBJ_CALL(self->object->and$(bitset));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError((PyObject *) self, "andSet", arg);
}

static PyObject *j_bitset_andNot(j_bitset *self, PyObject *arg)
{
    java::util::BitSet *bitset;

    if (!parseArg(arg, "J", &java::util::BitSet::class$, &bitset))
    {
        OBJ_CALL(self->object->andNot(bitset));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError((PyObject *) self, "andNot", arg);
}

static PyObject *j_bitset_cardinality(j_bitset *self)
{
    jint nbits;

    OBJ_CALL(nbits = self->object->cardinality());
    return PyInt_FromLong(nbits);
}

static PyObject *j_bitset_clear(j_bitset *self, PyObject *args)
{
    switch (PyTuple_GET_SIZE(args)) {
      case 0:
      {
          OBJ_CALL(self->object->clear());
          Py_RETURN_NONE;
      }
      case 1:
      {
          jint bitIndex;

          if (PyArg_ParseTuple(args, "i", &bitIndex))
          {
              OBJ_CALL(self->object->clear(bitIndex));
              Py_RETURN_NONE;
          }
          return NULL;
      }
      case 2:
      {
          jint fromIndex, toIndex;

          if (PyArg_ParseTuple(args, "ii", &fromIndex, &toIndex))
          {
              OBJ_CALL(self->object->clear(fromIndex, toIndex));
              Py_RETURN_NONE;
          }
          return NULL;
      }
    }

    return PyErr_SetArgsError((PyObject *) self, "clear", args);
}

static PyObject *j_bitset_flip(j_bitset *self, PyObject *args)
{
    switch (PyTuple_GET_SIZE(args)) {
      case 1:
      {
          jint bitIndex;

          if (PyArg_ParseTuple(args, "i", &bitIndex))
          {
              OBJ_CALL(self->object->flip(bitIndex));
              Py_RETURN_NONE;
          }
          return NULL;
      }
      case 2:
      {
          jint fromIndex, toIndex;

          if (PyArg_ParseTuple(args, "ii", &fromIndex, &toIndex))
          {
              OBJ_CALL(self->object->flip(fromIndex, toIndex));
              Py_RETURN_NONE;
          }
          return NULL;
      }
    }

    return PyErr_SetArgsError((PyObject *) self, "flip", args);
}

static PyObject *j_bitset_get(j_bitset *self, PyObject *args)
{
    switch (PyTuple_GET_SIZE(args)) {
      case 1:
      {
          jint bitIndex;
          jboolean b;

          if (PyArg_ParseTuple(args, "i", &bitIndex))
          {
              OBJ_CALL(b = self->object->get(bitIndex));
              Py_RETURN_BOOL(b);
          }
          return NULL;
      }
      case 2:
      {
          jint fromIndex, toIndex;
          java::util::BitSet *bitset;

          if (PyArg_ParseTuple(args, "ii", &fromIndex, &toIndex))
          {
              OBJ_CALL(bitset = self->object->get(fromIndex, toIndex));
              return wrap_BitSet(bitset);
          }
          return NULL;
      }
    }

    return PyErr_SetArgsError((PyObject *) self, "get", args);
}

static PyObject *j_bitset_intersects(j_bitset *self, PyObject *arg)
{
    java::util::BitSet *bitset;

    if (!parseArg(arg, "J", &java::util::BitSet::class$, &bitset))
    {
        jboolean b;

        OBJ_CALL(b = self->object->intersects(bitset));
        Py_RETURN_BOOL(b);
    }

    return PyErr_SetArgsError((PyObject *) self, "intersects", arg);
}

static PyObject *j_bitset_isEmpty(j_bitset *self)
{
    jboolean b;

    OBJ_CALL(b = self->object->isEmpty());
    Py_RETURN_BOOL(b);
}

static PyObject *j_bitset_length(j_bitset *self)
{
    jint length;

    OBJ_CALL(length = self->object->length());
    return PyInt_FromLong(length);
}

static PyObject *j_bitset_nextClearBit(j_bitset *self, PyObject *arg)
{
    jint fromIndex;

    if (!parseArg(arg, "i", &fromIndex))
    {
        OBJ_CALL(fromIndex = self->object->nextClearBit(fromIndex));
        return PyInt_FromLong(fromIndex);
    }

    return PyErr_SetArgsError((PyObject *) self, "nextClearBit", arg);
}

static PyObject *j_bitset_nextSetBit(j_bitset *self, PyObject *arg)
{
    jint fromIndex;

    if (!parseArg(arg, "i", &fromIndex))
    {
        OBJ_CALL(fromIndex = self->object->nextSetBit(fromIndex));
        return PyInt_FromLong(fromIndex);
    }

    return PyErr_SetArgsError((PyObject *) self, "nextSetBit", arg);
}

static PyObject *j_bitset_orSet(j_bitset *self, PyObject *arg)
{
    java::util::BitSet *bitset;

    if (!parseArg(arg, "J", &java::util::BitSet::class$, &bitset))
    {
        OBJ_CALL(self->object->or$(bitset));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError((PyObject *) self, "orSet", arg);
}

static PyObject *j_bitset_set(j_bitset *self, PyObject *args)
{
    jint bitIndex, fromIndex, toIndex;
    jboolean value;

    switch (PyTuple_GET_SIZE(args)) {
      case 1:
      {
          if (PyArg_ParseTuple(args, "i", &bitIndex))
          {
              OBJ_CALL(self->object->set(bitIndex));
              Py_RETURN_NONE;
          }
          return NULL;
      }
      case 2:
      {
          if (!parseArgs(args, "iB", &bitIndex, &value))
          {
              OBJ_CALL(self->object->set(bitIndex, value));
              Py_RETURN_NONE;
          }
          if (!parseArgs(args, "ii", &fromIndex, &toIndex))
          {
              OBJ_CALL(self->object->set(fromIndex, toIndex));
              Py_RETURN_NONE;
          }
          break;
      }
      case 3:
      {
          if (!parseArgs(args, "iiB", &fromIndex, &toIndex, &value))
          {
              OBJ_CALL(self->object->set(fromIndex, toIndex, value));
              Py_RETURN_NONE;
          }
          break;
      }
    }

    return PyErr_SetArgsError((PyObject *) self, "set", args);
}

static PyObject *j_bitset_size(j_bitset *self)
{
    jint size;

    OBJ_CALL(size = self->object->size());
    return PyInt_FromLong(size);
}

static PyObject *j_bitset_xorSet(j_bitset *self, PyObject *arg)
{
    java::util::BitSet *bitset;

    if (!parseArg(arg, "J", &java::util::BitSet::class$, &bitset))
    {
        OBJ_CALL(self->object->xor$(bitset));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError((PyObject *) self, "xorSet", arg);
}


/* Date */

static int j_date_init(j_date *self, PyObject *args, PyObject *kwds)
{
    long long time;
    java::util::Date *date;

    switch (PyTuple_GET_SIZE(args)) {
      case 0:
        INT_CALL(date = new java::util::Date());
        self->object = date;
        break;
      case 1:
        if (PyArg_ParseTuple(args, "L", &time))
        {
            INT_CALL(date = new java::util::Date(time));
            self->object = date;
            break;
        }
        PyErr_SetArgsError((PyObject *) self, "__init__", args);
        return -1;
      default:
        PyErr_SetArgsError((PyObject *) self, "__init__", args);
        return -1;
    }

    if (self->object)
    {
        refObject(self->object);
        return 0;
    }
    
    return -1;
}

static PyObject *j_date_after(j_date *self, PyObject *arg)
{
    java::util::Date *date;

    if (!parseArg(arg, "J", &java::util::Date::class$, &date))
    {
        jboolean b;

        OBJ_CALL(b = self->object->after(date));
        Py_RETURN_BOOL(b);
    }

    return PyErr_SetArgsError((PyObject *) self, "after", arg);
}

static PyObject *j_date_before(j_date *self, PyObject *arg)
{
    java::util::Date *date;

    if (!parseArg(arg, "J", &java::util::Date::class$, &date))
    {
        jboolean b;

        OBJ_CALL(b = self->object->before(date));
        Py_RETURN_BOOL(b);
    }

    return PyErr_SetArgsError((PyObject *) self, "before", arg);
}

static PyObject *j_date_compareTo(j_date *self, PyObject *arg)
{
    java::util::Date *date;

    if (!parseArg(arg, "J", &java::util::Date::class$, &date))
    {
        jint n;

        OBJ_CALL(n = self->object->compareTo(date));
        return PyInt_FromLong(n);
    }

    return PyErr_SetArgsError((PyObject *) self, "compareTo", arg);
}

static PyObject *j_date_getTime(j_date *self)
{
    long long time;

    OBJ_CALL(time = self->object->getTime());
    return PyLong_FromLongLong(time);
}

static PyObject *j_date_setTime(j_date *self, PyObject *arg)
{
    jlong time;

    if (!parseArg(arg, "L", &time))
    {
        OBJ_CALL(self->object->setTime(time));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError((PyObject *) self, "setTime", arg);
}


/* Calendar */

static PyObject *j_calendar_getInstance(PyTypeObject *type, PyObject *args)
{
    java::util::Locale *locale;
    java::util::TimeZone *tz;
    java::util::Calendar *calendar;

    switch (PyTuple_GET_SIZE(args)) {
      case 0:
        OBJ_CALL(calendar = java::util::Calendar::getInstance());
        return wrap_Calendar(calendar);
      case 1:
        if (!parseArgs(args, "J", &java::util::Locale::class$, &locale))
        {
            OBJ_CALL(calendar = java::util::Calendar::getInstance(locale));
            return wrap_Calendar(calendar);
        }
        if (!parseArgs(args, "J", &java::util::TimeZone::class$, &tz))
        {
            OBJ_CALL(calendar = java::util::Calendar::getInstance(tz));
            return wrap_Calendar(calendar);
        }
        break;
      case 2:
        if (!parseArgs(args, "JJ", &java::util::TimeZone::class$,
                       &java::util::Locale::class$, &tz, &locale))
        {
            OBJ_CALL(calendar = java::util::Calendar::getInstance(tz, locale));
            return wrap_Calendar(calendar);
        }
        break;
    }

    return PyErr_SetArgsError(type, "getInstance", args);
}

static PyObject *j_calendar_getAvailableLocales(PyTypeObject *type)
{
    JArray<java::util::Locale *> *locales;
    
    OBJ_CALL(locales = java::util::Calendar::getAvailableLocales());
    return ja2pl((jobjectArray) locales, (PyObject *(*)(jobject)) wrap_Locale);
}

static PyObject *j_calendar_getTime(j_calendar *self)
{
    java::util::Date *date;

    OBJ_CALL(date = self->object->getTime());
    return wrap_Date(date);
}

static PyObject *j_calendar_setTime(j_calendar *self, PyObject *arg)
{
    java::util::Date *date;

    if (!parseArg(arg, "J", &java::util::Date::class$, &date))
    {
        OBJ_CALL(self->object->setTime(date));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError((PyObject *) self, "setTime", arg);
}

static PyObject *j_calendar_getTimeInMillis(j_calendar *self)
{
    long long time;

    OBJ_CALL(time = self->object->getTimeInMillis());
    return PyLong_FromLongLong(time);
}

static PyObject *j_calendar_setTimeInMillis(j_calendar *self, PyObject *arg)
{
    jlong time;

    if (!parseArg(arg, "L", &time))
    {
        OBJ_CALL(self->object->setTimeInMillis(time));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError((PyObject *) self, "setTimeInMillis", arg);
}

static PyObject *j_calendar_getTimeZone(j_calendar *self)
{
    java::util::TimeZone *tz;

    OBJ_CALL(tz = self->object->getTimeZone());
    return wrap_TimeZone(tz);
}

static PyObject *j_calendar_setTimeZone(j_calendar *self, PyObject *arg)
{
    java::util::TimeZone *tz;

    if (!parseArg(arg, "J", &java::util::TimeZone::class$, &tz))
    {
        OBJ_CALL(self->object->setTimeZone(tz));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError((PyObject *) self, "setTimeZone", arg);
}

static PyObject *j_calendar_get(j_calendar *self, PyObject *arg)
{
    jint field;

    if (!parseArg(arg, "i", &field))
    {
        OBJ_CALL(field = self->object->get(field));
        return PyInt_FromLong(field);
    }

    return PyErr_SetArgsError((PyObject *) self, "get", arg);
}

static PyObject *j_calendar_set(j_calendar *self, PyObject *args)
{
    jint field, value, year, month, date, hour, minute, second;

    switch (PyTuple_GET_SIZE(args)) {
      case 2:
        if (PyArg_ParseTuple(args, "ii", &field, &value))
        {
            OBJ_CALL(self->object->set(field, value));
            Py_RETURN_NONE;
        }
        return NULL;
      case 3:
        if (PyArg_ParseTuple(args, "iii", &year, &month, &date))
        {
            OBJ_CALL(self->object->set(year, month, date));
            Py_RETURN_NONE;
        }
        return NULL;
      case 5:
        if (PyArg_ParseTuple(args, "iiiii", &year, &month, &date,
                             &hour, &minute))
        {
            OBJ_CALL(self->object->set(year, month, date,
                                       hour, minute));
            Py_RETURN_NONE;
        }
        return NULL;
      case 6:
        if (PyArg_ParseTuple(args, "iiiiii", &year, &month, &date,
                             &hour, &minute, &second))
        {
            OBJ_CALL(self->object->set(year, month, date,
                                       hour, minute, second));
            Py_RETURN_NONE;
        }
        return NULL;
    }

    return PyErr_SetArgsError((PyObject *) self, "set", args);
}

static PyObject *j_calendar_clear(j_calendar *self, PyObject *args)
{
    switch (PyTuple_GET_SIZE(args)) {
      case 0:
        OBJ_CALL(self->object->clear());
        Py_RETURN_NONE;
      case 1:
      {
          jint field;

          if (PyArg_ParseTuple(args, "i", &field))
          {
              OBJ_CALL(self->object->clear(field));
              Py_RETURN_NONE;
          }
      }
    }
    
    return PyErr_SetArgsError((PyObject *) self, "clear", args);
}

static PyObject *j_calendar_isSet(j_calendar *self, PyObject *arg)
{
    jint field;
    jboolean b;

    if (!parseArg(arg, "i", &field))
    {
        OBJ_CALL(b = self->object->isSet(field));
        Py_RETURN_BOOL(b);
    }

    return PyErr_SetArgsError((PyObject *) self, "isSet", arg);
}

static PyObject *j_calendar_before(j_calendar *self, PyObject *arg)
{
    java::util::Calendar *calendar;

    if (!parseArg(arg, "J", &java::util::Calendar::class$, &calendar))
    {
        jboolean b;

        OBJ_CALL(b = self->object->before(calendar));
        Py_RETURN_BOOL(b);
    }

    return PyErr_SetArgsError((PyObject *) self, "before", arg);
}

static PyObject *j_calendar_after(j_calendar *self, PyObject *arg)
{
    java::util::Calendar *calendar;

    if (!parseArg(arg, "J", &java::util::Calendar::class$, &calendar))
    {
        jboolean b;

        OBJ_CALL(b = self->object->after(calendar));
        Py_RETURN_BOOL(b);
    }

    return PyErr_SetArgsError((PyObject *) self, "after", arg);
}

static PyObject *j_calendar_add(j_calendar *self, PyObject *args)
{
    jint field, amount;

    if (PyArg_ParseTuple(args, "ii", &field, &amount))
    {
        OBJ_CALL(self->object->add(field, amount));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError((PyObject *) self, "add", args);
}

static PyObject *j_calendar_roll(j_calendar *self, PyObject *args)
{
    jint field, amount;
    jboolean up;

    if (PyArg_ParseTuple(args, "iB", &field, &up))
    {
        OBJ_CALL(self->object->roll(field, up));
        Py_RETURN_NONE;
    }
    if (PyArg_ParseTuple(args, "ii", &field, &amount))
    {
        OBJ_CALL(self->object->roll(field, amount));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError((PyObject *) self, "roll", args);
}

static PyObject *j_calendar_setLenient(j_calendar *self, PyObject *arg)
{
    jboolean b;

    if (!parseArg(arg, "b", &b))
    {
        OBJ_CALL(self->object->setLenient(b));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError((PyObject *) self, "setLenient", arg);
}

static PyObject *j_calendar_isLenient(j_calendar *self)
{
    jboolean b;

    OBJ_CALL(b = self->object->isLenient());
    Py_RETURN_BOOL(b);
}

static PyObject *j_calendar_setFirstDayOfWeek(j_calendar *self, PyObject *arg)
{
    jint day;

    if (!parseArg(arg, "i", &day))
    {
        OBJ_CALL(self->object->setFirstDayOfWeek(day));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError((PyObject *) self, "setFirstDayOfWeek", arg);
}

static PyObject *j_calendar_getFirstDayOfWeek(j_calendar *self)
{
    jint day;

    OBJ_CALL(day = self->object->getFirstDayOfWeek());
    return PyInt_FromLong(day);
}

static PyObject *j_calendar_setMinimalDaysInFirstWeek(j_calendar *self,
                                                      PyObject *arg)
{
    jint value;

    if (!parseArg(arg, "i", &value))
    {
        OBJ_CALL(self->object->setMinimalDaysInFirstWeek(value));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError((PyObject *) self, "setMinimalDaysInFirstWeek",
                              arg);
}

static PyObject *j_calendar_getMinimalDaysInFirstWeek(j_calendar *self)
{
    jint value;

    OBJ_CALL(value = self->object->getMinimalDaysInFirstWeek());
    return PyInt_FromLong(value);
}

static PyObject *j_calendar_getMinimum(j_calendar *self, PyObject *arg)
{
    jint field;

    if (!parseArg(arg, "i", &field))
    {
        OBJ_CALL(field = self->object->getMinimum(field));
        return PyInt_FromLong(field);
    }

    return PyErr_SetArgsError((PyObject *) self, "getMinimum", arg);
}

static PyObject *j_calendar_getMaximum(j_calendar *self, PyObject *arg)
{
    jint field;

    if (!parseArg(arg, "i", &field))
    {
        OBJ_CALL(field = self->object->getMaximum(field));
        return PyInt_FromLong(field);
    }

    return PyErr_SetArgsError((PyObject *) self, "getMaximum", arg);
}

static PyObject *j_calendar_getGreatestMinimum(j_calendar *self, PyObject *arg)
{
    jint field;

    if (!parseArg(arg, "i", &field))
    {
        OBJ_CALL(field = self->object->getGreatestMinimum(field));
        return PyInt_FromLong(field);
    }

    return PyErr_SetArgsError((PyObject *) self, "getGreatestMinimum", arg);
}

static PyObject *j_calendar_getLeastMaximum(j_calendar *self, PyObject *arg)
{
    jint field;

    if (!parseArg(arg, "i", &field))
    {
        OBJ_CALL(field = self->object->getLeastMaximum(field));
        return PyInt_FromLong(field);
    }

    return PyErr_SetArgsError((PyObject *) self, "getLeastMaximum", arg);
}

static PyObject *j_calendar_getActualMinimum(j_calendar *self, PyObject *arg)
{
    jint field;

    if (!parseArg(arg, "i", &field))
    {
        OBJ_CALL(field = self->object->getActualMinimum(field));
        return PyInt_FromLong(field);
    }

    return PyErr_SetArgsError((PyObject *) self, "getActualMinimum", arg);
}

static PyObject *j_calendar_getActualMaximum(j_calendar *self, PyObject *arg)
{
    jint field;

    if (!parseArg(arg, "i", &field))
    {
        OBJ_CALL(field = self->object->getActualMaximum(field));
        return PyInt_FromLong(field);
    }

    return PyErr_SetArgsError((PyObject *) self, "getActualMaximum", arg);
}

DEFINE_DOWNCAST(j_calendar, GregorianCalendar,
                java::util::GregorianCalendar);

/* GregorianCalendar */

static int j_gregoriancalendar_init(j_gregoriancalendar *self,
                                    PyObject *args, PyObject *kwds)
{
    jint year, month, date, hour, minute, second;
    java::util::Locale *locale;
    java::util::TimeZone *tz;
    java::util::GregorianCalendar *calendar;

    switch (PyTuple_GET_SIZE(args)) {
      case 0:
        {
            INT_CALL(calendar = new java::util::GregorianCalendar());
            self->object = calendar;
            break;
        }
        PyErr_SetArgsError((PyObject *) self, "__init__", args);
        return -1;
      case 1:
        if (!parseArgs(args, "J", &java::util::Locale::class$, &locale))
        {
            INT_CALL(calendar = new java::util::GregorianCalendar(locale));
            self->object = calendar;
            break;
        }
        if (!parseArgs(args, "J", &java::util::TimeZone::class$, &tz))
        {
            INT_CALL(calendar = new java::util::GregorianCalendar(tz));
            self->object = calendar;
            break;
        }
        PyErr_SetArgsError((PyObject *) self, "__init__", args);
        return -1;
      case 2:
        if (!parseArgs(args, "JJ", &java::util::TimeZone::class$,
                       &java::util::Locale::class$, &tz, &locale))
        {
            INT_CALL(calendar = new java::util::GregorianCalendar(tz, locale));
            self->object = calendar;
            break;
        }
        PyErr_SetArgsError((PyObject *) self, "__init__", args);
        return -1;
      case 3:
        if (PyArg_ParseTuple(args, "iii", &year, &month, &date))
        {
            INT_CALL(calendar = new java::util::GregorianCalendar(year, month, date));
            self->object = calendar;
            break;
        }
        PyErr_SetArgsError((PyObject *) self, "__init__", args);
        return -1;
      case 5:
        if (PyArg_ParseTuple(args, "iiiii", &year, &month, &date, &hour, &minute))
        {
            INT_CALL(calendar = new java::util::GregorianCalendar(year, month, date, hour, minute));
            self->object = calendar;
            break;
        }
        PyErr_SetArgsError((PyObject *) self, "__init__", args);
        return -1;
      case 6:
        if (PyArg_ParseTuple(args, "iiiiii", &year, &month, &date, &hour, &minute, &second))
        {
            INT_CALL(calendar = new java::util::GregorianCalendar(year, month, date, hour, minute, second));
            self->object = calendar;
            break;
        }
        PyErr_SetArgsError((PyObject *) self, "__init__", args);
        return -1;
      default:
        PyErr_SetArgsError((PyObject *) self, "__init__", args);
        return -1;
    }

    if (self->object)
    {
        refObject(self->object);
        return 0;
    }
    
    return -1;
}

static PyObject *j_gregoriancalendar_getGregorianChange(j_gregoriancalendar *self)
{
    java::util::Date *date;
    
    OBJ_CALL(date = self->object->getGregorianChange());
    return wrap_Date(date);
}

static PyObject *j_gregoriancalendar_setGregorianChange(j_gregoriancalendar *self, PyObject *arg)
{
    java::util::Date *date;

    if (!parseArg(arg, "J", &java::util::Date::class$, &date))
    {
        OBJ_CALL(self->object->setGregorianChange(date));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError((PyObject *) self, "setGregorianChange", arg);
}

static PyObject *j_gregoriancalendar_isLeapYear(j_gregoriancalendar *self, PyObject *arg)
{
    jint year;
    jboolean b;

    if (!parseArg(arg, "i", &year))
    {
        OBJ_CALL(b = self->object->isLeapYear(year));
        Py_RETURN_BOOL(b);
    }

    return PyErr_SetArgsError((PyObject *) self, "isLeapYear", arg);
}


/* Format */

static PyObject *j_format_format(j_format *self, PyObject *arg)
{
    if (PyObject_TypeCheck(arg, &ObjectType))
    {
        jstring string;

        OBJ_CALL(string = self->object->format(((j_object *) arg)->object));
        return j2p(string);
    }

    return PyErr_SetArgsError((PyObject *) self, "format", arg);
}


/* NumberFormat */

static PyObject *j_numberformat_getAvailableLocales(PyTypeObject *type)
{
    JArray<java::util::Locale *> *locales;
    
    OBJ_CALL(locales = java::text::NumberFormat::getAvailableLocales());
    return ja2pl((jobjectArray) locales, (PyObject *(*)(jobject)) wrap_Locale);
}

static PyObject *j_numberformat_getCurrencyInstance(PyTypeObject *type,
                                                    PyObject *args)
{
    java::text::NumberFormat *format;

    switch (PyTuple_GET_SIZE(args)) {
      case 0:
        OBJ_CALL(format = java::text::NumberFormat::getCurrencyInstance());
        return wrap_NumberFormat(format);
      case 1:
      {
          java::util::Locale *locale;

          if (!parseArgs(args, "J", &java::util::Locale::class$, &locale))
          {
              OBJ_CALL(format = java::text::NumberFormat::getCurrencyInstance(locale));
              return wrap_NumberFormat(format);
          }
      }
    }
    
    return PyErr_SetArgsError(type, "getCurrencyInstance", args);
}

static PyObject *j_numberformat_getInstance(PyTypeObject *type, PyObject *args)
{
    java::text::NumberFormat *format;

    switch (PyTuple_GET_SIZE(args)) {
      case 0:
        OBJ_CALL(format = java::text::NumberFormat::getInstance());
        return wrap_NumberFormat(format);
      case 1:
      {
          java::util::Locale *locale;

          if (!parseArgs(args, "J", &java::util::Locale::class$, &locale))
          {
              OBJ_CALL(format = java::text::NumberFormat::getInstance(locale));
              return wrap_NumberFormat(format);
          }
      }
    }
    
    return PyErr_SetArgsError(type, "getInstance", args);
}

static PyObject *j_numberformat_getNumberInstance(PyTypeObject *type,
                                                  PyObject *args)
{
    java::text::NumberFormat *format;

    switch (PyTuple_GET_SIZE(args)) {
      case 0:
        OBJ_CALL(format = java::text::NumberFormat::getNumberInstance());
        return wrap_NumberFormat(format);
      case 1:
      {
          java::util::Locale *locale;

          if (!parseArgs(args, "J", &java::util::Locale::class$, &locale))
          {
              OBJ_CALL(format = java::text::NumberFormat::getNumberInstance(locale));
              return wrap_NumberFormat(format);
          }
      }
    }
    
    return PyErr_SetArgsError(type, "getNumberInstance", args);
}

static PyObject *j_numberformat_getIntegerInstance(PyTypeObject *type,
                                                   PyObject *args)
{
    java::text::NumberFormat *format;

    switch (PyTuple_GET_SIZE(args)) {
      case 0:
        OBJ_CALL(format = java::text::NumberFormat::getIntegerInstance());
        return wrap_NumberFormat(format);
      case 1:
      {
          java::util::Locale *locale;

          if (!parseArgs(args, "J", &java::util::Locale::class$, &locale))
          {
              OBJ_CALL(format = java::text::NumberFormat::getIntegerInstance(locale));
              return wrap_NumberFormat(format);
          }
      }
    }
    
    return PyErr_SetArgsError(type, "getIntegerInstance", args);
}

static PyObject *j_numberformat_getPercentInstance(PyTypeObject *type,
                                                   PyObject *args)
{
    java::text::NumberFormat *format;

    switch (PyTuple_GET_SIZE(args)) {
      case 0:
        OBJ_CALL(format = java::text::NumberFormat::getPercentInstance());
        return wrap_NumberFormat(format);
      case 1:
      {
          java::util::Locale *locale;

          if (!parseArgs(args, "J", &java::util::Locale::class$, &locale))
          {
              OBJ_CALL(format = java::text::NumberFormat::getPercentInstance(locale));
              return wrap_NumberFormat(format);
          }
      }
    }
    
    return PyErr_SetArgsError(type, "getPercentInstance", args);
}

static PyObject *j_numberformat_format(j_numberformat *self, PyObject *arg)
{
    jlong l;
    jdouble d;
    jstring s;

    if (!parseArg(arg, "d", &d))
    {
        OBJ_CALL(s = self->object->format(d));
        return j2p(s);
    }
    if (!parseArg(arg, "L", &l))
    {
        OBJ_CALL(s = self->object->format(l));
        return j2p(s);
    }

    return PyErr_SetArgsError((PyObject *) self, "format", arg);
}

static PyObject *j_numberformat_getMaximumFractionDigits(j_numberformat *self)
{
    jint value;

    OBJ_CALL(value = self->object->getMaximumFractionDigits());
    return PyInt_FromLong(value);
}

static PyObject *j_numberformat_getMaximumIntegerDigits(j_numberformat *self)
{
    jint value;

    OBJ_CALL(value = self->object->getMaximumIntegerDigits());
    return PyInt_FromLong(value);
}

static PyObject *j_numberformat_getMinimumFractionDigits(j_numberformat *self)
{
    jint value;

    OBJ_CALL(value = self->object->getMinimumFractionDigits());
    return PyInt_FromLong(value);
}

static PyObject *j_numberformat_getMinimumIntegerDigits(j_numberformat *self)
{
    jint value;

    OBJ_CALL(value = self->object->getMinimumIntegerDigits());
    return PyInt_FromLong(value);
}

static PyObject *j_numberformat_isGroupingUsed(j_numberformat *self)
{
    jboolean b;

    OBJ_CALL(b = self->object->isGroupingUsed());
    Py_RETURN_BOOL(b);
}

static PyObject *j_numberformat_isParseIntegerOnly(j_numberformat *self)
{
    jboolean b;

    OBJ_CALL(b = self->object->isParseIntegerOnly());
    Py_RETURN_BOOL(b);
}

static PyObject *j_numberformat_setGroupingUsed(j_numberformat *self, PyObject *arg)
{
    jboolean b;

    if (!parseArg(arg, "b", &b))
    {
        OBJ_CALL(self->object->setGroupingUsed(b));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError((PyObject *) self, "setGroupingUsed", arg);
}

static PyObject *j_numberformat_setMaximumFractionDigits(j_numberformat *self, PyObject *arg)
{
    jint value;

    if (!parseArg(arg, "i", &value))
    {
        OBJ_CALL(self->object->setMaximumFractionDigits(value));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError((PyObject *) self, "setMaximumFractionDigits", arg);
}

static PyObject *j_numberformat_setMaximumIntegerDigits(j_numberformat *self, PyObject *arg)
{
    jint value;

    if (!parseArg(arg, "i", &value))
    {
        OBJ_CALL(self->object->setMaximumIntegerDigits(value));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError((PyObject *) self, "setMaximumIntegerDigits", arg);
}

static PyObject *j_numberformat_setMinimumFractionDigits(j_numberformat *self, PyObject *arg)
{
    jint value;

    if (!parseArg(arg, "i", &value))
    {
        OBJ_CALL(self->object->setMinimumFractionDigits(value));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError((PyObject *) self, "setMinimumFractionDigits", arg);
}

static PyObject *j_numberformat_setMinimumIntegerDigits(j_numberformat *self, PyObject *arg)
{
    jint value;

    if (!parseArg(arg, "i", &value))
    {
        OBJ_CALL(self->object->setMinimumIntegerDigits(value));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError((PyObject *) self, "setMinimumIntegerDigits", arg);
}

static PyObject *j_numberformat_setParseIntegerOnly(j_numberformat *self, PyObject *arg)
{
    jboolean b;

    if (!parseArg(arg, "b", &b))
    {
        OBJ_CALL(self->object->setParseIntegerOnly(b));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError((PyObject *) self, "setParseIntegerOnly", arg);
}


/* TimeZone */

static PyObject *j_timezone_getAvailableIDs(PyTypeObject *type, PyObject *args)
{
    jstringArray ids;

    OBJ_CALL(ids = java::util::TimeZone::getAvailableIDs());
    return jsa2psl(ids);
}

static PyObject *j_timezone_getDefault(PyTypeObject *type)
{
    java::util::TimeZone *tz;

    OBJ_CALL(tz = java::util::TimeZone::getDefault());
    return wrap_TimeZone(tz);
}

static PyObject *j_timezone_setDefault(PyTypeObject *type, PyObject *arg)
{
    java::util::TimeZone *tz;

    if (!parseArg(arg, "J", &java::util::TimeZone::class$, &tz))
    {
        OBJ_CALL(java::util::TimeZone::setDefault(tz));
        Py_RETURN_NONE;
    }
    
    return PyErr_SetArgsError(type, "setDefault", arg);
}

static PyObject *j_timezone_getTimeZone(PyTypeObject *type, PyObject *arg)
{
    java::util::TimeZone *tz;
    jstring id;

    if (!parseArg(arg, "s", &id))
    {
        OBJ_CALL(tz = java::util::TimeZone::getTimeZone(id));
        return wrap_TimeZone(tz);
    }

    return PyErr_SetArgsError(type, "getTimeZone", arg);
}

static PyObject *j_timezone_getDisplayName(j_timezone *self, PyObject *args)
{
    java::util::Locale *locale;
    jboolean daylight;
    jint style;
    jstring s;
    
    switch (PyTuple_GET_SIZE(args)) {
      case 0:
        OBJ_CALL(s = self->object->getDisplayName());
        return j2p(s);
      case 1:
        if (!parseArgs(args, "J", &java::util::Locale::class$, &locale))
        {
            OBJ_CALL(s = self->object->getDisplayName(locale));
            return j2p(s);
        }
        break;
      case 2:
        if (!parseArg(args, "bi", &daylight, &style))
        {
            OBJ_CALL(s = self->object->getDisplayName(daylight, style));
            return j2p(s);
        }
        break;
      case 3:
        if (!parseArg(args, "biJ", &java::util::Locale::class$,
                      &daylight, &style, &locale))
        {
            OBJ_CALL(s = self->object->getDisplayName(daylight, style, locale));
            return j2p(s);
        }
        break;
    }

    return PyErr_SetArgsError((PyObject *) self, "getDisplayName", args);
}

static PyObject *j_timezone_getDSTSavings(j_timezone *self)
{
    jint value;

    OBJ_CALL(value = self->object->getDSTSavings());
    return PyInt_FromLong(value);
}

static PyObject *j_timezone_getID(j_timezone *self)
{
    jstring id;

    OBJ_CALL(id = self->object->getID());
    return j2p(id);
}

static PyObject *j_timezone_setID(j_timezone *self, PyObject *arg)
{
    jstring id;

    if (!parseArg(arg, "s", &id))
    {
        OBJ_CALL(self->object->setID(id));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError((PyObject *) self, "setID", arg);
}

static PyObject *j_timezone_getOffset(j_timezone *self, PyObject *args)
{
    jint offset;

    switch (PyTuple_GET_SIZE(args)) {
      case 1:
      {
          jlong date;

          if (PyArg_ParseTuple(args, "L", &date))
          {
              OBJ_CALL(offset = self->object->getOffset(date));
              return PyInt_FromLong(offset);
          }
          return NULL;
      }
      case 6:
      {
          jint year, month, day, hour, minute, second;

          if (PyArg_ParseTuple(args, "iiiiii", &year, &month, &day, &hour,
                               &minute, &second))
          {
              OBJ_CALL(offset = self->object->getOffset(year, month, day, hour,
                                                        minute, second));
              return PyInt_FromLong(offset);
          }
          return NULL;
      }
    }
              
    return PyErr_SetArgsError((PyObject *) self, "getOffset", args);
}

static PyObject *j_timezone_getRawOffset(j_timezone *self)
{
    jint offset;

    OBJ_CALL(offset = self->object->getRawOffset());
    return PyInt_FromLong(offset);
}

static PyObject *j_timezone_setRawOffset(j_timezone *self, PyObject *arg)
{
    jint offset;

    if (!parseArg(arg, "i", &offset))
    {
        OBJ_CALL(self->object->setRawOffset(offset));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError((PyObject *) self, "setOffset", arg);
}

static PyObject *j_timezone_hasSameRules(j_timezone *self, PyObject *arg)
{
    java::util::TimeZone *tz;
    jboolean b;

    if (!parseArg(arg, "J", &java::util::TimeZone::class$, &tz))
    {
        OBJ_CALL(b = self->object->hasSameRules(tz));
        Py_RETURN_BOOL(b);
    }

    return PyErr_SetArgsError((PyObject *) self, "hasSameRules", arg);
}

static PyObject *j_timezone_inDaylightTime(j_timezone *self, PyObject *arg)
{
    java::util::Date *date;
    jboolean b;

    if (!parseArg(arg, "J", &java::util::Date::class$, &date))
    {
        OBJ_CALL(b = self->object->inDaylightTime(date));
        Py_RETURN_BOOL(b);
    }

    return PyErr_SetArgsError((PyObject *) self, "inDaylightTime", arg);
}

static PyObject *j_timezone_useDaylightTime(j_timezone *self)
{
    OBJ_CALL(self->object->useDaylightTime());
    Py_RETURN_NONE;
}


/* DateFormat */

static PyObject *j_dateformat_getAvailableLocales(PyTypeObject *type)
{
    JArray<java::util::Locale *> *locales;
    
    OBJ_CALL(locales = java::text::DateFormat::getAvailableLocales());
    return ja2pl((jobjectArray) locales, (PyObject *(*)(jobject)) wrap_Locale);
}

static PyObject *j_dateformat_getDateInstance(PyTypeObject *type,
                                              PyObject *args)
{
    java::text::DateFormat *df;
    java::util::Locale *locale;
    jint style;

    switch (PyTuple_GET_SIZE(args)) {
      case 0:
        OBJ_CALL(df = java::text::DateFormat::getDateInstance());
        return wrap_DateFormat(df);
      case 1:
        if (!parseArgs(args, "i", &style))
        {
            OBJ_CALL(df = java::text::DateFormat::getDateInstance(style));
            return wrap_DateFormat(df);
        }
        break;
      case 2:
        if (!parseArgs(args, "iJ", &java::util::Locale::class$,
                       &style, &locale))
        {
            OBJ_CALL(df = java::text::DateFormat::getDateInstance(style, locale));
            return wrap_DateFormat(df);
        }
        break;
    }
        
    return PyErr_SetArgsError(type, "getDateInstance", args);
}

static PyObject *j_dateformat_getTimeInstance(PyTypeObject *type,
                                              PyObject *args)
{
    java::text::DateFormat *df;
    java::util::Locale *locale;
    jint style;

    switch (PyTuple_GET_SIZE(args)) {
      case 0:
        OBJ_CALL(df = java::text::DateFormat::getTimeInstance());
        return wrap_DateFormat(df);
      case 1:
        if (!parseArgs(args, "i", &style))
        {
            OBJ_CALL(df = java::text::DateFormat::getTimeInstance(style));
            return wrap_DateFormat(df);
        }
        break;
      case 2:
        if (!parseArgs(args, "iJ", &java::util::Locale::class$,
                       &style, &locale))
        {
            OBJ_CALL(df = java::text::DateFormat::getTimeInstance(style, locale));
            return wrap_DateFormat(df);
        }
        break;
    }
        
    return PyErr_SetArgsError(type, "getTimeInstance", args);
}

static PyObject *j_dateformat_getDateTimeInstance(PyTypeObject *type,
                                                  PyObject *args)
{
    java::text::DateFormat *df;
    java::util::Locale *locale;
    jint dateStyle, timeStyle;

    switch (PyTuple_GET_SIZE(args)) {
      case 0:
        OBJ_CALL(df = java::text::DateFormat::getDateTimeInstance());
        return wrap_DateFormat(df);
      case 2:
        if (!parseArgs(args, "ii", &dateStyle, &timeStyle))
        {
            OBJ_CALL(df = java::text::DateFormat::getDateTimeInstance(dateStyle, timeStyle));
            return wrap_DateFormat(df);
        }
        break;
      case 3:
        if (!parseArgs(args, "iiJ", &java::util::Locale::class$,
                       &dateStyle, &timeStyle, &locale))
        {
            OBJ_CALL(df = java::text::DateFormat::getDateTimeInstance(dateStyle, timeStyle, locale));
            return wrap_DateFormat(df);
        }
        break;
    }
        
    return PyErr_SetArgsError(type, "getDateTimeInstance", args);
}

static PyObject *j_dateformat_getInstance(PyTypeObject *type)
{
    java::text::DateFormat *df;

    OBJ_CALL(df = java::text::DateFormat::getInstance());
    return wrap_DateFormat(df);
}

static PyObject *j_dateformat_getNumberFormat(j_dateformat *self)
{
    java::text::NumberFormat *format;

    OBJ_CALL(format = self->object->getNumberFormat());
    return wrap_NumberFormat(format);
}

static PyObject *j_dateformat_setNumberFormat(j_dateformat *self, PyObject *arg)
{
    java::text::NumberFormat *format;

    if (!parseArg(arg, "J", &java::text::NumberFormat::class$, &format))
    {
        OBJ_CALL(self->object->setNumberFormat(format));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError((PyObject *) self, "setNumberFormat", arg);
}

static PyObject *j_dateformat_getCalendar(j_dateformat *self)
{
    java::util::Calendar *calendar;

    OBJ_CALL(calendar = self->object->getCalendar());
    return wrap_Calendar(calendar);
}

static PyObject *j_dateformat_setCalendar(j_dateformat *self, PyObject *arg)
{
    java::util::Calendar *calendar;

    if (!parseArg(arg, "J", &java::util::Calendar::class$, &calendar))
    {
        OBJ_CALL(self->object->setCalendar(calendar));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError((PyObject *) self, "setCalendar", arg);
}

static PyObject *j_dateformat_isLenient(j_dateformat *self)
{
    jboolean b;

    OBJ_CALL(b = self->object->isLenient());
    Py_RETURN_BOOL(b);
}

static PyObject *j_dateformat_setLenient(j_dateformat *self, PyObject *arg)
{
    jboolean b;

    if (!parseArg(arg, "b", &b))
    {
        OBJ_CALL(self->object->setLenient(b));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError((PyObject *) self, "setLenient", arg);
}

static PyObject *j_dateformat_format(j_dateformat *self, PyObject *arg)
{
    java::util::Date *date;
    jstring s;

    if (!parseArg(arg, "J", &java::util::Date::class$, &date))
    {
        OBJ_CALL(s = self->object->format(date));
        return j2p(s);
    }

    return PyErr_SetArgsError((PyObject *) self, "format", arg);
}

static PyObject *j_dateformat_parse(j_dateformat *self, PyObject *arg)
{
    java::util::Date *date;
    jstring s;

    if (!parseArg(arg, "s", &s))
    {
        OBJ_CALL(date = self->object->parse(s));
        return wrap_Date(date);
    }

    return PyErr_SetArgsError((PyObject *) self, "parse", arg);
}


/* DecimalFormat */

static int j_decimalformat_init(j_decimalformat *self,
                                PyObject *args, PyObject *kwds)
{
    jstring pattern;
    java::text::DecimalFormat *format;

    switch (PyTuple_GET_SIZE(args)) {
      case 0:
        INT_CALL(format = new java::text::DecimalFormat());
        self->object = format;
        break;
      case 1:
        if (!parseArgs(args, "s", &pattern))
        {
            INT_CALL(format = new java::text::DecimalFormat(pattern));
            self->object = format;
            break;
        }
        PyErr_SetArgsError((PyObject *) self, "__init__", args);
        return -1;
      default:
        PyErr_SetArgsError((PyObject *) self, "__init__", args);
        return -1;
    }

    if (self->object)
    {
        refObject(self->object);
        return 0;
    }
    
    return -1;
}

static PyObject *j_decimalformat_applyLocalizedPattern(j_decimalformat *self, PyObject *arg)
{
    jstring pattern;

    if (!parseArg(arg, "s", &pattern))
    {
        OBJ_CALL(self->object->applyLocalizedPattern(pattern));
        Py_RETURN_NONE;
    }
    
    return PyErr_SetArgsError((PyObject *) self, "applyLocalizedPattern", arg);
}

static PyObject *j_decimalformat_applyPattern(j_decimalformat *self, PyObject *arg)
{
    jstring pattern;

    if (!parseArg(arg, "s", &pattern))
    {
        OBJ_CALL(self->object->applyPattern(pattern));
        Py_RETURN_NONE;
    }
    
    return PyErr_SetArgsError((PyObject *) self, "applyPattern", arg);
}

static PyObject *j_decimalformat_getGroupingSize(j_decimalformat *self)
{
    jint size;

    OBJ_CALL(size = self->object->getGroupingSize());
    return PyInt_FromLong(size);
}

static PyObject *j_decimalformat_setGroupingSize(j_decimalformat *self, PyObject *arg)
{
    jint size;

    if (!parseArg(arg, "i", &size))
    {
        OBJ_CALL(self->object->setGroupingSize(size));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError((PyObject *) self, "setGroupingSize", arg);
}

static PyObject *j_decimalformat_getMultiplier(j_decimalformat *self)
{
    jint multiplier;

    OBJ_CALL(multiplier = self->object->getMultiplier());
    return PyInt_FromLong(multiplier);
}

static PyObject *j_decimalformat_setMultiplier(j_decimalformat *self, PyObject *arg)
{
    jint multiplier;

    if (!parseArg(arg, "i", &multiplier))
    {
        OBJ_CALL(self->object->setMultiplier(multiplier));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError((PyObject *) self, "setMultiplier", arg);
}

static PyObject *j_decimalformat_getNegativePrefix(j_decimalformat *self)
{
    jstring prefix;

    OBJ_CALL(prefix = self->object->getNegativePrefix());
    return j2p(prefix);
}

static PyObject *j_decimalformat_getNegativeSuffix(j_decimalformat *self)
{
    jstring suffix;

    OBJ_CALL(suffix = self->object->getNegativeSuffix());
    return j2p(suffix);
}

static PyObject *j_decimalformat_setNegativePrefix(j_decimalformat *self, PyObject *arg)
{
    jstring prefix;

    if (!parseArg(arg, "s", &prefix))
    {
        OBJ_CALL(self->object->setNegativePrefix(prefix));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError((PyObject *) self, "setNegativePrefix", arg);
}

static PyObject *j_decimalformat_setNegativeSuffix(j_decimalformat *self, PyObject *arg)
{
    jstring suffix;

    if (!parseArg(arg, "s", &suffix))
    {
        OBJ_CALL(self->object->setNegativeSuffix(suffix));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError((PyObject *) self, "setNegativeSuffix", arg);
}

static PyObject *j_decimalformat_isDecimalSeparatorAlwaysShown(j_decimalformat *self)
{
    jboolean b;

    OBJ_CALL(b = self->object->isDecimalSeparatorAlwaysShown());
    Py_RETURN_BOOL(b);
}

static PyObject *j_decimalformat_setDecimalSeparatorAlwaysShown(j_decimalformat *self, PyObject *arg)
{
    jboolean b;

    if (!parseArg(arg, "b", &b))
    {
        OBJ_CALL(self->object->setDecimalSeparatorAlwaysShown(b));
        Py_RETURN_NONE;
    }

    return PyErr_SetArgsError((PyObject *) self, "setDecimalSeparatorAlwaysShown", arg);
}

static PyObject *j_decimalformat_toLocalizedPattern(j_decimalformat *self)
{
    jstring pattern;

    OBJ_CALL(pattern = self->object->toLocalizedPattern());
    return j2p(pattern);
}

static PyObject *j_decimalformat_toPattern(j_decimalformat *self)
{
    jstring pattern;

    OBJ_CALL(pattern = self->object->toPattern());
    return j2p(pattern);
}


/* SimpleDateFormat */

static int j_simpledateformat_init(j_simpledateformat *self,
                                   PyObject *args, PyObject *kwds)
{
    jstring pattern;
    java::text::SimpleDateFormat *format;
    java::util::Locale *locale;

    switch (PyTuple_GET_SIZE(args)) {
      case 0:
        INT_CALL(format = new java::text::SimpleDateFormat());
        self->object = format;
        break;
      case 1:
        if (!parseArgs(args, "s", &pattern))
        {
            INT_CALL(format = new java::text::SimpleDateFormat(pattern));
            self->object = format;
            break;
        }
        PyErr_SetArgsError((PyObject *) self, "__init__", args);
        return -1;
      case 2:
        if (!parseArgs(args, "sJ", &java::util::Locale::class$,
                       &pattern, &locale))
        {
            INT_CALL(format = new java::text::SimpleDateFormat(pattern, locale));
            self->object = format;
            break;
        }
        PyErr_SetArgsError((PyObject *) self, "__init__", args);
        return -1;
      default:
        PyErr_SetArgsError((PyObject *) self, "__init__", args);
        return -1;
    }

    if (self->object)
    {
        refObject(self->object);
        return 0;
    }
    
    return -1;
}

static PyObject *j_simpledateformat_applyLocalizedPattern(j_simpledateformat *self, PyObject *arg)
{
    jstring pattern;

    if (!parseArg(arg, "s", &pattern))
    {
        OBJ_CALL(self->object->applyLocalizedPattern(pattern));
        Py_RETURN_NONE;
    }
    
    return PyErr_SetArgsError((PyObject *) self, "applyLocalizedPattern", arg);
}

static PyObject *j_simpledateformat_applyPattern(j_simpledateformat *self, PyObject *arg)
{
    jstring pattern;

    if (!parseArg(arg, "s", &pattern))
    {
        OBJ_CALL(self->object->applyPattern(pattern));
        Py_RETURN_NONE;
    }
    
    return PyErr_SetArgsError((PyObject *) self, "applyPattern", arg);
}

static PyObject *j_simpledateformat_get2DigitYearStart(j_simpledateformat *self)
{
    java::util::Date *date;

    OBJ_CALL(date = self->object->get2DigitYearStart());
    return wrap_Date(date);
}

static PyObject *j_simpledateformat_toLocalizedPattern(j_simpledateformat *self)
{
    jstring pattern;

    OBJ_CALL(pattern = self->object->toLocalizedPattern());
    return j2p(pattern);
}

static PyObject *j_simpledateformat_toPattern(j_simpledateformat *self)
{
    jstring pattern;

    OBJ_CALL(pattern = self->object->toPattern());
    return j2p(pattern);
}


/* Charset */

static int j_charset_init(j_charset *self, PyObject *args, PyObject *kwds)
{
    JArray<jchar> *charset;

    switch (PyTuple_GET_SIZE(args)) {
      case 1:
        if (!parseArgs(args, "P", &JArray<jchar>::class$,
                       check_Charset, &charset, make_Charset))
        {
            self->object = charset;
            break;
        }
        PyErr_SetArgsError((PyObject *) self, "__init__", args);
        return -1;
      default:
        PyErr_SetArgsError((PyObject *) self, "__init__", args);
        return -1;
    }

    if (self->object)
    {
        refObject(self->object);
        return 0;
    }
    
    return -1;
}


void _init_java(PyObject *m)
{
    JvInitClass(&java::util::Locale::class$);

#ifdef GCJ_STATIC
    /* force linking in of classes that are normally dynamically loaded and 
     * whose absence would prevent _PyLucene.so from loading when statically
     * linked against libgcj.so
     */

    JvInitClass(&gnu::gcj::convert::Output_8859_1::class$);
    JvInitClass(&gnu::gcj::convert::Output_ASCII::class$);
    JvInitClass(&gnu::gcj::convert::Output_EUCJIS::class$);
    JvInitClass(&gnu::gcj::convert::Output_iconv::class$);
    JvInitClass(&gnu::gcj::convert::Output_JavaSrc::class$);
    JvInitClass(&gnu::gcj::convert::Output_SJIS::class$);
    JvInitClass(&gnu::gcj::convert::Output_UTF8::class$);
#endif

    PropertiesType.tp_as_mapping = &j_properties_as_mapping;
    PropertiesType.tp_iter = (getiterfunc)j_properties_propertyNames;
    IteratorType.tp_iter = (getiterfunc) j_iterator_iter;
    IteratorType.tp_iternext = (iternextfunc) j_iterator_next;
    EnumerationType.tp_iter = (getiterfunc) j_enumeration_iter;
    EnumerationType.tp_iternext = (iternextfunc) j_enumeration_nextElement;
    StringEnumerationType.tp_iternext = (iternextfunc) j_stringenumeration_nextElement;
    CharsetType.tp_as_sequence = &j_charset_as_sequence;

    INSTALL_TYPE(Object, m);
    INSTALL_TYPE(Throwable, m);
    INSTALL_TYPE(Class, m);
    INSTALL_TYPE(ClassLoader, m);
    INSTALL_TYPE(Comparable, m);
    INSTALL_TYPE(Runnable, m);
    INSTALL_TYPE(Thread, m);
    INSTALL_TYPE(System, m);
    INSTALL_TYPE(Properties, m);
    INSTALL_TYPE(Iterator, m);
    INSTALL_TYPE(Enumeration, m);
    INSTALL_TYPE(StringEnumeration, m);
    INSTALL_TYPE(PrintStream, m);
    INSTALL_TYPE(Process, m);
    INSTALL_TYPE(Runtime, m);
    INSTALL_TYPE(Package, m);
    INSTALL_TYPE(Reader, m);
    INSTALL_TYPE(StringReader, m);
    INSTALL_TYPE(Locale, m);
    INSTALL_TYPE(BitSet, m);
    INSTALL_TYPE(Date, m);
    INSTALL_TYPE(Calendar, m);
    INSTALL_TYPE(GregorianCalendar, m);
    INSTALL_TYPE(Format, m);
    INSTALL_TYPE(NumberFormat, m);
    INSTALL_TYPE(TimeZone, m);
    INSTALL_TYPE(DateFormat, m);
    INSTALL_TYPE(DecimalFormat, m);
    INSTALL_TYPE(SimpleDateFormat, m);
    INSTALL_TYPE(Charset, m);

    INSTALL_STATIC(System, out, PrintStream, java::lang::System);
    INSTALL_STATIC(System, err, PrintStream, java::lang::System);

    INSTALL_STATIC(Locale, ENGLISH, Locale, java::util::Locale);
    INSTALL_STATIC(Locale, FRENCH, Locale, java::util::Locale);
    INSTALL_STATIC(Locale, GERMAN, Locale, java::util::Locale);
    INSTALL_STATIC(Locale, ITALIAN, Locale, java::util::Locale);
    INSTALL_STATIC(Locale, JAPANESE, Locale, java::util::Locale);
    INSTALL_STATIC(Locale, KOREAN, Locale, java::util::Locale);
    INSTALL_STATIC(Locale, CHINESE, Locale, java::util::Locale);
    INSTALL_STATIC(Locale, SIMPLIFIED_CHINESE, Locale, java::util::Locale);
    INSTALL_STATIC(Locale, TRADITIONAL_CHINESE, Locale, java::util::Locale);
    INSTALL_STATIC(Locale, FRANCE, Locale, java::util::Locale);
    INSTALL_STATIC(Locale, GERMANY, Locale, java::util::Locale);
    INSTALL_STATIC(Locale, ITALY, Locale, java::util::Locale);
    INSTALL_STATIC(Locale, JAPAN, Locale, java::util::Locale);
    INSTALL_STATIC(Locale, KOREA, Locale, java::util::Locale);
    INSTALL_STATIC(Locale, CHINA, Locale, java::util::Locale);
    INSTALL_STATIC(Locale, PRC, Locale, java::util::Locale);
    INSTALL_STATIC(Locale, TAIWAN, Locale, java::util::Locale);
    INSTALL_STATIC(Locale, UK, Locale, java::util::Locale);
    INSTALL_STATIC(Locale, US, Locale, java::util::Locale);
    INSTALL_STATIC(Locale, CANADA, Locale, java::util::Locale);
    INSTALL_STATIC(Locale, CANADA_FRENCH, Locale, java::util::Locale);

    INSTALL_STATIC_INT(Calendar, ERA, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, YEAR, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, MONTH, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, WEEK_OF_YEAR, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, WEEK_OF_MONTH, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, DATE, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, DAY_OF_MONTH, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, DAY_OF_YEAR, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, DAY_OF_WEEK, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, DAY_OF_WEEK_IN_MONTH, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, AM_PM, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, HOUR, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, HOUR_OF_DAY, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, MINUTE, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, SECOND, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, MILLISECOND, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, ZONE_OFFSET, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, DST_OFFSET, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, FIELD_COUNT, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, SUNDAY, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, MONDAY, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, TUESDAY, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, WEDNESDAY, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, THURSDAY, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, FRIDAY, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, SATURDAY, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, JANUARY, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, FEBRUARY, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, MARCH, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, APRIL, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, MAY, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, JUNE, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, JULY, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, AUGUST, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, SEPTEMBER, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, OCTOBER, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, NOVEMBER, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, DECEMBER, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, UNDECIMBER, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, AM, java::util::Calendar);
    INSTALL_STATIC_INT(Calendar, PM, java::util::Calendar);

    INSTALL_STATIC_INT(GregorianCalendar, BC, java::util::GregorianCalendar);
    INSTALL_STATIC_INT(GregorianCalendar, AD, java::util::GregorianCalendar);

    INSTALL_STATIC_INT(NumberFormat, INTEGER_FIELD, java::text::NumberFormat);
    INSTALL_STATIC_INT(NumberFormat, FRACTION_FIELD, java::text::NumberFormat);

    INSTALL_STATIC_INT(TimeZone, LONG, java::util::TimeZone);
    INSTALL_STATIC_INT(TimeZone, SHORT, java::util::TimeZone);

    INSTALL_STATIC_INT(DateFormat, FULL, java::text::DateFormat);
    INSTALL_STATIC_INT(DateFormat, LONG, java::text::DateFormat);
    INSTALL_STATIC_INT(DateFormat, MEDIUM, java::text::DateFormat);
    INSTALL_STATIC_INT(DateFormat, SHORT, java::text::DateFormat);
    INSTALL_STATIC_INT(DateFormat, DEFAULT, java::text::DateFormat);
    INSTALL_STATIC_INT(DateFormat, ERA_FIELD, java::text::DateFormat);
    INSTALL_STATIC_INT(DateFormat, YEAR_FIELD, java::text::DateFormat);
    INSTALL_STATIC_INT(DateFormat, MONTH_FIELD, java::text::DateFormat);
    INSTALL_STATIC_INT(DateFormat, DATE_FIELD, java::text::DateFormat);
    INSTALL_STATIC_INT(DateFormat, HOUR_OF_DAY1_FIELD, java::text::DateFormat);
    INSTALL_STATIC_INT(DateFormat, HOUR_OF_DAY0_FIELD, java::text::DateFormat);
    INSTALL_STATIC_INT(DateFormat, MINUTE_FIELD, java::text::DateFormat);
    INSTALL_STATIC_INT(DateFormat, SECOND_FIELD, java::text::DateFormat);
    INSTALL_STATIC_INT(DateFormat, MILLISECOND_FIELD, java::text::DateFormat);
    INSTALL_STATIC_INT(DateFormat, DAY_OF_WEEK_FIELD, java::text::DateFormat);
    INSTALL_STATIC_INT(DateFormat, DAY_OF_YEAR_FIELD, java::text::DateFormat);
    INSTALL_STATIC_INT(DateFormat, DAY_OF_WEEK_IN_MONTH_FIELD, java::text::DateFormat);
    INSTALL_STATIC_INT(DateFormat, WEEK_OF_YEAR_FIELD, java::text::DateFormat);
    INSTALL_STATIC_INT(DateFormat, WEEK_OF_MONTH_FIELD, java::text::DateFormat);
    INSTALL_STATIC_INT(DateFormat, AM_PM_FIELD, java::text::DateFormat);
    INSTALL_STATIC_INT(DateFormat, HOUR1_FIELD, java::text::DateFormat);
    INSTALL_STATIC_INT(DateFormat, HOUR0_FIELD, java::text::DateFormat);
    INSTALL_STATIC_INT(DateFormat, TIMEZONE_FIELD, java::text::DateFormat);
}
