Sunday Sep 07, 2008

Dealing with Helpsets from 3rd Party JARs

Let's say you have an application on top of the NetBeans Platform. One of the application's modules does nothing more than wrap a 3rd party library. However, within that 3rd party library is a helpset that you'd like to integrate into your own application's helpset. How do you integrate that helpset, i.e., one that is within a 3rd party JAR, into your own application?

You could, of course, simply manually copy the help files from the 3rd party helpset and paste them into one of the modules in your suite that already provides a helpset. That solution presents two problems, however. Firstly, you now have the same HTML files in two places—within the 3rd party JAR as well as within the module that integrates them into the application's helpset. That's not very convenient and your application is now potentially much larger than it needs to be. Secondly, what happens when the JAR is updated? The helpset is then potentially modified and you'll need to copy them over again, again manually. Not convenient either.

So the better solution is to add an Ant script to your build process. The Ant script will, at whatever point in your build process that it is convenient to do so, unjar the 3rd pary JAR, create a scratch folder, copy the complete content of the 3rd party JAR into the scratch folder, and then copy the relevant folder (i.e., the 'help' folder) into the module that will provide the helpset. So long as the "helpsetref" tag in your helpset.xml file points to the "hs" file that is expanded into the module, everything will work seamlessly and you'll have a single source for the helpset. In other words, you'll not check any help topics into your CVS. Instead, you'll recreate the helpset on the fly, as needed, and the HTML files will always be within the JAR file:

<target name="create-marvin-help" description="Get help topics from JAR">

    <property name="help.dir" location="../modules/MarvinHelp/javahelp/com/im/ijc/marvinhelp/help"/>
    <property name="scratch.dir" location="../modules/MarvinHelp/scratch"/>

    <delete dir="${help.dir}"/>
    <mkdir dir="${help.dir}"/>

    <mkdir dir="${scratch.dir}"/>
    <unjar  src="../libraries/JChem/release/modules/ext/jchem.jar" dest="${scratch.dir}"/>
    <copy todir="${help.dir}">
        <fileset dir="${scratch.dir}/help">
            <include name="\*\*"/>
    <delete dir="${scratch.dir}"/>


The downside of this approach is that you now have no control over the helpset at all, since you're simply unjarring it on the fly. In other words, you need to take the settings and content provided by the JAR as given, there's no way for you to change them. For example, if 'expand=false' is not set in the TOC, and you don't want the top node to be expanded, there's nothing you can do since you're using the TOC from the JAR, rather than one you have control over within your module.

The Possibility of a Translation

"Damit Service Provider einem System dynamisch und flexibel hinzugefügt werden können, also auch dann noch, wenn eine Anwendung bereits ausgeliefert wurde, und erst dann geladen werden, wenn sie auch wirklich benötigt werden, werden diese deklarativ, also über Konfigurationsdateien, registriert."

The above sentence encapsulates the wonderfulness of the German language! What I absolutely love about it is the fact that its VERB is "registriert". :-) I.e., the very last word in that whole long sentence. (And the fact that about 5 separate facts are transmitted, and need to be digested, before one gets to that point! The reader's had a lot to chew on at that stage, having gained an unlikely wealth of knowledge before being permitted to draw breath again.) I also like the word "Damit" which is a firm start to a sentence (like "Now" at the start of Richard III), even though it meanders (albeit very strongly and declaratively, like a purposeful guide in a jungle slashing a path resolutely off the beaten track, heading towards a goal that those under his care can do no more than guess at), only to return to its original path right at the end. Translated more or less directly, the above means the below:

"In order for a service provider to be added dynamically and flexibly to an application, even when the application has already been released, and in order for it to be loaded only when it is actually needed, the service provider is registered declaratively, that is, by means of configuration data."

Bear in mind that I cheated quite a bit in the above translation and that I went out of my way to put everything into a single sentence. Had I been 'honest', I would have translated "diese" to "it", instead of "the service provider". It's cool how dangling participles are not a problem in German, apparently. But the above sounds, despite my overcompensations, quite unnatural in English, and having "in order for" twice (even once) in a sentence is clunky and the sentence as a whole misses the modern American-style friendliness common to just about everything nowadays. So maybe it should be translated as follows instead:

"You register service providers declaratively, that is, using configuration data. One advantage of this approach is that you can add service providers dynamically, even after you've distributed the application to your users. Another advantage is that the service provider will only be loaded once your users actually need to make use of it."

The human actors, missing from the original, have been injected back into the sequence of events. The sentence has been broken into manageable chunks. (Even a contraction, to show we're all nice and down to earth!) The reader, the ever-smiling "you" is present again (calmly reading by the fire, a comforting whisky at hand, echoing the rational lord of the manor down the ages, the glow of a laptop screen replacing the hearth, a grubby t-shirt instead of a double-breasted suit). However, the emphasis of the original is lost. But, then again, I'm not sure whether the German original had an emphasis to begin with. Perhaps the original emphasis was the declarative nature of the registration, while my translation above emphasizes the advantages of declarative registration. The latter, though, is what I believe to be the more important point. That, in turn, brings one into the ethical issues relating to translation. Should one try to improve the original? And who is to say that your personal preferences are improvements at all?


Geertjan Wielenga (@geertjanw) is a Principal Product Manager in the Oracle Developer Tools group living & working in Amsterdam. He is a Java technology enthusiast, evangelist, trainer, speaker, and writer. He blogs here daily.

The focus of this blog is mostly on NetBeans (a development tool primarily for Java programmers), with an occasional reference to NetBeans, and sometimes diverging to topics relating to NetBeans. And then there are days when NetBeans is mentioned, just for a change.


« September 2008 »