Args4j の EnumOptionHandler の使い方を記載します。
Args4j の version
'2.33'
を使用しています。
// https://mvnrepository.com/artifact/args4j/args4j
compile group: 'args4j', name: 'args4j', version: '2.33'
使い方
Option アノテーションを使用する場合は、以下のように記載します。
@Option(name = "-format", usage = "Format of output ", metaVar = "[console or json]")
private Format format = Format.CONSOLE;
- Field の型を指定したい Enum にする。
- Handler は指定しない。
Handler を指定するとどうなるか?
handler を指定すると以下のように書けます。
@Option(name = "-format", usage = "Format of output ", metaVar = "[console or json]", handler = EnumOptionHandler.class)
private Format format = Format.CONSOLE;
この状態で Command を実行すると、以下のエラーが発生します。
Caused by: java.lang.IllegalArgumentException: class org.kohsuke.args4j.spi.EnumOptionHandler does not have the proper constructor
at org.kohsuke.args4j.OptionHandlerRegistry.getConstructor(OptionHandlerRegistry.java:111) ~[args4j-2.33.jar!/:na]
at org.kohsuke.args4j.OptionHandlerRegistry.access$000(OptionHandlerRegistry.java:43) ~[args4j-2.33.jar!/:na]
at org.kohsuke.args4j.OptionHandlerRegistry$DefaultConstructorHandlerFactory.<init>(OptionHandlerRegistry.java:217) ~[args4j-2.33.jar!/:na]
at org.kohsuke.args4j.OptionHandlerRegistry.createOptionHandler(OptionHandlerRegistry.java:188) ~[args4j-2.33.jar!/:na]
Args4j には、handler を登録する機能があり、試しに Enum のHanlder を登録してみたのですが、結果は変わりませんでした。
// registerHandler
OptionHandlerRegistry.OptionHandlerFactory factory = (parser, o, setter) -> {
// infer the type
Class<?> t = setter.getType();
return new EnumOptionHandler(parser,o,setter,t);
};
OptionHandlerRegistry.getRegistry().registerHandler(Format.class, factory);
OptionHandlerRegistry#createOptionHandler() の動作について
以下、args4j/OptionHandlerRegistry.java at master · kohsuke/args4j の createOptionHandler
の抜粋です。
指定されたアノテーション、パラメータの型を元に、使用する Handler
を取得する処理になります。
/**
* Creates an {@link OptionHandler} that handles the given {@link Option} annotation
* and the {@link Setter} instance.
*/
@SuppressWarnings("unchecked")
protected OptionHandler createOptionHandler(CmdLineParser parser, OptionDef o, Setter setter) {
checkNonNull(o, "CmdLineParser");
checkNonNull(o, "OptionDef");
checkNonNull(setter, "Setter");
Class<? extends OptionHandler> h = o.handler();
if(h==OptionHandler.class) {
// infer the type
Class<?> t = setter.getType();
// enum is the special case
if(Enum.class.isAssignableFrom(t))
return new EnumOptionHandler(parser,o,setter,t);
OptionHandlerFactory factory = handlers.get(t);
if (factory==null)
throw new IllegalAnnotationError(Messages.UNKNOWN_HANDLER.format(t));
return factory.getHandler(parser, o, setter);
} else {
// explicit handler specified
return new DefaultConstructorHandlerFactory(h).getHandler(parser, o, setter);
}
}
OptionHalder を指定すると、else のほうに処理が流れて、EnumOptionHandler
は、Constructor の引数が4つなので、DefaultConstructorHandlerFactory
の getHandler
メソッドでは、インスタンス化できずエラーになるようです。
最初に、handler を指定する形式で実装して、エラーが出てはまってしまいました。
以上です。
コメント