/** Generates parameter classes. */
  public void generate() throws IOException {
    // Check that the version of generateDS.py is correct:
    String version = runCommand("generateDS.py", "--version");
    if (!version.equals("generateDS.py version " + GENERATE_DS_VERSION)) {
      throw new IOException(
          "The version of generateDS.py isn't correct, it should be " + GENERATE_DS_VERSION + ".");
    }

    // Get the location of the XML schemma file:
    File xsdFile = XsdData.getInstance().getFile();

    // Run the generateDS.py program to generate the params.py file:
    runCommand("generateDS.py", "-f", "-o", XSD_PARAMS_FILE, xsdFile.getAbsolutePath());

    // Load all the lines of the params.py file in memory so that we can modify them easily:
    try (BufferedReader in = new BufferedReader(new FileReader(XSD_PARAMS_FILE))) {
      String line;
      while ((line = in.readLine()) != null) {
        source.add(line);
      }
    }

    // Modify the code:
    addImports();
    removeExternalEncoding();
    addBasestringHack();
    addSuperAttributes();
    renameExportMethod();
    useBytesIO();

    // Generate the class map:
    source.add("");
    source.add(BEGIN_NOT_GENERATED);
    source.add("");
    generateClassMap();
    source.add("");
    source.add("");
    generateTagsMap();
    source.add("");
    source.add("");
    appendFunctions();
    source.add("");
    source.add(END_NOT_GENERATED);

    // Write the modified params.py file:
    try (PrintWriter out = new PrintWriter(XSD_PARAMS_FILE)) {
      for (String line : source) {
        out.println(line);
      }
    }
  }
  private void generateTagsMap() throws IOException {
    // Sort the type names:
    Map<String, String> map = XsdData.getInstance().getTagsByType();
    List<String> types = new ArrayList<>(map.keySet());
    Collections.sort(types);

    // Generate a list of pairs, each containing the type and the corresponding XML tag:
    addLines(source.size(), 0, "_tag_for_type = {");
    for (String type : types) {
      String tag = map.get(type);
      String line = String.format("%s: \"%s\",", type, tag);
      addLines(source.size(), 4, line);
    }
    addLines(source.size(), 0, "}");
  }
  private void generateClassMap() throws IOException {
    // Sort the names of the elements:
    Map<String, String> map = XsdData.getInstance().getTypesByTag();
    List<String> names = new ArrayList<>(map.keySet());
    Collections.sort(names);

    // Generate the map:
    addLines(source.size(), 0, "_rootClassMap = {");
    for (String name : names) {
      String type = map.get(name);
      String line = String.format("\"%-31s: %s,", name + "\"", type);
      addLines(source.size(), 20, line);
    }
    addLines(source.size(), 16, "}");
  }