private static String setUpOptions()

in shell/src/main/java/org/apache/accumulo/shell/commands/SetIterCommand.java [200:342]


  private static String setUpOptions(ClassLoader classloader, final LineReader reader,
      final PrintWriter writer, final String className, final Map<String,String> options)
      throws IOException, ShellCommandException {
    String input;
    SortedKeyValueIterator<Key,Value> skvi;
    String clazzName;
    try {
      @SuppressWarnings("unchecked")
      var clazz = (Class<? extends SortedKeyValueIterator<Key,Value>>) classloader
          .loadClass(className).asSubclass(SortedKeyValueIterator.class);
      clazzName = clazz.getName();
      skvi = clazz.getDeclaredConstructor().newInstance();
    } catch (ReflectiveOperationException e) {
      StringBuilder msg = new StringBuilder("Unable to load ").append(className);
      if (className.indexOf('.') < 0) {
        msg.append("; did you use a fully qualified package name?");
      } else {
        msg.append("; class not found.");
      }
      throw new ShellCommandException(ErrorCode.INITIALIZATION_FAILURE, msg.toString());
    } catch (ClassCastException e) {
      String msg = className + " loaded successfully but does not implement SortedKeyValueIterator."
          + " This class cannot be used with this command.";
      throw new ShellCommandException(ErrorCode.INITIALIZATION_FAILURE, msg);
    }

    OptionDescriber iterOptions = null;
    if (OptionDescriber.class.isAssignableFrom(skvi.getClass())) {
      iterOptions = (OptionDescriber) skvi;
    }

    String iteratorName;
    if (iterOptions != null) {
      final IteratorOptions itopts = iterOptions.describeOptions();
      iteratorName = itopts.getName();

      if (iteratorName == null) {
        throw new IllegalArgumentException(
            className + " described its default distinguishing name as null");
      }
      String shortClassName = className;
      if (className.contains(".")) {
        shortClassName = className.substring(className.lastIndexOf('.') + 1);
      }
      final Map<String,String> localOptions = new HashMap<>();
      do {
        // clean up the overall options that caused things to fail
        for (String key : localOptions.keySet()) {
          options.remove(key);
        }
        localOptions.clear();

        writer.println(itopts.getDescription());

        String prompt;
        if (itopts.getNamedOptions() != null) {
          for (Entry<String,String> e : itopts.getNamedOptions().entrySet()) {
            prompt = Shell.repeat("-", 10) + "> set " + shortClassName + " parameter " + e.getKey()
                + ", " + e.getValue() + ": ";
            writer.flush();
            input = reader.readLine(prompt);

            if (input == null) {
              writer.println();
              throw new IOException("Input stream closed");
            }
            // Places all Parameters and Values into the LocalOptions, even if the value is "".
            // This allows us to check for "" values when setting the iterators and allows us to
            // remove
            // the parameter and value from the table property.
            localOptions.put(e.getKey(), input);
          }
        }

        if (itopts.getUnnamedOptionDescriptions() != null) {
          for (String desc : itopts.getUnnamedOptionDescriptions()) {
            writer.println(Shell.repeat("-", 10) + "> entering options: " + desc);
            input = "start";
            prompt = Shell.repeat("-", 10) + "> set " + shortClassName
                + " option (<name> <value>, hit enter to skip): ";
            while (true) {
              writer.flush();
              input = reader.readLine(prompt);
              if (input == null) {
                writer.println();
                throw new IOException("Input stream closed");
              } else {
                input = new String(input);
              }

              if (input.isEmpty()) {
                break;
              }

              String[] sa = input.split(" ", 2);
              localOptions.put(sa[0], sa[1]);
            }
          }
        }

        options.putAll(localOptions);
        if (!iterOptions.validateOptions(options)) {
          writer.println("invalid options for " + clazzName);
        }

      } while (!iterOptions.validateOptions(options));
    } else {
      writer.flush();
      writer.println("The iterator class does not implement OptionDescriber."
          + " Consider this for better iterator configuration using this setiter command.");
      iteratorName = reader.readLine("Name for iterator (enter to skip): ");
      if (iteratorName == null) {
        writer.println();
        throw new IOException("Input stream closed");
      } else if (iteratorName.isBlank()) {
        // Treat whitespace or empty string as no name provided
        iteratorName = null;
      }

      writer.flush();
      writer.println("Optional, configure name-value options for iterator:");
      String prompt = Shell.repeat("-", 10) + "> set option (<name> <value>, hit enter to skip): ";
      final HashMap<String,String> localOptions = new HashMap<>();

      while (true) {
        writer.flush();
        input = reader.readLine(prompt);
        if (input == null) {
          writer.println();
          throw new IOException("Input stream closed");
        } else if (input.isBlank()) {
          break;
        }

        String[] sa = input.split(" ", 2);
        localOptions.put(sa[0], sa[1]);
      }

      options.putAll(localOptions);
    }

    return iteratorName;
  }