Make warnings for unkeyed lists disabled by default
[yangtools.git] / tools / yang-model-validator / src / main / java / org / opendaylight / yangtools / yang / validator / Main.java
index 858d7b9e229d2d9ca6b5506bd18ac360afbf5978..b93a4436e2ce8bc81ddaee4a179b3df8554738c1 100644 (file)
@@ -14,19 +14,14 @@ import ch.qos.logback.core.FileAppender;
 import com.google.common.base.Stopwatch;
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
-import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.CommandLineParser;
-import org.apache.commons.cli.DefaultParser;
-import org.apache.commons.cli.HelpFormatter;
-import org.apache.commons.cli.Option;
-import org.apache.commons.cli.OptionGroup;
-import org.apache.commons.cli.Options;
-import org.apache.commons.cli.ParseException;
+import net.sourceforge.argparse4j.ArgumentParsers;
+import net.sourceforge.argparse4j.impl.Arguments;
+import net.sourceforge.argparse4j.inf.ArgumentParser;
+import net.sourceforge.argparse4j.inf.Namespace;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
 import org.slf4j.Logger;
@@ -36,21 +31,7 @@ import org.slf4j.LoggerFactory;
  * Main class of Yang parser system test.
  *
  * <p>
- * yang-system-test [-f features] [-h help] [-p path] [-v verbose] yangFiles...
- *  -f,--features &lt;arg&gt;   features is a string in the form
- *                        [feature(,feature)*] and feature is a string in the form
- *                        [($namespace?revision=$revision)$local_name].
- *                        This option is used to prune the data model by removing
- *                        all nodes that are defined with a "if-feature".
- *  -h,--help             print help message and exit.
- *  -p,--path &lt;arg&gt;       path is a colon (:) separated list of directories
- *                        to search for yang modules.
- *  -r, --recursive       recursive search of directories specified by -p option
- *  -v, --verbose         shows details about the results of test running.
- *  -o, --output          path to output file for logs. Output file will be overwritten.
- *  -m, --module-name     validate yang by module name.
- *  -wul, --warning-for-unkeyed-lists
- *                        add warnings about unkeyed lists with config true.
+ * Type yang-system-test -h for usage.
  */
 @SuppressWarnings({"checkstyle:LoggerMustBeSlf4j", "checkstyle:LoggerFactoryClassParameter"})
 public final class Main {
@@ -59,89 +40,53 @@ public final class Main {
             (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME);
     private static final int MB = 1024 * 1024;
 
-    private static final Option FEATURE = new Option("f", "features", true,
-        "features is a string in the form [feature(,feature)*] and feature is a string in the form "
-                + "[($namespace?revision=$revision)$local_name]. This option is used to prune the data model "
-                + "by removing all nodes that are defined with a \"if-feature\".");
-
-    private static final Option HELP = new Option("h", "help", false, "print help message and exit.");
-    private static final Option MODULE_NAME = new Option("m", "module-name", true,
-            "validate yang model by module name.");
-    private static final Option OUTPUT = new Option("o", "output", true,
-            "path to output file for logs. Output file will be overwritten");
-    private static final Option PATH = new Option("p", "path", true,
-            "path is a colon (:) separated list of directories to search for yang modules.");
-    private static final Option RECURSIVE = new Option("r", "recursive", false,
-            "recursive search of directories specified by -p option.");
-
-    private static final Option DEBUG = new Option("d", "debug", false, "add debug output");
-    private static final Option QUIET = new Option("q", "quiet", false, "completely suppress output.");
-    private static final Option VERBOSE = new Option("v", "verbose", false,
-        "shows details about the results of test running.");
-    private static final Option LIST_WARNING_ON = new Option("wul", "warning-for-unkeyed-lists", false,
-        "add warnings about unkeyed lists with config true");
-    private static final Option LIST_WARNING_OFF = new Option("no-wul", "no-warning-for-unkeyed-lists", false,
-        "do not add warnings about unkeyed lists with config true");
+    private static final String YANG_MODEL = "yang-model";
+    private static final String PATH = "path";
+    private static final String RECURSIVE = "recursive";
+    private static final String UNKEYED_LIST_WARNING_ON = "warning-for-unkeyed-lists";
+    private static final String OUTPUT = "output";
+    private static final String MODULE_NAME = "module-name";
+    private static final String FEATURES = "features";
+    private static final String DEBUG = "debug";
+    private static final String QUIET = "quiet";
+    private static final String VERBOSE = "verbose";
 
     private Main() {
         // Hidden on purpose
     }
 
-    private static Options createOptions() {
-        return new Options()
-            .addOption(HELP)
-            .addOption(PATH)
-            .addOption(RECURSIVE)
-            .addOptionGroup(new OptionGroup().addOption(DEBUG).addOption(QUIET).addOption(VERBOSE))
-            .addOptionGroup(new OptionGroup().addOption(LIST_WARNING_ON).addOption(LIST_WARNING_OFF))
-            .addOption(OUTPUT)
-            .addOption(MODULE_NAME)
-            .addOption(FEATURE);
-    }
-
     public static void main(final String[] args) {
-        final HelpFormatter formatter = new HelpFormatter();
-        final Options options = createOptions();
-        final CommandLine arguments = parseArguments(args, options, formatter);
+        final ArgumentParser parser = getParser();
+        final Namespace arguments = parser.parseArgsOrFail(args);
 
-        if (arguments.hasOption(HELP.getLongOpt())) {
-            printHelp(options, formatter);
-            return;
-        }
-
-        final String[] outputValues = arguments.getOptionValues(OUTPUT.getLongOpt());
+        final String outputValues = arguments.get(OUTPUT);
         if (outputValues != null) {
             setOutput(outputValues);
         }
 
         LOG_ROOT.setLevel(Level.WARN);
-        if (arguments.hasOption(DEBUG.getLongOpt())) {
+        if (arguments.getBoolean(DEBUG)) {
             LOG_ROOT.setLevel(Level.DEBUG);
-        } else if (arguments.hasOption(VERBOSE.getLongOpt())) {
+        } else if (arguments.getBoolean(VERBOSE)) {
             LOG_ROOT.setLevel(Level.INFO);
-        } else if (arguments.hasOption(QUIET.getLongOpt())) {
+        } else if (arguments.getBoolean(QUIET)) {
             LOG_ROOT.detachAndStopAllAppenders();
         }
 
-        final boolean warnForUnkeyedLists;
-        if (arguments.hasOption(LIST_WARNING_ON.getLongOpt()) || !arguments.hasOption(LIST_WARNING_OFF.getLongOpt())) {
-            warnForUnkeyedLists = true;
-        } else {
-            warnForUnkeyedLists = false;
-        }
-
         final List<String> yangLibDirs = initYangDirsPath(arguments);
         final List<String> yangFiles = new ArrayList<>();
-        final String[] moduleNameValues = arguments.getOptionValues(MODULE_NAME.getLongOpt());
+        final List<String> moduleNameValues = arguments.get(MODULE_NAME);
         if (moduleNameValues != null) {
-            yangFiles.addAll(Arrays.asList(moduleNameValues));
+            yangFiles.addAll(moduleNameValues);
+        }
+        if (arguments.get(YANG_MODEL) != null) {
+            yangFiles.addAll(arguments.get(YANG_MODEL));
         }
-        yangFiles.addAll(Arrays.asList(arguments.getArgs()));
 
         final Set<QName> supportedFeatures = initSupportedFeatures(arguments);
 
-        runSystemTest(yangLibDirs, yangFiles, supportedFeatures, arguments.hasOption(RECURSIVE.getLongOpt()),
-            warnForUnkeyedLists);
+        runSystemTest(yangLibDirs, yangFiles, supportedFeatures, arguments.getBoolean(RECURSIVE),
+                arguments.getBoolean(UNKEYED_LIST_WARNING_ON));
 
         LOG_ROOT.getLoggerContext().reset();
     }
@@ -197,23 +142,20 @@ public final class Main {
         printMemoryInfo("after gc");
     }
 
-    private static List<String> initYangDirsPath(final CommandLine arguments) {
+    private static List<String> initYangDirsPath(final Namespace arguments) {
         final List<String> yangDirs = new ArrayList<>();
-        if (arguments.hasOption("path")) {
-            for (final String pathArg : arguments.getOptionValues("path")) {
-                yangDirs.addAll(Arrays.asList(pathArg.split(":")));
-            }
+        final List<String> path = arguments.get(PATH);
+        if (path != null) {
+            yangDirs.addAll(path);
         }
         return yangDirs;
     }
 
-    private static Set<QName> initSupportedFeatures(final CommandLine arguments) {
-        Set<QName> supportedFeatures = null;
-        if (arguments.hasOption("features")) {
-            supportedFeatures = new HashSet<>();
-            for (final String pathArg : arguments.getOptionValues("features")) {
-                supportedFeatures.addAll(createQNames(pathArg.split(",")));
-            }
+    private static Set<QName> initSupportedFeatures(final Namespace arguments) {
+        final Set<QName> supportedFeatures = new HashSet<>();
+        final List<String> features = arguments.get(FEATURES);
+        if (features != null) {
+            supportedFeatures.addAll(createQNames(features.toArray(new String[0])));
         }
         return supportedFeatures;
     }
@@ -223,29 +165,62 @@ public final class Main {
         for (final String featureStr : featuresArg) {
             qnames.add(QName.create(featureStr));
         }
-
         return qnames;
     }
 
-    @SuppressFBWarnings("DM_EXIT")
-    private static CommandLine parseArguments(final String[] args, final Options options,
-            final HelpFormatter formatter) {
-        final CommandLineParser parser = new DefaultParser();
-
-        CommandLine cmd = null;
-        try {
-            cmd = parser.parse(options, args);
-        } catch (final ParseException e) {
-            LOG.error("Failed to parse command line options.", e);
-            printHelp(options, formatter);
-            System.exit(1);
-        }
-
-        return cmd;
-    }
-
-    private static void printHelp(final Options options, final HelpFormatter formatter) {
-        formatter.printHelp("yang-system-test [OPTION...] YANG-FILE...", options);
+    private static ArgumentParser getParser() {
+        final var parser = ArgumentParsers.newFor("yang-system-test").addHelp(true).build()
+                .description("Main class of Yang parser system test.");
+        parser.addArgument(YANG_MODEL)
+                .help("yang file(s) to validate")
+                .dest(YANG_MODEL)
+                .nargs("*")
+                .metavar(YANG_MODEL)
+                .type(String.class);
+        parser.addArgument("-p", "--path")
+                .help("path is a space separated list of directories to search for yang modules")
+                .dest(PATH)
+                .nargs("+")
+                .type(String.class);
+        parser.addArgument("-r", "--recursive")
+                .help("recursive search of directories specified by -p option")
+                .dest(RECURSIVE)
+                .action(Arguments.storeTrue());
+        parser.addArgument("-W", "--warning-for-unkeyed-lists")
+                .help("add warnings about unkeyed lists with config true")
+                .dest(UNKEYED_LIST_WARNING_ON)
+                .action(Arguments.storeTrue());
+        parser.addArgument("-o", "--output")
+                .help("path to output file for logs. Output file will be overwritten")
+                .dest(OUTPUT);
+        parser.addArgument("-m", "--module-name")
+                .help("validate yang model by module name.")
+                .dest(MODULE_NAME)
+                .nargs("+")
+                .type(String.class);
+        parser.addArgument("-f", "--features").help(
+                """
+                features is a space separated list strings in the form [($namespace?revision=$revision)$local_name].
+                This option is used to prune the data model by removing all nodes that are defined with a "if-feature".
+                """)
+                .dest(FEATURES)
+                .nargs("+")
+                .type(String.class);
+        final var group = parser.addMutuallyExclusiveGroup("logging")
+                .description("exclusive group for logging parameters");
+        group.addArgument("-d", "--debug")
+                .help("add debug output")
+                .dest(DEBUG)
+                .action(Arguments.storeTrue());
+        group.addArgument("-q", "--quiet")
+                .help("completely suppress output")
+                .dest(QUIET)
+                .action(Arguments.storeTrue());
+        group.addArgument("-v", "--verbose")
+                .help("shows details about the results of test running")
+                .dest(VERBOSE)
+                .action(Arguments.storeTrue());
+        return parser;
     }
 
     private static void printMemoryInfo(final String info) {