001/*
002 * SPDX-FileCopyrightText: none
003 * SPDX-License-Identifier: CC0-1.0
004 */
005
006package dev.metaschema.databind.codegen;
007
008import java.io.IOException;
009import java.nio.file.Path;
010
011import dev.metaschema.core.model.IModule;
012import dev.metaschema.core.model.MetaschemaException;
013import dev.metaschema.core.util.ObjectUtils;
014import dev.metaschema.databind.model.IBoundModule;
015import edu.umd.cs.findbugs.annotations.NonNull;
016
017/**
018 * Default implementation of {@link IModuleBindingGenerator} that generates and
019 * compiles Java classes for a Metaschema module.
020 * <p>
021 * This generator creates Java source files representing the module and its
022 * definitions, compiles them, and loads the resulting classes using a custom
023 * class loader.
024 */
025public class DefaultModuleBindingGenerator implements IModuleBindingGenerator {
026  @NonNull
027  private final Path compilePath;
028
029  /**
030   * Construct a new binding generator that generates classes in the specified
031   * directory.
032   *
033   * @param compilePath
034   *          the directory where generated Java classes will be created and
035   *          compiled
036   */
037  public DefaultModuleBindingGenerator(@NonNull Path compilePath) {
038    this.compilePath = compilePath;
039  }
040
041  @Override
042  public Class<? extends IBoundModule> generate(IModule module) throws MetaschemaException {
043    ClassLoader classLoader = ModuleCompilerHelper.newClassLoader(
044        compilePath,
045        ObjectUtils.notNull(Thread.currentThread().getContextClassLoader()));
046
047    IProduction production;
048    try {
049      production = ModuleCompilerHelper.compileMetaschema(module, compilePath);
050    } catch (IOException ex) {
051      throw new MetaschemaException(
052          String.format("Unable to generate and compile classes for module '%s'.", module.getLocation()),
053          ex);
054    }
055
056    try {
057      return ObjectUtils.notNull(production.getModuleProduction(module)).load(classLoader);
058    } catch (ClassNotFoundException ex) {
059      throw new IllegalStateException(ex);
060    }
061  }
062
063}