001/*
002 * SPDX-FileCopyrightText: none
003 * SPDX-License-Identifier: CC0-1.0
004 */
005
006package dev.metaschema.core.model;
007
008import dev.metaschema.core.MetaschemaConstants;
009import dev.metaschema.core.model.constraint.IFeatureModelConstrained;
010import dev.metaschema.core.model.util.ModuleUtils;
011import dev.metaschema.core.qname.IEnhancedQName;
012import edu.umd.cs.findbugs.annotations.NonNull;
013import edu.umd.cs.findbugs.annotations.Nullable;
014
015/**
016 * Represents an assembly definition in a Metaschema module.
017 * <p>
018 * An assembly is a complex structured data object that may contain flags,
019 * fields, and other nested assemblies. Assembly definitions may be designated
020 * as root elements for documents.
021 */
022public interface IAssemblyDefinition
023    extends IModelDefinition, IContainerModelAssembly, IAssembly, IFeatureModelConstrained {
024  /**
025   * The qualified name for the model property in Metaschema.
026   */
027  IEnhancedQName MODEL_QNAME = IEnhancedQName.of(MetaschemaConstants.METASCHEMA_NAMESPACE, "model");
028
029  /**
030   * Check if the assembly is a top-level root assembly.
031   *
032   * @return {@code true} if the assembly is a top-level root, or {@code false}
033   *         otherwise
034   */
035  default boolean isRoot() {
036    // not a root by default
037    return false;
038  }
039
040  /**
041   * Get the root name if this assembly is a top-level root.
042   *
043   * @return the root name if this assembly is a top-level root, or {@code null}
044   *         otherwise
045   */
046  @Nullable
047  default String getRootName() {
048    // not a root by default
049    return null;
050  }
051
052  /**
053   * Get the root index to use for binary data, if this assembly is a top-level
054   * root.
055   *
056   * @return the root index if provided and this assembly is a top-level root, or
057   *         {@code null} otherwise
058   */
059  @Nullable
060  default Integer getRootIndex() {
061    // not a root by default
062    return null;
063  }
064
065  /**
066   * Get the XML qualified name to use in XML as the root element.
067   *
068   * @return the root XML qualified name if this assembly is a top-level root, or
069   *         {@code null} otherwise
070   */
071  default IEnhancedQName getRootQName() {
072    IEnhancedQName retval = null;
073    String rootName = getRootName();
074    if (rootName != null) {
075      retval = ModuleUtils.parseModelName(getContainingModule(), rootName);
076    }
077    return retval;
078  }
079
080  /**
081   * Get the name used for the associated property in JSON/YAML.
082   *
083   * @return the root JSON property name if this assembly is a top-level root, or
084   *         {@code null} otherwise
085   */
086  default String getRootJsonName() {
087    return getRootName();
088  }
089
090  @Override
091  default boolean isInline() {
092    // not inline by default
093    return false;
094  }
095
096  @Override
097  default IAssemblyInstance getInlineInstance() {
098    // not inline by default
099    return null;
100  }
101
102  @Override
103  default IAssemblyDefinition getOwningDefinition() {
104    return this;
105  }
106  //
107  // @Override
108  // default IAssemblyNodeItem getNodeItem() {
109  // return null;
110  // }
111
112  @Override
113  default boolean hasChildren() {
114    return IModelDefinition.super.hasChildren() || IContainerModelAssembly.super.hasChildren();
115  }
116
117  /**
118   * A visitor callback.
119   *
120   * @param <CONTEXT>
121   *          the type of the context parameter
122   * @param <RESULT>
123   *          the type of the visitor result
124   * @param visitor
125   *          the calling visitor
126   * @param context
127   *          a parameter used to pass contextual information between visitors
128   * @return the visitor result
129   */
130  @Override
131  default <CONTEXT, RESULT> RESULT accept(@NonNull IModelElementVisitor<CONTEXT, RESULT> visitor, CONTEXT context) {
132    return visitor.visitAssemblyDefinition(this, context);
133  }
134}