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.Map;
010
011import dev.metaschema.core.model.impl.DefaultContainerModelChoiceGroupSupport;
012import dev.metaschema.core.util.CollectionUtil;
013import edu.umd.cs.findbugs.annotations.NonNull;
014
015/**
016 * A choice group model builder.
017 * <p>
018 * Is extended to support other model builders (i.e. choice and assembly model
019 * builders).
020 *
021 * @param <NMI>
022 *          the named model instance Java type
023 * @param <FI>
024 *          the field instance Java type
025 * @param <AI>
026 *          the assembly instance Java type
027 * @see DefaultChoiceModelBuilder for a choice model builder
028 * @see DefaultAssemblyModelBuilder for an assembly model builder
029 */
030@SuppressWarnings("PMD.UseConcurrentHashMap")
031public class DefaultChoiceGroupModelBuilder<
032    NMI extends INamedModelInstance,
033    FI extends IFieldInstance,
034    AI extends IAssemblyInstance> {
035
036  // collections to store model instances
037  @NonNull
038  private final Map<Integer, NMI> namedModelInstances = new LinkedHashMap<>();
039  @NonNull
040  private final Map<Integer, FI> fieldInstances = new LinkedHashMap<>();
041  @NonNull
042  private final Map<Integer, AI> assemblyInstances = new LinkedHashMap<>();
043
044  /**
045   * Append the instance.
046   *
047   * @param instance
048   *          the instance to append
049   */
050  @SuppressWarnings("unchecked")
051  public void append(@NonNull FI instance) {
052    Integer key = instance.getQName().getIndexPosition();
053    namedModelInstances.put(key, (NMI) instance);
054    fieldInstances.put(key, instance);
055  }
056
057  /**
058   * Append the instance.
059   *
060   * @param instance
061   *          the instance to append
062   */
063  @SuppressWarnings("unchecked")
064  public void append(@NonNull AI instance) {
065    Integer key = instance.getQName().getIndexPosition();
066    namedModelInstances.put(key, (NMI) instance);
067    assemblyInstances.put(key, instance);
068  }
069
070  /**
071   * Get the appended named model instances.
072   *
073   * @return the instances or an empty map if no instances were appended
074   */
075  @NonNull
076  protected Map<Integer, NMI> getNamedModelInstances() {
077    return namedModelInstances;
078  }
079
080  /**
081   * Get the appended field instances.
082   *
083   * @return the instances or an empty map if no instances were appended
084   */
085  @NonNull
086  protected Map<Integer, FI> getFieldInstances() {
087    return fieldInstances;
088  }
089
090  /**
091   * Get the appended assembly instances.
092   *
093   * @return the instances or an empty map if no instances were appended
094   */
095  @NonNull
096  protected Map<Integer, AI> getAssemblyInstances() {
097    return assemblyInstances;
098  }
099
100  /**
101   * Build an immutable choice group model container based on the appended
102   * instances.
103   *
104   * @return the container
105   */
106  @NonNull
107  public IContainerModelSupport<NMI, NMI, FI, AI> buildChoiceGroup() {
108    return getNamedModelInstances().isEmpty()
109        ? IContainerModelSupport.empty()
110        : new DefaultContainerModelChoiceGroupSupport<>(
111            CollectionUtil.unmodifiableMap(getNamedModelInstances()),
112            CollectionUtil.unmodifiableMap(getFieldInstances()),
113            CollectionUtil.unmodifiableMap(getAssemblyInstances()));
114  }
115}