Java Extensions

Using Java Classes

The ObjectBox comes with built-in support for binding Java classes directly to your o:XML programs. Any Java class can be resolved at compile time, making it available to use in your o:XML program. The resolved Java class can be instantiated and subtyped like any other o:XML type, furthermore all static methods can be invoked and static member fields accessed.

Public constructors of a resolved class are available as functions in a namespace that contains the Java package name. Static methods and fields are also available but here the namespace contains the full Java class name, which avoid possible clashes between classes in the same package. Static methods, if public, are simply functions qualified by that namespace, whereas static fields are available as variables.

Here's an example that demonstrates accessing Java classes with static class fields as well as through instantiation with a constructor and then invoking class methods.



<program xmlns:o="http://www.o-xml.org/lang/"
   xmlns:ex="http://www.o-xml.com/examples/" 
   xmlns:java="http://www.o-xml.com/java/"
   xmlns:java-lang="http://www.o-xml.com/java/java.lang"
   xmlns:System="http://www.o-xml.com/java/java.lang.System">

  <!-- define a function that takes one argument -->
  <!-- and prints it on the Java System.out stream -->
  <o:function name="ex:log">
    <o:param name="arg"/>
    <o:do>
      <java:resolve classname="java.lang.System"/>
      <!-- java:resolve will put all fields that are both public and static as -->
      <!-- variables in the namespace 'http://www.o-xml.com/java/java.lang.System'. -->
      <!-- here '$System.out' refers to the field 'out' in java.lang.System -->
      <o:do select="$System:out.println($arg)"/>
    </o:do>
  </o:function>

  <java:resolve classname="java.lang.StringBuffer"/>
  <!-- all public constructors are made available as functions in the namespace -->
  <!-- containing the package name, ie 'http://www.o-xml.com/java/java.lang' -->
  <o:variable name="buf" select="java-lang:StringBuffer('tautology: ')"/>

  <!-- o:XML basic types (String, Number, Boolean) are converted to Java objects -->
  <o:do select="$buf.append(1)"/>
  <o:do select="$buf.append('|')"/>
  <o:do select="$buf.append(0)"/>
  <o:do select="$buf.append('=')"/>
  <o:do select="$buf.append(true())"/>

  <!-- call the log function -->
  <o:eval select="ex:log($buf.toString())"/>

</program>

Type Conversion

Java String, Character, Boolean and Number classes are automatically converted to and from their o:XML counterparts. There's also a convenience function that turns Java arrays into java.lang.List objects. This is because in o:XML there are no arrays, and a List is much easier to manipulate using methods. For an example see the way an array of Cookies are handled in the Http Snoop example.

The Java extensions also provide convenient o:XML functions for converting between o:XML nodesets and Java DOM objects, as illustrated in this example:



<program xmlns:o="http://www.o-xml.org/lang/" 
  xmlns:java="http://www.o-xml.com/java/">

  <!-- define some data -->
  <o:variable name="data">
      <one>one</one>
      <two>two</two>
  </o:variable>

  <!-- turn the data into a Java DOM DocumentFragment -->
  <o:variable name="dom" select="java:toDOM($data)"/>

  <!-- invoke a class method on the DOM object -->
  <o:variable name="kids" select="$dom.getChildNodes()"/>

  <!-- the variable 'kids' now holds a DOM NodeList -->
  <o:for-each name="i" from="0" to="$kids.getLength()">
     <!-- turn each child node back into an o:XML nodeset -->
     <o:eval select="java:toNative($kids.item($i))"/>
  </o:for-each>

</program>