Top Description Inners Fields Constructors Methods
org.glassfish.pfl.basic.tools.argparser

public Class ArgParser

extends Object
Class Inheritance
Imports
java.lang.reflect.Array, .InvocationHandler, .Method, .Proxy, java.net.URL, java.util.ArrayList, .Arrays, .Collection, .Collections, .HashMap, .List, .Map, .Set, org.glassfish.pfl.basic.contain.Pair

A general purpose argument parser that uses annotations, reflection, and generics.

This class solves a simple problem: How do I write an argument parser that parses arguments of the form

-xxx value

There are many ways of doing this: the ORB has probably at least 6 different ways of attacking this problem (and I wrote half of them). The approach taken here is to start with an interface, annotate it to indicate some information (like default values) for parsing, and then use reflection to produce an implementation of the interface that uses a dynamic proxy.

The argument parsing is entirely specified in terms of an interface with annotated methods. The name of the method is the name used as a -xxx argument when parsing the data. The type of data determines the valid inputs for the argument. All arguments must be in the -xxx yyy form, where yyy is a valid input for the type of method xxx() in the interface.

The interface is very simply: just create an ArgParser of the appropriate type, and then call parse( String[] ) to get an instance of the interface. There is also a getHelpText() method that returns a String with formatted information about all the valid arguments for this parser.

Not all required information can be derived from the method type and name. Some annotations are defined for additional information:

  1. @DefaultValue. This gives a String that is used to construct a default value for the given method.
  2. @Separator. This is used to override the default "," separator used for lists of values for fields of type List<Type> or Type[].
  3. @Help. This is used to give any help text for the field that is displayed by the getHelpText method.
TODO:
  1. Support I18N for this (required before it could be used for public parts of the ORB).
  2. Support Set<Type> Similar to list, but all elements must be unique.
  3. Support Map<Type,Type>
  4. Do we want to support really complex types, like Map<String,List<Map<String,Foo>>> How would we specify needed separators?
  5. Should we extend along the lines of the ORB arg parser, with an embedded language to describe how to parse a String?
  6. Extend this to support property parsing as well (required for ORB.init parsing). Probably just want to parse Properties as well as String[]. This requires some way to handle the property prefix (as in -ORBInitHost and org.omg.CORBA.ORBInitHost).
  7. Extend to support abstract classes. Only non-private abstract methods that are read-only beans and are annotated with @DefaultValue can be set by the parser. Other methods are allowed, but not used by the parser.
  8. Support an @Complete annotation. All such methods must be void(), and are executed in some order after the parsing is complete.
  9. Add an @Keyword notation to override the default name of the argument (the method name). This allows having different names for the methods and the arguments. Note that this can be used for fully-qualified property names. This supports the ORB dual use of properties and arguments (with perhaps a little fudging for things like ORBInitRef: if there are multiple args, concat them together and use a list separator?)
  10. Add an @ClassName annotation that takes no arguments. This means that the string passed must be the name of a class that has a no-args constructor. The class must be assignment compatible with the return type of the annotated method. At parse time, we just load the class named by the string and create a new instance of it.
  11. Consider using apt for this. This solves two problems:
    1. We can generate a more efficient class than the current version that uses a dynamic proxy and a table lookup. This becomes important when we consider that ORBData may be referenced many times during an invocation.
    2. We can generate much of the required ORBConstants (say as ORBPropertyNames) directly from the annotated interface.
  12. Most of the extensions here are aimed at reducing the code size of the ORB data stuff.
  13. If we don't want to use apt:
    1. Use codegen to generate a class that implements the argument interface.
    2. Instead of generating ORBConstants, look things up from it using static reflection on the name of the constant. This would require some other annotations:
      1. @IndirectKeyword gives the name of the constant in the @ConstantClass to look for. Do we need multiple constant classes?
      2. @ConstantClass would give the class to use for looking up public static final constants for @IndirectKeyword, which is like @Keyword.
Summary of current and proposed annotations:
  1. @DefaultValue: current method-level takes string
  2. @Separator: current method-level takes string
  3. @Help: current method-level takes string
  4. @ConstantClass: proposed class-level takes class constant
  5. @Complete: proposed method-level marker
  6. @Keyword: proposed method-level takes string
  7. @IndirectKeyword: proposed method-level takes string
  8. @ClassName: proposed method-level marker
Author
Ken Cavanaugh

Nested and Inner Type Summary

Modifier and TypeClass and Description
private static enum
public static class
ArgParser.StringPair

Useful utility class for parsing pairs of strings.

private static interface
private static interface

Field Summary

Modifier and TypeField and Description
private final Map<String, Object>
private final Map<String, String>
private final List<Class<?>>
private final Map<String, ElementParser>

Constructor Summary

AccessConstructor and Description
public
ArgParser(final Class<?> cls)

Construct an ArgParser that parses an argument string into an instance of the Class argument.

public
ArgParser(final List<Class<?>> classes)

Method Summary

Modifier and TypeMethod and Description
private String
private String
display(final Object obj)

private void
error(final String msg)

public String
getHelpText()

Returns a formatted text string that describes the expected arguments for this parser.

private String
getKeyword(final String arg)

private void
init(final Class<?> cls)

private void
init(final List<Class<?>> classes)

private void
internalParse(final Map<String, String> data, Map<String, Object> result)

public static void
main(String[] args)

private Map<String, String>
makeMap(final String[] args)

