// Path: bin/src/io/github/alechenninger/monarch/apply/ApplyChangesInput.java
// public interface ApplyChangesInput {
//   Optional<String> getHierarchyPathOrYaml();
// 
//   Optional<String> getChangesPathOrYaml();
// 
//   Optional<SourceSpec> getTarget();
// 
//   Optional<String> getDataDir();
// 
//   List<String> getConfigPaths();
// 
//   Optional<String> getOutputDir();
// 
//   List<String> getMergeKeys();
// 
//   boolean isHelpRequested();
// 
//   String getHelpMessage();
// 
//   Optional<YamlConfiguration.Isolate> getYamlIsolate();
// 
// }
// 
// Path: bin/src/io/github/alechenninger/monarch/set/UpdateSetInput.java
// public interface UpdateSetInput {
//   /**
//    * Path of changes to read from and update (or create, if the path does not exist).
//    */
//   Optional<String> getChangesPath();
// 
//   /**
//    * Source for the change we wish to modify or create.
//    */
//   Optional<SourceSpec> getSource();
// 
//   /**
//    * A list of key value pairs to add or replace in the set block of the source's change.
//    *
//    * <p>The list may contain paths to yaml files or inline yaml heterogeneously.
//    */
//   List<String> getPutPathsOrYaml();
// 
//   /**
//    * A list of keys to remove from the set block of the source's change.
//    */
//   List<String> getRemovals();
// 
//   Optional<String> getHierarchyPathOrYaml();
// 
//   List<String> getConfigPaths();
// 
//   boolean isHelpRequested();
// 
//   String getHelpMessage();
// }
// 
// Path: bin/src/io/github/alechenninger/monarch/yaml/YamlConfiguration.java
// public interface YamlConfiguration {
//   YamlConfiguration DEFAULT = new Default();
// 
//   default int indent() {
//     return 2;
//   }
// 
//   default Isolate updateIsolation() {
//     return Isolate.ALWAYS;
//   }
// 
//   enum Isolate {
//     ALWAYS,
//     // TODO: Support WHEN_POSSIBLE
//     // This involves modifying unmanaged portion while maintaining formatting and whitespace.
//     // Not trivial to do.
//     //WHEN_POSSIBLE,
//     NEVER;
//   }
// 
//   /** Extendable for reusable toString */
//   class Default implements YamlConfiguration {
//     @Override
//     public String toString() {
//       return "YamlConfiguration{" +
//           "indent=" + indent() +
//           ", updateIsolation=" + updateIsolation() +
//           '}';
//     }
//   }
// }


import io.github.alechenninger.monarch.apply.ApplyChangesInput;
import io.github.alechenninger.monarch.set.UpdateSetInput;
import io.github.alechenninger.monarch.yaml.YamlConfiguration;
import net.sourceforge.argparse4j.ArgumentParsers;
import net.sourceforge.argparse4j.impl.Arguments;
import net.sourceforge.argparse4j.impl.action.StoreTrueArgumentAction;
import net.sourceforge.argparse4j.inf.Argument;
import net.sourceforge.argparse4j.inf.ArgumentAction;
import net.sourceforge.argparse4j.inf.ArgumentParser;
import net.sourceforge.argparse4j.inf.ArgumentParserException;
import net.sourceforge.argparse4j.inf.MutuallyExclusiveGroup;
import net.sourceforge.argparse4j.inf.Namespace;
import net.sourceforge.argparse4j.inf.Subparser;
import net.sourceforge.argparse4j.inf.Subparsers;
import net.sourceforge.argparse4j.internal.UnrecognizedArgumentException;
import net.sourceforge.argparse4j.internal.UnrecognizedCommandException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.logging.Level;
import java.util.stream.Collectors;
              "When a variable is assigned a value, its implicit assignments are applied " +
              "simultaneously. Assignments may rule out possible values for a variable if those " +
              "values would imply conflicts with known assignments."
          );

      subparser.addArgument("--data-dir", "-d")
          .dest("data_dir")
          .help("Path to where existing data sources life. The data for sources describe in the "
              + "hierarchy is looked using the paths in the hierarchy relative to this folder. "
              + "If not provided, will look for a value in config files with key 'dataDir'.");

      subparser.addArgument("--output-dir", "-o")
          .dest("output_dir")
          .help("Path to directory where result data sources will be written. Data sources will be "
              + "written using relative paths from hierarchy. If not provided, will look for a "
              + "value in config files with key 'outputDir'.");

      subparser.addArgument("--merge-keys", "-m")
          .dest("merge_keys")
          .metavar("MERGE_KEY")
          .nargs("+")
          .help("Space-delimited list of keys which should be inherited with merge semantics. "
              + "That is, normally the value that is inherited for a given key is only the nearest "
              + "ancestor's value. Keys that are in the merge key list however inherit values from "
              + "all of their ancestor's and merge them together, provided they are like types of "
              + "either collections or maps. If not provided, will look for an array value in "
              + "config files with key 'outputDir'.");

      subparser.addArgument("--yaml-isolate")
          .dest("yaml_isolate")
