001/*
002 * SPDX-FileCopyrightText: none
003 * SPDX-License-Identifier: CC0-1.0
004 */
005
006package dev.metaschema.core.model;
007
008import java.util.LinkedHashMap;
009import java.util.LinkedList;
010import java.util.List;
011import java.util.Map;
012
013import dev.metaschema.core.model.impl.DefaultContainerModelAssemblySupport;
014import dev.metaschema.core.util.CollectionUtil;
015import edu.umd.cs.findbugs.annotations.NonNull;
016import edu.umd.cs.findbugs.annotations.Nullable;
017
018/**
019 * An assembly model builder.
020 *
021 * @param <MI>
022 *          the model instance Java type
023 * @param <NMI>
024 *          the named model instance Java type
025 * @param <FI>
026 *          the field instance Java type
027 * @param <AI>
028 *          the assembly instance Java type
029 * @param <CI>
030 *          the choice instance Java type
031 * @param <CGI>
032 *          the choice group instance Java type
033 * @see DefaultChoiceGroupModelBuilder for a choice group model builder
034 * @see DefaultChoiceModelBuilder for a choice model builder
035 */
036@SuppressWarnings("PMD.UseConcurrentHashMap")
037public class DefaultAssemblyModelBuilder<
038    MI extends IModelInstance,
039    NMI extends INamedModelInstance,
040    FI extends IFieldInstance,
041    AI extends IAssemblyInstance,
042    CI extends IChoiceInstance,
043    CGI extends IChoiceGroupInstance>
044    extends DefaultChoiceModelBuilder<MI, NMI, FI, AI> {
045  // collections to store model instances
046  @NonNull
047  private final List<CI> choiceInstances = new LinkedList<>();
048  @NonNull
049  private final Map<String, CGI> choiceGroupInstances = new LinkedHashMap<>();
050  @Nullable
051  private IAnyInstance anyInstance;
052
053  /**
054   * Append the instance.
055   *
056   * @param instance
057   *          the instance to append
058   */
059  @SuppressWarnings("unchecked")
060  public void append(@NonNull CI instance) {
061    getModelInstances().add((MI) instance);
062    choiceInstances.add(instance);
063  }
064
065  /**
066   * Append the instance.
067   *
068   * @param instance
069   *          the instance to append
070   */
071  @SuppressWarnings("unchecked")
072  public void append(@NonNull CGI instance) {
073    getModelInstances().add((MI) instance);
074    choiceGroupInstances.put(instance.getGroupAsName(), instance);
075  }
076
077  /**
078   * Get the appended choice instances.
079   *
080   * @return the instances or an empty list if no instances were appended
081   */
082  @NonNull
083  protected List<CI> getChoiceInstances() {
084    return choiceInstances;
085  }
086
087  /**
088   * Get the appended choice group instances.
089   *
090   * @return the instances or an empty map if no instances were appended
091   */
092  @NonNull
093  protected Map<String, CGI> getChoiceGroupInstances() {
094    return choiceGroupInstances;
095  }
096
097  /**
098   * Get the {@code any} instance.
099   *
100   * @return the {@code any} instance, or {@code null} if none has been set
101   */
102  @Nullable
103  public IAnyInstance getAnyInstance() {
104    return anyInstance;
105  }
106
107  /**
108   * Set the {@code any} instance for this model.
109   *
110   * @param anyInstance
111   *          the {@code any} instance, or {@code null} to clear it
112   */
113  public void setAnyInstance(@Nullable IAnyInstance anyInstance) {
114    this.anyInstance = anyInstance;
115  }
116
117  /**
118   * Build an immutable assembly model container based on the appended instances.
119   *
120   * @return the container
121   */
122  @NonNull
123  public IContainerModelAssemblySupport<MI, NMI, FI, AI, CI, CGI> buildAssembly() {
124    return getModelInstances().isEmpty() && anyInstance == null
125        ? IContainerModelAssemblySupport.empty()
126        : new DefaultContainerModelAssemblySupport<>(
127            CollectionUtil.unmodifiableList(getModelInstances()),
128            CollectionUtil.unmodifiableMap(getNamedModelInstances()),
129            CollectionUtil.unmodifiableMap(getFieldInstances()),
130            CollectionUtil.unmodifiableMap(getAssemblyInstances()),
131            CollectionUtil.unmodifiableList(getChoiceInstances()),
132            CollectionUtil.unmodifiableMap(getChoiceGroupInstances()),
133            anyInstance);
134  }
135}