Chapter 14. Loading JSAP Configurations at Runtime with XML

Caution

As of v2.0 this feature should be considered experimental.

In order to keep your program source free of clutter and to support a large number of possible command line syntaxes, JSAP provides a means to load configurations from XML sources at run time. A new contructor with the signature JSAP(URL xmlJSAPSource) has been introduced to support this. It is now very easy to store a number of JSAP configurations in XML files in the same .jar as your application.

Note

This feature requires the XStream .jar from http://xstream.codehaus.org. XStream is an excellent library that provides a simple means to map objects to/from XML. It is made available under a BSD-style license.

Although a .jar is available with JSAP, XStream is in no way affiliated with Martian Software or the JSAP project. Furthermore, you're virtually guaranteed a more up-to-date version of the .jar if you go straight to their website. As a bonus, codehaus hosts a variety of other great projects worth checking out.

The XML syntax for JSAP configurations is designed to closely mirror the sequence of function calls required to manually instantiate a JSAP.

Tip

An Eclipse plug-in for editing JSAP XML files would be very cool. If you're interested in writing one, let me know!

The following example is a reimplementation of the HelloWorld_8 example found earlier in this document.

<jsap>
    <parameters>
        <flaggedOption>
            <id>count</id>
            <stringParser>
                <classname>IntegerStringParser</classname>
            </stringParser> 
            <required>true</required>
            <shortFlag>n</shortFlag>
            <defaults>
                <string>1</string>
            </defaults>
            <help>The number of times to say hello (default=1).</help>
        </flaggedOption>

        <qualifiedSwitch>
            <id>verbose</id>
            <shortFlag>v</shortFlag>
            <longFlag>verbose</longFlag>
            <list>true</list>
            <listSeparator>,</listSeparator>
            <help>Requests verbose output.</help>
        </qualifiedSwitch>
        
        <unflaggedOption>
            <id>name</id>
            <defaults>
                <string>World</string>
            </defaults>
            <required>true</required>
            <greedy>true</greedy>
            <help>One or more names of people you would like to greet.</help>
        </unflaggedOption>

    </parameters>
</jsap>
    public static void main(String[] args) throws Exception {
        JSAP jsap = new JSAP(Manual_HelloWorld_9.class.getResource("Manual_HelloWorld_9.jsap"));
        
        JSAPResult config = jsap.parse(args);    

        if (!config.success()) {
            
            System.err.println();

            // print out specific error messages describing the problems
            // with the command line, THEN print usage, THEN print full
            // help.  This is called "beating the user with a clue stick."
            for (java.util.Iterator errs = config.getErrorMessageIterator();
                    errs.hasNext();) {
                System.err.println("Error: " + errs.next());
            }
            
            System.err.println();
            System.err.println("Usage: java "
                                + Manual_HelloWorld_9.class.getName());
            System.err.println("                "
                                + jsap.getUsage());
            System.err.println();
            System.err.println(jsap.getHelp());
            System.exit(1);
        }
        
        String[] names = config.getStringArray("name");
        String[] languages = config.getStringArray("verbose");
        if (languages.length == 0) languages = new String[] {"en"};
        
        for (int lang = 0; lang < languages.length; ++lang) {
            for (int i = 0; i < config.getInt("count"); ++i) {
                for (int j = 0; j < names.length; ++j) {
                    System.out.println((config.getBoolean("verbose") ? getVerboseHello(languages[lang]) : "Hi")
                                    + ", "
                                    + names[j]
                                    + "!");
                }
            }
        }
    }
    
    private static String getVerboseHello(String language) {
        if ((language == null) || "en".equalsIgnoreCase(language)) {
            return("Hello");
        } else if ("de".equalsIgnoreCase(language)) {
            return("Guten Tag");
        } else {
            return("(Barely audible grunt)");
        }
    }    
[mlamb@morbo]$ java com.martiansoftware.jsap.examples.Manual_HelloWorld_9 -n 2 --verbose Zoidberg
Hello, Zoidberg!
Hello, Zoidberg!


[mlamb@morbo]$ java com.martiansoftware.jsap.examples.Manual_HelloWorld_9 --verbose:de Farnsworth
Guten Tag, Farnsworth!


[mlamb@morbo]$ java com.martiansoftware.jsap.examples.Manual_HelloWorld_9 -v:de,en Branigan
Guten Tag, Branigan!
Hello, Branigan!


[mlamb@morbo]$ java com.martiansoftware.jsap.examples.Manual_HelloWorld_9 Horrible_Gelatanous_Blob
Hi, Horrible_Gelatanous_Blob!