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}