private Object
makeProxy(final Map<String, Object> data)

public Object
parse(final String[] args)

Parse the argument string into an instance of type T.

public <T> T
parse(final String[] args, final Class<T> cls)

Inherited from java.lang.Object:
cloneequalsfinalizegetClasshashCodenotifynotifyAlltoStringwaitwaitwait

Field Detail

defaultValuesback to summary
private final Map<String, Object> defaultValues
helpTextback to summary
private final Map<String, String> helpText
interfaceClassesback to summary
private final List<Class<?>> interfaceClasses
parserDataback to summary
private final Map<String, ElementParser> parserData

Constructor Detail

ArgParserback to summary
public ArgParser(final Class<?> cls)

Construct an ArgParser that parses an argument string into an instance of the Class argument. cls must be an interface. Each method in this interface must take no arguments. Each method must be annotated with a DefaultValue annotation. Each method must return one of the following types:

  • A primitive type
  • A String type
  • A type that has a public constructor that takes a single String argument
  • An Enum
  • A List parameterized by one of the above types
  • An array of one of the first four types
The name of the method is the name of the keyword.
ArgParserback to summary
public ArgParser(final List<Class<?>> classes)

Method Detail

checkMethodback to summary
private String checkMethod(final Method m)
displayback to summary
private String display(final Object obj)
errorback to summary
private void error(final String msg)
getHelpTextback to summary
public String getHelpText()

Returns a formatted text string that describes the expected arguments for this parser.

getKeywordback to summary
private String getKeyword(final String arg)
initback to summary
private void init(final Class<?> cls)
initback to summary
private void init(final List<Class<?>> classes)
internalParseback to summary
private void internalParse(final Map<String, String> data, Map<String, Object> result)
mainback to summary
public static void main(String[] args)
makeMapback to summary
private Map<String, String> makeMap(final String[] args)
makeProxyback to summary
private Object makeProxy(final Map<String, Object> data)
parseback to summary
public Object parse(final String[] args)

Parse the argument string into an instance of type T.

parseback to summary
public <T> T parse(final String[] args, final Class<T> cls)
org.glassfish.pfl.basic.tools.argparser back to summary

private final Enum ArgParser.PrimaryColor

extends Enum<ArgParser.PrimaryColor>
Class Inheritance

Field Summary

Modifier and TypeField and Description
public static final ArgParser.PrimaryColor
public static final ArgParser.PrimaryColor
public static final ArgParser.PrimaryColor

Constructor Summary

AccessConstructor and Description
private

Method Summary

Modifier and TypeMethod and Description
public static ArgParser.PrimaryColor
public static ArgParser.PrimaryColor[]
Inherited from java.lang.Enum:
clonecompareTodescribeConstableequalsfinalizegetDeclaringClasshashCodenameordinaltoStringvalueOf

Field Detail

BLUEback to summary
public static final ArgParser.PrimaryColor BLUE
GREENback to summary
public static final ArgParser.PrimaryColor GREEN
REDback to summary
public static final ArgParser.PrimaryColor RED

Constructor Detail

PrimaryColorback to summary
private PrimaryColor()

Method Detail

valueOfback to summary
public static ArgParser.PrimaryColor valueOf(String name)
valuesback to summary
public static ArgParser.PrimaryColor[] values()
org.glassfish.pfl.basic.tools.argparser back to summary

public Class ArgParser.StringPair

extends Pair<String, String>
Class Inheritance

Useful utility class for parsing pairs of strings.

Field Summary

Inherited from org.glassfish.pfl.basic.contain.Pair:
_first_second

Constructor Summary

AccessConstructor and Description
public
StringPair(String first, String second)

public
StringPair(String
The string to parse into a StringPair.
data
)

Construct a StringPair from data of the first first:second.

Method Summary

Inherited from org.glassfish.pfl.basic.contain.Pair:
equalsfirsthashCodesecondtoString

Constructor Detail

StringPairback to summary
public StringPair(String first, String second)
StringPairback to summary
public StringPair(String data)

Construct a StringPair from data of the first first:second.

Parameters
data:String

The string to parse into a StringPair.

org.glassfish.pfl.basic.tools.argparser back to summary

private Interface ArgParser.TestInterface1


Method Summary

Modifier and TypeMethod and Description
public ArgParser.PrimaryColor
public String
lake()

public int

Method Detail

colorback to summary
public ArgParser.PrimaryColor color()
Annotations
@DefaultValue:RED
@Help:Pick a color
lakeback to summary
public String lake()
Annotations
@DefaultValue:Michigan
@Help:The name of a lake
valueback to summary
public int value()
Annotations
@DefaultValue:27
@Help:An integer value
org.glassfish.pfl.basic.tools.argparser back to summary

private Interface ArgParser.TestInterface2


Method Summary

Modifier and TypeMethod and Description
public ArgParser.StringPair[]
public List<ArgParser.StringPair>
public URL
url()

Method Detail

arrayDataback to summary
public ArgParser.StringPair[] arrayData()
Annotations
@DefaultValue:funny:thing,another:thing,something:else
@Help:A list of pairs of the form xxx:yyy
@Separator:,
listDataback to summary
public List<ArgParser.StringPair> listData()
Annotations
@DefaultValue:funny:thing,another:thing,something:else
@Help:A list of pairs of the form xxx:yyy
@Separator:,
urlback to summary
public URL url()
Annotations
@DefaultValue:http://www.sun.com
@Help:your favorite URL