1   /*
2    * SPDX-FileCopyrightText: none
3    * SPDX-License-Identifier: CC0-1.0
4    */
5   
6   package dev.metaschema.databind.codegen;
7   
8   import java.io.IOException;
9   import java.nio.file.Path;
10  
11  import dev.metaschema.core.model.IModule;
12  import dev.metaschema.core.model.MetaschemaException;
13  import dev.metaschema.core.util.ObjectUtils;
14  import dev.metaschema.databind.model.IBoundModule;
15  import edu.umd.cs.findbugs.annotations.NonNull;
16  
17  /**
18   * Default implementation of {@link IModuleBindingGenerator} that generates and
19   * compiles Java classes for a Metaschema module.
20   * <p>
21   * This generator creates Java source files representing the module and its
22   * definitions, compiles them, and loads the resulting classes using a custom
23   * class loader.
24   */
25  public class DefaultModuleBindingGenerator implements IModuleBindingGenerator {
26    @NonNull
27    private final Path compilePath;
28  
29    /**
30     * Construct a new binding generator that generates classes in the specified
31     * directory.
32     *
33     * @param compilePath
34     *          the directory where generated Java classes will be created and
35     *          compiled
36     */
37    public DefaultModuleBindingGenerator(@NonNull Path compilePath) {
38      this.compilePath = compilePath;
39    }
40  
41    @Override
42    public Class<? extends IBoundModule> generate(IModule module) throws MetaschemaException {
43      ClassLoader classLoader = ModuleCompilerHelper.newClassLoader(
44          compilePath,
45          ObjectUtils.notNull(Thread.currentThread().getContextClassLoader()));
46  
47      IProduction production;
48      try {
49        production = ModuleCompilerHelper.compileMetaschema(module, compilePath);
50      } catch (IOException ex) {
51        throw new MetaschemaException(
52            String.format("Unable to generate and compile classes for module '%s'.", module.getLocation()),
53            ex);
54      }
55  
56      try {
57        return ObjectUtils.notNull(production.getModuleProduction(module)).load(classLoader);
58      } catch (ClassNotFoundException ex) {
59        throw new IllegalStateException(ex);
60      }
61    }
62  
63  }