Wednesday, December 10, 2008

A Major Refactoring Of OpenJUMP Begins

I’ve begun what I hope will become a major refactoring of the OpenJUMP core. This is different from minor changes to classes and interfaces in the core, and is more akin to rebuilding the core from the ground up. I’ll be reusing as much code as I can, but will be making some fairly major changes to the architecture. (I will attempt to keep changes to the API of the program to a minimum.)

Why attempt such a major refactoring of OpenJUMP’s core? Why attempt such a major refactoring now?

Let met tackle that first question with a list of my goals for the refactoring:

Integration of the InfoNode Docking Window Framework.

I had originally planned on just bolting this on to the existing TaskFrame class. (I even released a version of BizzJUMP with this functionality.) I later realized, after some suggestions from other programmers, that it would be good to integrate the docking window framework into the root of the OpenJUMP GUI, the WorkbenchFrame class. It would also make sense to integrate existing OpenJUMP functionality presented to the user with JInternalFrames into the docking window framework. This would be things like the view of attribute tables. You can learn more about the InfoNode docking windows framework here: http://www.infonode.net/index.html?idw

Extraction of OpenJUMP RCP code.

It makes sense to extract the basic application framework from OpenJUMP so it can be reused in other programs, especially if we’ll be integrating a docking window framework. I’ll be doing this by separating the “generic application functionality” from the WorkbenchFrame and other related classes. For example, I’ve started moving some of this functionality to an ApplicationFrame class which the WorkbenchFrame will now extend. In the future, this will allow other programmers to build on the application framework currently embedded in OpenJUMP for programs that don’t look anything like OpenJUMP.

Extraction of a OpenJUMP “model” library.

When JUMP was first written, it included two JAR files. One JAR file contained only the classes and interfaces needed for the “model” of OpenJUMP. This separation allowed the model to be used outside of OpenJUMP. I want to take another crack at cementing this separation and packaging and promoting the use of the OpenJUMP model outside of the program. The model will contain classes like Feature, FeatureCollection, and FeatureSchema and FeatureEvent.

Improve the separation between “model” and “view”.

The orginal programmers did a pretty good job of enforcing this separation. However, I found that this separation becomes more fuzzy when you start dealing with things at the level of the WorkbenchFrame class. For example, the WorkbenchFrame class has a createTask method. This method doesn’t really belong on the WorkbenchFrame, because a Task object is not part of the GUI, it is part of the model. I hope to fix this problem and similar problems by creating a separate JumpApplicationModel class that is referenced by the WorkbenchFrame. Non-GUI methods that manipulate the OpenJUMP model will be moved here. (What is the model for OpenJUMP? It is a collection of Task objects, where each Task is a wrapper for a collection of Layers. Right now the WorkbenchFrame manages this collection of tasks, there is no container for tasks cleanly separated from the GUI code.)

Separation of generic utility code and JUMP-specific utility code.

OpenJUMP contains lots of great utility code. Some of this code is very generic, and could be used for all sorts of Java programming. Examples of this are the CollectionMap class, the Block class, and the FileUtil class. Other utility code in OpenJUMP is made to work with OpenJUMP objects. Examples of these classes are the FeatureUtil class and the FeatureCollectionUtil class. I’d like to move the generic utility to the JODD library, so it can be packaged and distributed for use in other Java programs. We’d then make JODD an OpenJUMP dependency, and gain access to a host of other utility code. The OpenJUMP specific utility code I would also like to see moved into a separate library. This would keep the “model” JAR size to an absolute minimum, and increase the modularity. Some clean-up and consolidation of the utility code is likely going to be needed, as this code is currently scattered about the different contributions to OpenJUMP.

Remove unnecessary code.

There is some junk floating around in the OpenJUMP core. Examples are classes that help client code work with JTS geometry objects. A lot of this code has now been moved to the JTS library, on which OpenJUMP already depends. There is no need to keep this code in two (2) places. I also suspect there is code contributed at one time by organizations that are no longer involved with OpenJUMP programming. This code may not be maintained, or may duplicate functionality present in other classes. Other code may no longer be necessary due to the introduction of new language features in Java 1.5 and Java 1.6.

Integration of Java 1.5 language features.

This is one of my most important goals for the refactoring of OpenJUMP. Let’s get rid of all those collections that aren’t type safe because they were written before Java Generics! And all those static final member variables, we don’t need them because we have Enums! (The AttributeType class is an example of a class that could benefit from Java Enums.) Other features of the 1.5 language I hope to integrate into OpenJUMP are listed here:
http://java.sun.com/j2se/1.5.0/docs/relnotes/features.html

Support for low-RAM architecture.

There are certain aspects of OpenJUMP’s current architecture that make low-ram operation difficult. For example, the FeatureCollection object has a getFeatures method that requires a List of all Feaure objects. That really needs to be replaced with a method that returns an Iterator instead. That would free a FeatureCollection implementation from the requirement to keep all its Feature objects, or a façade to its Feature objects, in RAM.

Here are some new things that I would like to add to OpenJUMP during the major refactoring:


A default FeatureCollection implementation that is spatially indexed and writeable. I believe this would lead to some significant performance gains, especially for rendering. (The performance of any operation that depends on the query method of the FeatureColleciton interface could be improved.)


Support for validation of feature attribute values with a new AttributeType and FeatureAttributeFilter classes.


The ability to install and update plug-ins from an online plug-in catalog, similar to the way plug-ins are updated in Eclipse.


Integration of the JavaHelp system in a way that allows plug-ins to contribute help topics.
Native Application Launcher for Windows using Launch4J or a similar tool.


Why attempt such a major refactoring now?

There are a couple of reasons that make this a good time. We are discussing the possibility of applying for OSGeo project incubation. That means we will need to have a firm handle on the patent/copyright issues of our code base. What a great opportunity for some house cleaning! Also, my work on the docking window framework has really come to a stand still until I can make some of the changes mentioned above. In addition, the OpenJUMP code base is getting sort of old. There have been a lot of changes to the Java programming language since JUMP was first written, and I think things are starting to get a little cluttered.

The Sunburned Surveyor
Posted on 1:10 PM | Categories: