001/*
002 * SPDX-FileCopyrightText: none
003 * SPDX-License-Identifier: CC0-1.0
004 */
005
006package dev.metaschema.schemagen;
007
008import dev.metaschema.core.configuration.IConfiguration;
009import dev.metaschema.core.model.IDefinition;
010import edu.umd.cs.findbugs.annotations.NonNull;
011
012/**
013 * A strategy for determining whether a definition should be inlined in the
014 * generated schema or referenced as a separate type definition.
015 */
016@FunctionalInterface
017public interface IInlineStrategy {
018  /**
019   * A strategy that never inlines any definition.
020   */
021  @NonNull
022  IInlineStrategy NONE_INLINE = new IInlineStrategy() {
023    @Override
024    public boolean isInline(
025        @NonNull IDefinition definition,
026        @NonNull ModuleIndex metaschemaIndex) {
027      return false;
028    }
029  };
030
031  /**
032   * A strategy that inlines definitions based on their
033   * {@link IDefinition#isInline()} property.
034   */
035  @NonNull
036  IInlineStrategy DEFINED_AS_INLINE = new IInlineStrategy() {
037    @Override
038    public boolean isInline(
039        @NonNull IDefinition definition,
040        @NonNull ModuleIndex metaschemaIndex) {
041      return definition.isInline();
042    }
043  };
044
045  /**
046   * A strategy that inlines definitions unless they are used in a choice group.
047   */
048  @NonNull
049  IInlineStrategy CHOICE_NOT_INLINE = new ChoiceNotInlineStrategy();
050
051  /**
052   * Create a new inline strategy based on the provided configuration.
053   *
054   * @param configuration
055   *          the schema generation configuration
056   * @return the appropriate inline strategy based on the configuration settings
057   */
058  @NonNull
059  static IInlineStrategy newInlineStrategy(@NonNull IConfiguration<SchemaGenerationFeature<?>> configuration) {
060    IInlineStrategy retval;
061    if (configuration.isFeatureEnabled(SchemaGenerationFeature.INLINE_DEFINITIONS)) {
062      if (configuration.isFeatureEnabled(SchemaGenerationFeature.INLINE_CHOICE_DEFINITIONS)) {
063        retval = DEFINED_AS_INLINE;
064      } else {
065        retval = CHOICE_NOT_INLINE;
066      }
067    } else {
068      retval = NONE_INLINE;
069    }
070    return retval;
071  }
072
073  /**
074   * Determine if the provided definition should be inlined in the generated
075   * schema.
076   *
077   * @param definition
078   *          the definition to check
079   * @param metaschemaIndex
080   *          the module index containing definition usage information
081   * @return {@code true} if the definition should be inlined, {@code false} if it
082   *         should be referenced as a separate type
083   */
084  boolean isInline(
085      @NonNull IDefinition definition,
086      @NonNull ModuleIndex metaschemaIndex);
087}