diff --git a/CliArg/src/main/java/org/jsonex/cliarg/CLIParser.java b/CliArg/src/main/java/org/jsonex/cliarg/CLIParser.java index 783c386..27ff251 100644 --- a/CliArg/src/main/java/org/jsonex/cliarg/CLIParser.java +++ b/CliArg/src/main/java/org/jsonex/cliarg/CLIParser.java @@ -1,20 +1,26 @@ package org.jsonex.cliarg; +import lombok.Data; +import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; import org.jsonex.core.util.BeanConvertContext; import org.jsonex.core.util.ClassUtil; +import static org.jsonex.core.util.LangUtil.doIf; +import static org.jsonex.core.util.LangUtil.doIfNotNull; +import static org.jsonex.core.util.ListUtil.isIn; import org.jsonex.jsoncoder.JSONCoder; import org.jsonex.jsoncoder.JSONCoderOption; import org.jsonex.treedoc.TDNode.Type; import org.jsonex.treedoc.json.TDJSONOption; -import lombok.Data; -import lombok.RequiredArgsConstructor; -import lombok.SneakyThrows; -import lombok.extern.slf4j.Slf4j; -import java.util.*; - -import static org.jsonex.core.util.LangUtil.doIf; -import static org.jsonex.core.util.ListUtil.isIn; +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; /** * Parse the input command line arguments against the {@link CLISpec}. The parsed result will be stored in the target @@ -106,7 +112,7 @@ private void parseArg(String arg) { } Param param = spec.indexedParams.get(paramIndex++); missingParams.remove(param.name); - param.property.set(target, parseValue(param, arg)); + doIfNotNull(parseValue(param, arg), v -> param.property.set(target, v)); } private Object parseValue(Param param, String value) { @@ -124,7 +130,8 @@ private Object parseValue(Param param, String value) { ? JSONCoder.decode(value, cls, opt) : JSONCoder.decodeTo(value, param.getProperty().get(target), opt.setMergeArray(true)); } catch (Exception e) { - log.error("Error parsing parameter:" + param.name, e); + errorMessages.put(param.name, value + ";" + e.toString()); + // log.error("Error parsing parameter:" + param.name, e); } return null; } @@ -133,9 +140,9 @@ private Object parseValue(Param param, String value) { public String getErrorsAsString() { StringBuilder sb = new StringBuilder(); - doIf(!missingParams.isEmpty(), () -> sb.append("\nMissing required arguments:" + missingParams)); - doIf(!extraArgs.isEmpty(), () -> sb.append("\nUnexpected arguments:" + extraArgs)); - doIf(!errorMessages.isEmpty(), () -> sb.append("\nError parsing following arguments:" + errorMessages)); + doIf(!missingParams.isEmpty(), () -> sb.append("\nMissing required arguments:").append(missingParams)); + doIf(!extraArgs.isEmpty(), () -> sb.append("\nUnexpected arguments:").append(extraArgs)); + doIf(!errorMessages.isEmpty(), () -> sb.append("\nError parsing following arguments:").append(errorMessages)); return sb.toString(); } } diff --git a/CliArg/src/main/java/org/jsonex/cliarg/CLISpec.java b/CliArg/src/main/java/org/jsonex/cliarg/CLISpec.java index ed069f8..b4155b4 100644 --- a/CliArg/src/main/java/org/jsonex/cliarg/CLISpec.java +++ b/CliArg/src/main/java/org/jsonex/cliarg/CLISpec.java @@ -20,6 +20,7 @@ import static org.jsonex.core.util.ListUtil.setAt; /** + *
* CLI specification based on annotated java bean of `cls`. Following annotations will be processed: * * Class level: @@ -27,9 +28,10 @@ * {@link Summary}: Summary of the command (Optional) * {@link Description}: Description of the command (Optional) * {@link Examples}: Array of string representation of samples usages (Optional) - * * For field level annotations, please refer to class {@link Param} * + *+ * * @param
+ * Represent a command line parameter, it can be either argument or option + * If index is not null indicate it is an argument. + * Argument default to required unless explicitly specified. + * Required argument can't follow non-required argument which index less than it + * If index is null indicates it's an option, option default to not required, unless specified + * For option of Boolean type, it will be mapped as flag, that means the value of the option can be omitted. + * For Param of complex type or array/list, the value can be specified as JSON(ex) string, the top level "{" or "[", * can be, omitted. The quote for key and value can be omitted. - * - * For array parameters, it also possible to specify the values as separate options. The values will be merged - * + + * For array parameters, it is also possible to specify the values as separate options. The values will be merged + * Following Annotation will be processed for each parameter: - * * {@link Name} Name of the parameter, optional, default to field name * {@link ShortName} The optional short name * {@link Description} The optional description * {@link Index} Indicate this an indexed parameter * {@link Required} Indicate if this field is required. all the index fields are required unless explicitly indicated. * All the non-index fields are not required unless explicitly indicated. + **/ @Data public class Param { diff --git a/CliArg/src/test/java/org/jsonex/cliarg/CliParserTest.java b/CliArg/src/test/java/org/jsonex/cliarg/CliParserTest.java index a3ed5a7..2bee19b 100644 --- a/CliArg/src/test/java/org/jsonex/cliarg/CliParserTest.java +++ b/CliArg/src/test/java/org/jsonex/cliarg/CliParserTest.java @@ -49,7 +49,7 @@ public static class Arg1 { @Test public void testParse() { - CLISpec spec = new CLISpec(Arg1.class); + CLISpec