Hi,

I am planning on starting work on the non-CORBA Java bindings for the 
official CellML API implementation (http://www.cellml.org/tools/api/) at 
some point within the next few weeks.

As I have not done any significant work on the Java binding, there is 
still time for changes to the API to be made. I would be keen to get any 
feedback from potential users of the API (especially those who currently 
have their own CellML API implementation in Java, and would benefit from 
being able to access the CellML API).

I have detailed a rough proposal as to how it should be done below. 
Please let me know if you disagree with anything in the proposal (I 
would also be interested for feedback if you think this would be useful 
for you and you would use it). Please also forward this on if you know 
of a group working with CellML from Java who isn't on the To: list.

Proposal:
1) The Java API bindings will simply forward calls between Java and the 
existing implementation in C++, PCM (Physiome CellML Mapping) (i.e. 
there is no plan to write a 100% pure Java implementation).
2) The interface will be defined using Java Native Interface (JNI). The 
bindings will target JDK 1.2 (or 1.1?) and earlier. It will attempt to 
avoid any non-portable C++ code, although binaries will need to be 
recompiled on each platform.
3) The general structure of the API will follow the existing 
specification described in the API document
https://svn.physiomeproject.org/svn/physiome/CellML_DOM_API/trunk/interfaces/CellML_APISPEC.idl
and the associated IDL files.
4) The bindings will be generated automatically from the IDL files. The 
code that will be written to support this will therefore take an IDL 
file as an input, and generate Java and C++ code to bridge between the 
existing API implementation and Java. The only code hand-written for the 
API will be the bootstrap code, used to get hold of the initial 
CellMLBootstrap object.
5) The code generator will be written in Python, extending the existing 
omniidl tool that comes with omniORB (http://omniorb.sourceforge.net).
6) The code generator will generate the following outputs:
  a) A Java interface file. There will be one public Java interface for 
each interface defined in the IDL files.
  b) A Java class file (one per interface) 'implementing' the interface. 
This class will define all methods as native.
  c) A C++ file acting as a Java->C++ bridge. This implements the native 
methods in b above, by calling the C++ API for them.
  d) A C++ file acting as a C++->Java bridge. This implements the 
interfaces defined in the IDL (in the form used by the existing API 
implementation), and uses JNI to invoke Java methods on classes 
implementing interfaces defined in a.
7) The base of all interfaces in the IDL definition, XPCOM::IObject, 
will have a corresponding Java interface (which is distinct from 
java.lang.Object), called XPCOM.IObject. This interface will expose 
query_interface (which will be renamed to queryInterface in the Java 
mapping) and the objid getter on the base object. However, as a special 
case, add_ref and release_ref will not be exposed to Java code. The 
rationale for this is that add_ref / release_ref are of no use to Java 
code, because the bindings will automatically create Java references to 
objects, allowing normal Java garbage collection to work as expected 
(subject to the caveat that no reference loop involving CellML API 
objects should be left around).
8) Because multiple inheritance of classes is not allowed in Java (and 
it would cause an explosion in code size if we generated all bindings 
for base interfaces on every implementation class). Therefore, where an 
interface has multiple base interfaces, the first interface in the list 
is selected, and all other base interfaces are not supported by the 
binding class. However, a new binding class can be obtained for the same 
underlying object using QueryInterface. For example, 
MathMLContentContainer inherits both MathMLContentElement and 
MathMLContainer. If you have a MathMLContentContainer called cc, and you 
want to access getNArguments() on MathMLContainer, you would have to 
write 
((MathMLContainer)cc.queryInterface("mathml_dom.MathMLContainer")).getNArguments().
10) The concrete implementation of XPCOM::IObject (C++->Java) overrides 
java.lang.Object.equals(java.lang.Object) for the the case that the 
argument is an XPCOM::IObject. In this case, it performs the comparison 
using getObjid() on XPCOM::IObject. Likewise, hashCode is implemented to 
hash the objid, and toString to contain the objid. This ensures that 
Java data-structures can be used together with CellML API objects.
11) The reference counting system used in the CellML API interacts with 
the garbage collection used in Java as follows:
   Every Java=>C++ wrapper has an associated strong reference (i.e. 
reference count incremented) to the underlying C++ object. This is 
stored in a private field. Upon finalisation of the C++
   wrapper by the garbage collector, this reference is released.

   Every C++=>Java wrapper holds a JNI global reference to the Java 
object. This global reference is released from the destructor of the 
wrapper. This means that as long as the API holds a reference
   to a Java object, it will not be eligible to be garbage collected.
12) The API currently has thread-safety issues if used from multiple 
threads (it doesn't use mutexes to protect data structures), so as an 
interim solution, users will be advised not to call the API from more 
than one thread in Java, unless green-threads are in use.
13) Interface packages will be as follows: module(.module)*. Interface 
names will be taken directly from the IDL. For example, the FQN of model 
interface will be cellml_api.Model.
14) Implementation classes will take the same name as the interface, but 
the package will be prefixed with "impl.".
15) Attributes in the IDL will map to getters (and setters for 
non-readonly attributes): The first letter of the name will be up-cased, 
with the prefix 'get' or 'set' applied.
For example, the following attribute:
attribute CellMLAttributeString cmetaId;
maps to:
String getCmetaId()
void setCmetaId(String arg);
16) Both UTF16 and UTF8 strings map to java.lang.String, converted as 
appropriate. Other basic types map as follows:
      PCM         IDL                     Java
       uint32_t    unsigned long     int
       uint16_t    unsigned short    short
       uint8_t      unsigned char     byte
       double      double                 double
       float          float                    float
17) All sequences in IDL map to the array of the underlying type in Java.
18) Java objects map to wrappers of that object in PCM. PCM objects map 
to wrappers of the object in Java.
19) As an exception to 18, Java objects which are wrappers of PCM 
objects are unwrapped instead of double wrapped, and likewise for PCM 
objects which are wrappers of Java objects.

More than likely, more similar types of rules will become necessary when 
I actually start work. If you can think of any now, or see something 
that is unclear, please let me know.

Best regards,
Andrew Miller

_______________________________________________
cellml-discussion mailing list
[email protected]
http://www.cellml.org/mailman/listinfo/cellml-discussion

Reply via email to