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; 010import java.util.Collection; 011import java.util.HashMap; 012import java.util.Map; 013import java.util.stream.Stream; 014 015import dev.metaschema.core.model.IModule; 016import dev.metaschema.databind.codegen.config.IBindingConfiguration; 017import dev.metaschema.databind.codegen.typeinfo.IMetaschemaClassFactory; 018import dev.metaschema.databind.codegen.typeinfo.ITypeResolver; 019import edu.umd.cs.findbugs.annotations.NonNull; 020import edu.umd.cs.findbugs.annotations.Nullable; 021 022/** 023 * Information about Java classes generated for a collection of Module modules. 024 */ 025public interface IProduction { 026 027 /** 028 * Get information about the Java classes generated for each Module module in 029 * the collection. 030 * 031 * @return the Java class information for each module 032 */ 033 @NonNull 034 Collection<IGeneratedModuleClass> getModuleProductions(); 035 036 /** 037 * Get information about the Java classes generated for the provided Module 038 * {@code module}. 039 * 040 * @param module 041 * the Module module to get information for 042 * @return the Java class information for the module or {@code null} if this 043 * production did not involve generating classes for the provided module 044 */ 045 @Nullable 046 IGeneratedModuleClass getModuleProduction(@NonNull IModule module); 047 048 /** 049 * Get a stream of all definition Java classes generated as part of this 050 * production. 051 * <p> 052 * This will include each unique class generated for all Module modules 053 * associated with this production. 054 * 055 * @return the stream of generated Java classes 056 */ 057 @NonNull 058 Collection<IGeneratedDefinitionClass> getGlobalDefinitionClasses(); 059 060 /** 061 * Get a stream of all Java classes generated as part of this production, 062 * including module, definition, and package-info classes. 063 * 064 * @return the stream of generated Java classes 065 */ 066 @NonNull 067 Stream<? extends IGeneratedClass> getGeneratedClasses(); 068 069 /** 070 * Create a new production for the provided set of Module {@code modules}. 071 * 072 * @param modules 073 * the Module modules to generate and compile classes for 074 * @param bindingConfiguration 075 * binding customizations that can be used to set namespaces, class 076 * names, and other aspects of generated classes 077 * @param classDir 078 * the directory to generate and compile classes in 079 * @return the production information 080 * @throws IOException 081 * if an error occurred while generating or compiling the classes 082 */ 083 @NonNull 084 static IProduction of( 085 @NonNull Collection<? extends IModule> modules, 086 @NonNull IBindingConfiguration bindingConfiguration, 087 @NonNull Path classDir) throws IOException { 088 089 ITypeResolver typeResolver = ITypeResolver.newTypeResolver(bindingConfiguration); 090 091 IMetaschemaClassFactory classFactory = IMetaschemaClassFactory.newInstance(typeResolver); 092 093 ProductionImpl retval = new ProductionImpl(); 094 for (IModule module : modules) { 095 assert module != null; 096 retval.addModule(module, classFactory, classDir); 097 } 098 099 Map<String, PackageMetadata> packageNameToPackageMetadataMap = new HashMap<>(); 100 for (IGeneratedModuleClass moduleProduction : retval.getModuleProductions()) { 101 String packageName = moduleProduction.getPackageName(); 102 103 PackageMetadata metadata = packageNameToPackageMetadataMap.get(packageName); 104 if (metadata == null) { 105 metadata = new PackageMetadata(moduleProduction); 106 packageNameToPackageMetadataMap.put(metadata.getPackageName(), metadata); 107 } else { 108 metadata.addModule(moduleProduction); 109 } 110 } 111 112 for (PackageMetadata metadata : packageNameToPackageMetadataMap.values()) { 113 assert metadata != null; 114 retval.addPackage( 115 metadata, 116 classFactory, 117 classDir); 118 } 119 return retval; 120 } 121}