001/* 002 * SPDX-FileCopyrightText: none 003 * SPDX-License-Identifier: CC0-1.0 004 */ 005 006package dev.metaschema.schemagen; 007 008import java.io.IOException; 009import java.util.Collection; 010import java.util.Locale; 011 012import dev.metaschema.core.model.IAssemblyDefinition; 013import dev.metaschema.core.model.IDefinition; 014import dev.metaschema.core.model.IModule; 015import edu.umd.cs.findbugs.annotations.NonNull; 016import edu.umd.cs.findbugs.annotations.Nullable; 017 018/** 019 * Represents the state information used during schema generation. 020 * 021 * @param <WRITER> 022 * the type of writer used for schema output 023 */ 024public interface IGenerationState<WRITER> { 025 /** 026 * Get the Metaschema module being processed for schema generation. 027 * 028 * @return the module 029 */ 030 @NonNull 031 IModule getModule(); 032 033 /** 034 * Get the writer used for schema output. 035 * <p> 036 * The caller does not own this writer and must not close it. 037 * 038 * @return the writer instance 039 */ 040 @NonNull 041 WRITER getWriter(); 042 043 /** 044 * Get the collection of root assembly definitions exported by the module. 045 * 046 * @return the root assembly definitions 047 */ 048 @NonNull 049 default Collection<? extends IAssemblyDefinition> getRootDefinitions() { 050 return getModule().getExportedRootAssemblyDefinitions(); 051 } 052 053 /** 054 * Determine if the provided definition should be inlined in the generated 055 * schema. 056 * 057 * @param definition 058 * the definition to check 059 * @return {@code true} if the definition should be inlined, {@code false} 060 * otherwise 061 */ 062 boolean isInline(@NonNull IDefinition definition); 063 064 /** 065 * Flush any buffered content to the underlying writer. 066 * 067 * @throws IOException 068 * if an I/O error occurs while flushing 069 */ 070 void flushWriter() throws IOException; 071 072 /** 073 * Generate a type name for the provided definition with an optional suffix. 074 * 075 * @param definition 076 * the definition to generate a type name for 077 * @param suffix 078 * an optional suffix to append to the type name, or {@code null} if no 079 * suffix is needed 080 * @return the generated type name 081 */ 082 @NonNull 083 String getTypeNameForDefinition(@NonNull IDefinition definition, @Nullable String suffix); 084 085 /** 086 * Convert a text string to camel case by splitting on punctuation and 087 * capitalizing each segment. 088 * 089 * @param text 090 * the text to convert 091 * @return the camel case representation of the text 092 */ 093 @NonNull 094 static CharSequence toCamelCase(String text) { 095 StringBuilder builder = new StringBuilder(); 096 for (String segment : text.split("\\p{Punct}")) { 097 if (segment.length() > 0) { 098 builder.append(segment.substring(0, 1).toUpperCase(Locale.ROOT)); 099 } 100 if (segment.length() > 1) { 101 builder.append(segment.substring(1).toLowerCase(Locale.ROOT)); 102 } 103 } 104 return builder; 105 } 106}