Home >> Media Group >> Research >> ViPER
Downloads -- Documentation -- Developers -- Discussion
LAMP     The Language and Media Processing Laboratory

Limn3: An Application Loader for Java

It uses rdf+n3, now with more OWL!

Introduction

Limn3 was developed for version four of the viper ground truth annotation tool, a visual tool that provides several different views of the same data, and may be extended by groups to support specific styles of annotation or annotation of task-specfic schemata. This can be as simple as adding new data types or new media types, or as complex as adding a new wizard that completely removes the need for the default interaction panels.

In order to edit the application at a high level, a developer normally needs access to a Java development environment, like NetBeans or eclipse. Not only that, but this normally involves modifying the internals of some java files with the application. It would be preferable to keep the application architecture specified in a place separate from the logic and implementation. This could include both structure and connection between components as well as initialization and parameters specific to each component.

In the previous version (versions 3 through 3.6.1 of the annotation tool) we used a set of Java properties files to specify user preferences, such as key bindings and the painting style of various widgets. As these are simply more bean initialization parameters, it was possible to remove those files as well. It would also be useful to include localization and internationalization information within the same framework. As such, I decided to use the Jena semantic web framework, which supports the RDF/N3 declarative language.

Existing Tools

There are a wide variety of tools for doing similar work. After deciding against using the Java application frameworks provided by NetBeans or eclipse, NetBeans for reasons similar to those described above, and eclipse because it was not yet usable as an application framework, I examined available text-based application loaders. I first looked at the XML toolkits GLADE, the GTK+ layout tool; BMF, the Bean Markup Language; and XUL, the Mozilla project's XML user interface language. Since deciding to use my own toolkit, developed to use RDF, I have become aware of two related applications, OSAF's Chandler and MIT's Haystack, both of which use semantic web technologies to drive a cross-platform application's behavior.

The first tool I looked at was GLADE, which provides both a visual editor and an xml format. This would allow the application to be modified by hand as well as with an editor, something I valued. However, its design is closely tied to the underlying widget toolkit, and it is not designed to be extended to other languages or gui widget sets. ViPER-GT required a toolkit that could be applied to Java, and one that is flexible enough to support widgets not designed with the toolkit in mind, or vice versa.

BMF is probably the most similar tool to what I wished to do. It is the most lightweight, and it maps most concretely to a JavaBeans application. However, it is too thin a layer atop java. It seems to be not much more than a different syntax for LiveConnect. It does have a variety of features not found in my solution: it is able to be compiled to Java code, and it supports invoking generic methods and setting fields. Both of these features can be added to my solution, but without the ordering constraint included in the XML DOM that is absent in the RDF model, it would be difficult.

XUL offers a useful toolkit for applications, often resulting in applications that feel more native than a modern java application, at least with the Gecko engine. Parties other than the main Mozilla organization offer java engines for XUL, but they fail to provide the complete functionality of the system.

Chandler and Haystack are both frameworks which attempt to provide a graphical front end to a set of data stored in an RDF format. Chandler combines RDF with its own XML format, while Haystack extends RDF with a scheme-like language, Adenine. Both represent more whole-hearted endeavors in their support of semantic web technologies, where our application launcher is more pragmatic in its approach, assuming that people have the ability to write some Java code in support of their application.

In addition to those frameworks, it is worth mentioning a few tools that perform some subset of the tasks that the application loader performs: internationalization, per user preferences, command line processing, menu items, and hotkey bindings. I examined the tools, but decided against using them (for now), but hope to include most of their features. These include GNU gettext, the Optik options parser, etc. [TODO: there is a C-like optik thing]

The Tool Schemata

The tool relies on a varity of RDF items, each of which are defined in OWL ontologies. I haven't tested the ontologies thoroughly, as the tool, as implemented, does not make use of them. Instead, they are mostly useful for documentation and satisfying my own pedantry.

Limn3 Core Schema

The root schema, this provides most of the description of how to load and initialize beans, as well as a few other useful properties and classes that most applications will need that do not fit anywhere else. It includes the ability to load, initialize, and link JavaBeans together, as well as some support for internationalization. It also includes definitions for the "userDirectory" property and the "Core" bean.

