Utilities

TM4J provides a collection of utility classes that provide high-level services for accessing and manipulating topic map data. The most important of these are the TopicMapUtils , TopicMapHandler and IDGenerator interfaces; and the TopicMapWalker and IDGeneratorFactory classes.

TopicMapUtils

The interface org.tm4j.topicmap.TopicMapUtils defines a set of indexes and utility functions for manipulating the topic map objects in a single topic map. Amongst these are functions to retrieve all objects of a specific type; retrieve all objects in a specific scope; and to extract a name from a topic suitable for either display or sorting. Every implementation of the TopicMap interface must provide access to an object implementing the TopicMapUtils interface through the function getUtils(). The default implementation of the TopicMapUtils interface, org.tm4j.topicmap.TopicMapUtilsImpl is suitable for use with any implementation of the TopicMap interface, building all the necessary indexes in memory on creation. Alternate implementations of the TM4J interfaces are free to also provide alternate implementations of the TopicMapUtils interface, which may make use of the technology of the underlying data store to provide more efficient implementations of the indexes or functions (e.g. an implementation built on a database may use database queries in place of the in-memory indexes created by the default implementation).

The methods of this interface are documented in the Javadoc for org.tm4j.topicmap.TopicMapUtils.

TopicMapWalker

The org.tm4j.topicmap.utils.TopicMapWalker class is a utility class that enumerates the contents of a TopicMap. The walker visits each topic and association in the topic map in turn, generating events to represent the objects found in the topic map. These events are delivered through the WalkerHandler interface. For objects which may contain other topic map objects, the WalkerHandler will receive a startXXX() event followed by events representing the contained objects and, all of the contained objects are read, the handler will then receive an endXXX() event. For objects which will never contain other objects, the event is reported using a single call to onXXX() in the WalkerHandler interface. The boolean return value from the startXXX() method can be used to skip contained objects. If the WalkerHandler returns false from the startXXX() method, then the TopicMapWalker will skip all of the contained objects and will not call the endXXX() method.

In addition to the WalkerHandler interface, the org.tm4j.topicmap.utils package also defines a WalkerFilter interface. The WalkerFilter extends WalkerHandler to add the method setHandler(). This enables a second handler to be chained on to the end of a WalkerFilter object. The class org.tm4j.topicmap.utils.WalkerFilterAdapter provides the basic logic for a filter. When creating your own filters, create a class which extends WalkerFilterAdapter and provide the logic for the startXXX(), endXXX() and onXXX() methods. Within those methods, if you choose to skip an object on a startXXX() event, simply return false. For all other methods or if you want to process the content of an object from a startXXX() event, you should call the matching method in the base class (e.g. in startTopic(Topic t), you should finish with the line:

super.startTopic(t);

IDGenerator and IDGeneratorFactory

In working with topic maps, it is often necessary to generate unique identifiers - especially when creating topics and associations (which both require a value to be assigned to their resourceID property). The API for generation of identifiers is defined by the interface org.tm4j.topicmap.utils.IDGenerator and a default implementation is provided by the class org.tm4j.topicmap.utils.IDGeneratorImpl. The default implementation generates an identifier based on the current system time (in milliseconds). Both the XTMParser and TopicMapFactoryImpl classes use an IDGenerator for creating IDs of the topics and associations which are 'implicit' in the topic map (see the section called “Collection Properties”, below, for more details).

Note

The default IDGenerator implementation uses current system time at the time the object was created followed by an incrementing number. This may lead to problems when two IDGenerator objects are created in quick succession - if the two objects are created within the same 'tick' of the system clock, it is possible that you will get duplicate identifiers created. For this reason it is suggested that where possible you use only a single IDGenerator of this implementation in any given application.

You may provide your own implementation of this very simple interface and make it the default by setting the system property org.tm4j.topcimap.idGenerator to the name of the class which implements an IDGenerator interface - the default parser and the implicit object creation routines will then use an instance of this new class for generating new IDs.

The IDGeneratorFactory class provides an easy way of retrieving the implementation of the IDGenerator interface that has been specified by the system property. Calling the function newIDGenerator() returns a new instance of the class specified by the system property settings. If no value was specified for the system property settings, or the class specified was not found or could not be instantiated, then the factory will return a new instance of the default org.tm4j.topicmap.utils.IDGeneratorImpl class.

Extractors and Testers

In addition to the utilty classes described above, TM4J provides a set of functional components which provide simple testing and value extraction capabilities. These may be combined and used in conjunction with collections of objects for purposes such as filtering, sorting and transformation. These utilities are described in more detail in Chapter 7, TM4J Utilities