/*
 * Bach - Java Shell Builder
 * Copyright (C) 2020 Christian Stein
 *
 * Licensed 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
 *
 *     https://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 de.sormuras.bach;

import java.lang.module.ModuleDescriptor.Version;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

/**
 * Common conventions.
 *
 * @see <a href="https://github.com/sormuras/bach#common-conventions">Common Conventions</a>
 */
public interface Convention {

  /** Return name of main class of the specified module. */
  static Optional<String> mainClass(Path info, String module) {
    var main = Path.of(module.replace('.', '/'), "Main.java");
    var exists = Files.isRegularFile(info.resolveSibling(main));
    return exists ? Optional.of(module + '.' + "Main") : Optional.empty();
  }

  /** Extend the passed map of modules with missing JUnit test engine implementations. */
  static void amendJUnitTestEngines(Map<String, Version> modules) {
    var names = modules.keySet();
    if (names.contains("org.junit.jupiter") || names.contains("org.junit.jupiter.api"))
      modules.putIfAbsent("org.junit.jupiter.engine", null);
    if (names.contains("junit")) modules.putIfAbsent("org.junit.vintage.engine", null);
  }

  /** Extend the passed map of modules with the JUnit Platform Console module. */
  static void amendJUnitPlatformConsole(Map<String, Version> modules) {
    var names = modules.keySet();
    if (names.contains("org.junit.platform.console")) return;
    var triggers =
        Set.of("org.junit.jupiter.engine", "org.junit.vintage.engine", "org.junit.platform.engine");
    names.stream()
        .filter(triggers::contains)
        .findAny()
        .ifPresent(__ -> modules.put("org.junit.platform.console", null));
  }
}

@@ -654,16 +654,58 @@
 .bach;%0A%0A
+import java.lang.module.ModuleDescriptor;%0A
 import j
@@ -746,16 +746,16 @@
 ersion;%0A
-
 import j
@@ -871,16 +871,84 @@
 til.Set;
+%0Aimport java.util.stream.Collectors;%0Aimport java.util.stream.Stream;
 %0A%0A/**%0A *
@@ -1351,16 +1351,16 @@
 main));%0A
-
     retu
@@ -1423,32 +1423,389 @@
 l.empty();%0A  %7D%0A%0A
+  /** Return name of the main module by finding a single main class containing descriptor. */%0A  static Optional%3CString%3E mainModule(Stream%3CModuleDescriptor%3E descriptors) %7B%0A    var mains = descriptors.filter(d -%3E d.mainClass().isPresent()).collect(Collectors.toList());%0A    return mains.size() == 1 ? Optional.of(mains.get(0).name()) : Optional.empty();%0A  %7D%0A%0A
   /** Extend the

Add main module convention