Loading and Initializing Beans

Whereas BML uses XML's ordering to load the beans appropriately, RDF has no such ordering of its data model, instead representing an unordered set of simple 3-ary assertions. The first step in developing the tool was to add the ordering mechanism. It currently uses a topological ordering of the beans, by the lal:requires link, to load them in order, then initialize them. The loading step calls the default constructor [FIXME: I think BML has a method for invoking constructors with non-zero argument lists]

After the beans are loaded, they are initialized using their setProperty properties. The Property objects are not good OWL, as they have properties (the propertyValue) that have no range specified (they can take literals or resources). I regarded this as necessary; sometimes it is useful to be able to set a String directly; other times, it is necessary to get the property of another bean.

Later, I realized the need for some beans to be loaded on the fly, leading to the creation of the ApplicationBean and TemporaryBean classes, subclasses of the original Bean type. The ApplicationBeans are all loaded when the system preferences file is loaded; the temporary beans are all loaded when they are requested by AppLoader.getBean method (e.g. explicitly by code, or in a property setter).

This lead to the need for the Parent bean, a pseudo-bean that always refers to the bean whose property is being set. This way, it is possible to create a temporary bean that sets one of its properties to the bean that is loading it (or one of that bean's properties).

There is one other Bean defined in the schema document: the Core bean. Currently implemented as a JFrame, the Core bean is useful for attaching other beans to, for giving the name of the application, and so forth. Unfortunately, making it a JFrame precludes describing command-line applications. It is likely that I will add another property in the future to allow the user to explicitly choose a class that implements a 'Core' interface.

Adding Listeners to Beans

The listenerBean and listenerType properties allow a user to attach a generic listener to a bean.

Actionators

Actionators get the java ActionListener/Action objects to fit into the Limn3 scheme of beans better.

Language Tools

In addition to the heavy lifting of loading beans and initializing them, the core schema also defines a few other useful properties. The lang property allows objects to be chosen by the language, as strings are.

GNU gettext is the standard tool, and exists for Java, making it much easier to generate the required resource bundles, using strings of the form some text {0} more text {2} to convert parameters into strings. In order to nest strings, it would be possible to override the toString methods of the parameter objects to use gettext, as well. It is likely that I will replace the current method with something that is compatible with the gettext method, allowing tools developed for that tool to work with our own. Gettext's use of numbered, and not named, attributes may prevent this.

Preferences Schema

This schema provides a way of describing how command line arguments and system variables can be loaded into RDF or used to execute java code. For example, this allows a command line argument to automatically insert some RDF into the system properties. As a side benefit, it also generates usage statements.

Most Recently Used File Schema

Most recently used file lists, while not an essential part of an application, go a long way to making it more useful, especially when dealing with a large file system.

Undo Schema

This schema provides a mechanism for localizing undo messages.

Bean Propery Schema

This schema provides a way of describing how to expose properties of java beans and arbitrary java class instances to the user and to the rest of the application loader framework.

Hotkey Binding Schema

This schema provides a way of describing how keystrokes are bound to application events. It uses a syntax for describing keystrokes that is both more consistent and more cross-platform than java's keystroke syntax.

The Application Loader

Dealing with Change

The Jena2 model of change notification is very simple - if the model changes, all listeners are notified that something has changed. Jena1 had no change listener mechanism, so we added our own, which allows listening for changes that involve certain nodes or properties, and the events include information about what exactly changed.

Serialization

Currently, changes are only serialized into the user.n3 file. The system.n3 file remains unaltered, even if the program changed it while it was running.

Future Work

Between Application beans and Anonymous Beans

:attachesTo and the core::wrap method of loading support harness for an object (I miss before/after)

Includes and Excludes

Currently, there is no way for the user to negate (retract) something in the system.n3 file. Also, there is no way for a file to include another file.

Conclusion

The system, as described, is capable of launching an application, putting beans together that were not written with the launcher in mind, and allowing beans that know about it to modify its model or listen to changes. There is still much work to be done for it to be a completely generic tool, but it is already useful for a variety of purposes.