// Path: bin/src/io/github/alechenninger/monarch/apply/ApplyChangesInput.java
// public interface ApplyChangesInput {
//   Optional<String> getHierarchyPathOrYaml();
// 
//   Optional<String> getChangesPathOrYaml();
// 
//   Optional<SourceSpec> getTarget();
// 
//   Optional<String> getDataDir();
// 
//   List<String> getConfigPaths();
// 
//   Optional<String> getOutputDir();
// 
//   List<String> getMergeKeys();
// 
//   boolean isHelpRequested();
// 
//   String getHelpMessage();
// 
//   Optional<YamlConfiguration.Isolate> getYamlIsolate();
// 
// }
// 
// Path: bin/src/io/github/alechenninger/monarch/set/UpdateSetInput.java
// public interface UpdateSetInput {
//   /**
//    * Path of changes to read from and update (or create, if the path does not exist).
//    */
//   Optional<String> getChangesPath();
// 
//   /**
//    * Source for the change we wish to modify or create.
//    */
//   Optional<SourceSpec> getSource();
// 
//   /**
//    * A list of key value pairs to add or replace in the set block of the source's change.
//    *
//    * <p>The list may contain paths to yaml files or inline yaml heterogeneously.
//    */
//   List<String> getPutPathsOrYaml();
// 
//   /**
//    * A list of keys to remove from the set block of the source's change.
//    */
//   List<String> getRemovals();
// 
//   Optional<String> getHierarchyPathOrYaml();
// 
//   List<String> getConfigPaths();
// 
//   boolean isHelpRequested();
// 
//   String getHelpMessage();
// }
// 
// Path: bin/src/io/github/alechenninger/monarch/yaml/YamlConfiguration.java
// public interface YamlConfiguration {
//   YamlConfiguration DEFAULT = new Default();
// 
//   default int indent() {
//     return 2;
//   }
// 
//   default Isolate updateIsolation() {
//     return Isolate.ALWAYS;
//   }
// 
//   enum Isolate {
//     ALWAYS,
//     // TODO: Support WHEN_POSSIBLE
//     // This involves modifying unmanaged portion while maintaining formatting and whitespace.
//     // Not trivial to do.
//     //WHEN_POSSIBLE,
//     NEVER;
//   }
// 
//   /** Extendable for reusable toString */
//   class Default implements YamlConfiguration {
//     @Override
//     public String toString() {
//       return "YamlConfiguration{" +
//           "indent=" + indent() +
//           ", updateIsolation=" + updateIsolation() +
//           '}';
//     }
//   }
// }


// Path: bin/src/io/github/alechenninger/monarch/ArgParseMonarchArgParser.java
import io.github.alechenninger.monarch.apply.ApplyChangesInput;
import io.github.alechenninger.monarch.set.UpdateSetInput;
import io.github.alechenninger.monarch.yaml.YamlConfiguration;
import net.sourceforge.argparse4j.ArgumentParsers;
import net.sourceforge.argparse4j.impl.Arguments;
import net.sourceforge.argparse4j.impl.action.StoreTrueArgumentAction;
import net.sourceforge.argparse4j.inf.Argument;
import net.sourceforge.argparse4j.inf.ArgumentAction;
import net.sourceforge.argparse4j.inf.ArgumentParser;
import net.sourceforge.argparse4j.inf.ArgumentParserException;
import net.sourceforge.argparse4j.inf.MutuallyExclusiveGroup;
import net.sourceforge.argparse4j.inf.Namespace;
import net.sourceforge.argparse4j.inf.Subparser;
import net.sourceforge.argparse4j.inf.Subparsers;
import net.sourceforge.argparse4j.internal.UnrecognizedArgumentException;
import net.sourceforge.argparse4j.internal.UnrecognizedCommandException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.logging.Level;
import java.util.stream.Collectors;

              "When a variable is assigned a value, its implicit assignments are applied " +
              "simultaneously. Assignments may rule out possible values for a variable if those " +
              "values would imply conflicts with known assignments."
          );

      subparser.addArgument("--data-dir", "-d")
          .dest("data_dir")
          .help("Path to where existing data sources life. The data for sources describe in the "
              + "hierarchy is looked using the paths in the hierarchy relative to this folder. "
              + "If not provided, will look for a value in config files with key 'dataDir'.");

      subparser.addArgument("--output-dir", "-o")
          .dest("output_dir")
          .help("Path to directory where result data sources will be written. Data sources will be "
              + "written using relative paths from hierarchy. If not provided, will look for a "
              + "value in config files with key 'outputDir'.");

      subparser.addArgument("--merge-keys", "-m")
          .dest("merge_keys")
          .metavar("MERGE_KEY")
          .nargs("+")
          .help("Space-delimited list of keys which should be inherited with merge semantics. "
              + "That is, normally the value that is inherited for a given key is only the nearest "
              + "ancestor's value. Keys that are in the merge key list however inherit values from "
              + "all of their ancestor's and merge them together, provided they are like types of "
              + "either collections or maps. If not provided, will look for an array value in "
              + "config files with key 'outputDir'.");

      subparser.addArgument("--yaml-isolate")
          .dest("yaml_isolate")
          .choices(Arrays.stream(YamlConfiguration.Isolate.values())