public static @NotNull RawProductModules parseModuleXml(@NotNull InputStream inputStream) throws XMLStreamException {
    XMLStreamReader reader = XMLInputFactory.newDefaultFactory().createXMLStreamReader(inputStream);
    int level = 0;
    ModuleImportance importance = null;
    String moduleName = null;
    List<RawIncludedRuntimeModule> rootMainGroupModules = new ArrayList<>();
    List<RuntimeModuleId> bundledPluginMainModules = new ArrayList<>();
    List<RawIncludedFromData> includedFrom = new ArrayList<>();
    RuntimeModuleId includedFromModule = null;
    Set<RuntimeModuleId> withoutModules = new LinkedHashSet<>();
    String secondLevelTag = null;
    String thirdLevelTag = null;
    while (reader.hasNext()) {
      int event = reader.next();
      if (event == XMLStreamConstants.START_ELEMENT) {
        level++;
        String tagName = reader.getLocalName();
        if (level == 2) {
          secondLevelTag = tagName;
        }
        else if (level == 3) {
          thirdLevelTag = tagName;
          if (tagName.equals("module")) {
            if (reader.getAttributeCount() > 0) {
              String attributeName = reader.getAttributeLocalName(0);
              if (!"importance".equals(attributeName)) {
                throw new XMLStreamException("Unexpected attribute '" + attributeName + "'");
              }
              importance = ModuleImportance.valueOf(reader.getAttributeValue(0).toUpperCase(Locale.US));
            }
            else {
              importance = ModuleImportance.FUNCTIONAL;
            }
          }
        }
      }
      else if (event == XMLStreamConstants.CHARACTERS) {
        if (level == 3) {
          moduleName = reader.getText().trim();
        }
      }
      else if (event == XMLStreamConstants.END_ELEMENT) {
        level--;
        if (level == 2) {
          if (moduleName == null || moduleName.isEmpty()) {
            throw new XMLStreamException("Module name is not specified");
          }
          RuntimeModuleId moduleId = RuntimeModuleId.raw(moduleName);
          if ("main-root-modules".equals(secondLevelTag)) {
            assert importance != null;
            rootMainGroupModules.add(new RawIncludedRuntimeModule(moduleId, importance));
          }
          else if ("bundled-plugins".equals(secondLevelTag)) {
            bundledPluginMainModules.add(moduleId);
          }
          else if ("include".equals(secondLevelTag)) {
            if ("from-module".equals(thirdLevelTag)) {
              includedFromModule = moduleId;
            }
            else if ("without-module".equals(thirdLevelTag)) {
              withoutModules.add(moduleId);
            }
            else {
              throw new XMLStreamException("Unexpected sub tag in 'include': " + secondLevelTag);
            }
          }
          else {
            throw new XMLStreamException("Unexpected second-level tag " + secondLevelTag);
          }
          moduleName = null;
          importance = null;
        }
        else if (level == 1 && "include".equals(secondLevelTag)) {
          if (includedFromModule == null) {
            throw new XMLStreamException("'from-module' tag for 'include' is not specified");
          }
          includedFrom.add(new RawIncludedFromData(includedFromModule, withoutModules));
          includedFromModule = null;
          withoutModules = new LinkedHashSet<>();
        }
        if (level == 0) {
          break;
        }
      }
    }
    reader.close();
    return new RawProductModules(rootMainGroupModules, bundledPluginMainModules, includedFrom);
  }
public static @NotNull RawProductModules parseModuleXml(@NotNull InputStream inputStream)