code: // Licensed to the Software Freedom Conservancy (SFC) under one
  // or more contributor license agreements.  See the NOTICE file
  // distributed with this work for additional information
  // regarding copyright ownership.  The SFC licenses this file
  // to you under the Apache License, Version 2.0 (the
  // "License"); you may not use this file except in compliance
  // with the License.  You may obtain a copy of the License at
  //
  //   http://www.apache.org/licenses/LICENSE-2.0
  //
  // Unless required by applicable law or agreed to in writing,
  // software distributed under the License is distributed on an
  // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  // KIND, either express or implied.  See the License for the
  // specific language governing permissions and limitations
  // under the License.
  
  package org.openqa.selenium.grid.config;
  
  import static org.openqa.selenium.grid.config.StandardGridRoles.ALL_ROLES;
  
  import com.beust.jcommander.Parameter;
  import com.google.common.collect.ImmutableMap;
  import com.google.common.collect.ImmutableSet;
  import com.google.common.collect.ImmutableSortedSet;
  import java.io.PrintStream;
  import java.nio.file.Path;
  import java.util.Arrays;
  import java.util.List;
  import java.util.Map;
  import java.util.Set;
  import java.util.TreeMap;
  import java.util.stream.Collectors;
  import org.openqa.selenium.json.Json;
  
  public class ConfigFlags implements HasRoles {
  
    private static final ImmutableSet<String> IGNORED_SECTIONS =
        ImmutableSet.of("java", "lc", "term");
  
    @Parameter(
        names = "--config",
        description = "Config file to read from (may be specified more than once)")
    private List<Path> configFiles;
  
    @Parameter(
        names = "--dump-config",
        description = "Dump the config of the server as JSON.",
        hidden = true)
    private boolean dumpConfig;
  
    @Parameter(
        names = "--config-help",
        description = "Output detailed information about config options")
    private boolean dumpConfigHelp;
  
    @Override
    public Set<Role> getRoles() {
      return ALL_ROLES;
    }
  
    public Config readConfigFiles() {
      if (configFiles == null || configFiles.isEmpty()) {
        return new MapConfig(ImmutableMap.of());
      }
  
      return new CompoundConfig(configFiles.stream().map(Configs::from).toArray(Config[]::new));
    }
  
    public boolean dumpConfig(Config config, PrintStream dumpTo) {
      if (!dumpConfig) {
        return false;
      }
  
      Map<String, Map<String, Object>> toOutput = new TreeMap<>();
      for (String section : config.getSectionNames()) {
        if (section.isEmpty() || IGNORED_SECTIONS.contains(section)) {
          continue;
        }
  
        config
            .getOptions(section)
            .forEach(
                option ->
                    config
                        .get(section, option)
                        .ifPresent(
                            value ->
                                toOutput
                                    .computeIfAbsent(section, ignored -> new TreeMap<>())
                                    .put(option, value)));
      }
  
      dumpTo.print(new Json().toJson(toOutput));
  
      return true;
    }
  
    public boolean dumpConfigHelp(Config config, Set<Role> currentRoles, PrintStream dumpTo) {
      if (!dumpConfigHelp) {
        return false;
      }
  
      Map<String, Set<DescribedOption>> allOptions =
          DescribedOption.findAllMatchingOptions(currentRoles).stream()
              .collect(
                  Collectors.toMap(
                      DescribedOption::section,
                      ImmutableSortedSet::of,
                      (l, r) ->
                          ImmutableSortedSet.<DescribedOption>naturalOrder()
                              .addAll(l)
                              .addAll(r)
                              .build()));
  
      StringBuilder demoToml = new StringBuilder();
      demoToml.append("Configuration help for Toml config file").append("\n\n");
      demoToml
          .append("In case of parsing errors, validate the config using https://www.toml-lint.com/")
          .append("\n\n");
      demoToml.append("Refer https://toml.io/en/ for TOML usage guidance").append("\n\n");
      allOptions.forEach(
          (section, options) -> {
            demoToml.append("[").append(section).append("]\n");
            options.stream()
                .filter(option -> !option.hidden)
                .forEach(
                    option -> {
                      if (!option.optionName.isEmpty()) {
                        demoToml.append("# ").append(option.description).append("\n");
                      }
                      demoToml.append("# Type: ").append(option.type).append("\n");
                      if (!option.defaultValue.isEmpty()) {
                        demoToml.append("# Default: ").append(option.defaultValue).append("\n");
                      }
                      Arrays.stream(option.example())
                          .forEach(
                              example -> {
                                demoToml.append("# Example: ").append("\n");
                                if (option.prefixed) {
                                  demoToml
                                      .append("[[")
                                      .append(section)
                                      .append(".")
                                      .append(option.optionName)
                                      .append("]]")
                                      .append(option.example(config, example))
                                      .append("\n\n");
                                } else {
                                  demoToml
                                      .append(option.optionName)
                                      .append(" = ")
                                      .append(option.example(config, example))
                                      .append("\n\n");
                                }
                              });
                      demoToml.append("\n");
                    });
          });
  
      dumpTo.print(demoToml);
  
      return true;
    }
  }
  