/*
 * Bach - Java Shell Builder
 * Copyright (C) 2019 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;
import java.lang.module.ModuleDescriptor.Version;
import java.net.URI;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

/*BODY*/
/** Modular project model. */
public /*STATIC*/ class Project {

  /** Base directory. */
  public final Path baseDirectory;
  /** Target directory. */
  public final Path targetDirectory;
  /** Name of the project. */
  public final String name;
  /** Version of the project. */
  public final Version version;
  /** Library. */
  public final Library library;
  /** Realms. */
  public final List<Realm> realms;

  public Project(
      Path baseDirectory,
      Path targetDirectory,
      String name,
      Version version,
      Library library,
      List<Realm> realms) {
    this.baseDirectory = Util.requireNonNull(baseDirectory, "base");
    this.targetDirectory = Util.requireNonNull(targetDirectory, "targetDirectory");
    this.version = Util.requireNonNull(version, "version");
    this.name = Util.requireNonNull(name, "name");
    this.library = Util.requireNonNull(library, "library");
    this.realms = List.copyOf(Util.requireNonEmpty(realms, "realms"));
  }

  /** Manage external 3rd-party modules. */
  public static class Library {
    /** List of library paths to external 3rd-party modules. */
    public final List<Path> modulePaths;
    /** Map external 3rd-party module names to their {@code URI}s. */
    public final Function<String, URI> moduleMapper;

    public Library(List<Path> modulePaths, Function<String, URI> moduleMapper) {
      this.modulePaths = List.copyOf(Util.requireNonEmpty(modulePaths, "modulePaths"));
      this.moduleMapper = moduleMapper;
    }
  }

  /** Java module source unit. */
  public static class ModuleUnit {
    /** Path to the backing {@code module-info.java} file. */
    public final Path info;
    /** Paths to the resources directories. */
    public final List<Path> sources;
    /** Paths to the resources directories. */
    public final List<Path> resources;
    /** Associated module descriptor, normally parsed from module {@link #info} file. */
    public final ModuleDescriptor descriptor;

    public ModuleUnit(
        Path info, List<Path> sources, List<Path> resources, ModuleDescriptor descriptor) {
      this.info = info;
      this.sources = List.copyOf(sources);
      this.resources = List.copyOf(resources);
      this.descriptor = descriptor;
    }
  }

  /** Main- and test realms. */
  public static class Realm {
    /** Name of the realm. */
    public final String name;
    /** Enable preview features. */
    public final boolean preview;
    /** Java feature release target number. */
    public final int release;
    /** Module source path specifies where to find input source files for multiple modules. */
    public final String moduleSourcePath;
    /** Map of declared module source unit. */
    public final Map<String, ModuleUnit> modules;
    /** List of required realms. */
    public final List<Realm> realms;

    public Realm(
        String name,
        boolean preview,
        int release,
        String moduleSourcePath,
        Map<String, ModuleUnit> modules,
        Realm... realms) {
      this.name = name;
      this.preview = preview;
      this.release = release;
      this.moduleSourcePath = moduleSourcePath;
      this.modules = Map.copyOf(modules);
      this.realms = List.of(realms);
    }
  }
}

@@ -2566,33 +2566,30 @@
 aths to the 
-re
 source
-s
  directories
@@ -2659,17 +2659,16 @@
 resource
-s
  directo
@@ -3072,32 +3072,32 @@
 yOf(resources);%0A
-
       this.descr
@@ -3123,24 +3123,732 @@
 %0A    %7D%0A  %7D%0A%0A
+  /** Multi-release module source unit */%0A  public static class MultiReleaseUnit extends ModuleUnit %7B%0A    /** Feature release number to source path map. */%0A    public final Map%3CInteger, Path%3E releases;%0A    /** Copy this module descriptor to the root of the generated modular jar. */%0A    public final int copyModuleDescriptorToRootRelease;%0A%0A    public MultiReleaseUnit(%0A        Path info, int copyModuleDescriptorToRootRelease, Map%3CInteger, Path%3E releases, List%3CPath%3E resources, ModuleDescriptor descriptor) %7B%0A      super(info, List.copyOf(releases.values()), resources, descriptor);%0A      this.copyModuleDescriptorToRootRelease = copyModuleDescriptorToRootRelease;%0A      this.releases = releases;%0A    %7D%0A  %7D%0A%0A
   /** Main- 

Introduce multi-release module unit class