001package com.mrivanplays.annotationconfig.yaml;
002
003import java.util.Collections;
004import java.util.HashMap;
005import java.util.Map;
006import java.util.Objects;
007
008/**
009 * Represents a section list. A YAML example:
010 *
011 * <pre><code>
012 * foo:
013 *   bar:
014 *     baz: aa
015 *     lorem: ipsum
016 *     dolor: sit
017 *     amet: lorem
018 *   ipsum:
019 *     baz: bb
020 *     lorem: dolor
021 *     dolor: lorem
022 *     amet: ipsum
023 * </code></pre>
024 *
025 * <p>How to use: you have to register a {@link SectionObjectListSerializer} with the help of a
026 * {@link com.mrivanplays.annotationconfig.core.utils.TypeToken} in order for this list to properly
027 * (de)serialize.
028 *
029 * @author MrIvanPlays
030 * @since v2.1.1
031 */
032public final class SectionObjectList<T> {
033
034  /**
035   * Creates a new {@link SectionObjectListBuilder} with pre-defined {@link Class} type.
036   *
037   * @param type type
038   * @param <T> object type
039   * @return new builder
040   */
041  public static <T> SectionObjectListBuilder<T> newBuilderForType(Class<? extends T> type) {
042    return new SectionObjectListBuilder<>(type);
043  }
044
045  private final Map<String, T> values;
046  private final Class<? extends T> clazz;
047
048  SectionObjectList(Class<? extends T> clazz, Map<String, T> values) {
049    this.clazz = clazz;
050    this.values = values;
051  }
052
053  /**
054   * Returns the {@link Class} type of the value objects held in this section object list.
055   *
056   * @return objects type
057   */
058  public Class<? extends T> getObjectsType() {
059    return clazz;
060  }
061
062  /**
063   * Returns an unmodifiable representation of this {@code SectionObjectList} as a {@link Map}
064   *
065   * @return as map
066   */
067  public Map<String, T> getAsMap() {
068    return Collections.unmodifiableMap(values);
069  }
070
071  /**
072   * Represents a builder of {@link SectionObjectList}
073   *
074   * @param <T> object type
075   * @author MrIvanPlays
076   * @since v2.1.1
077   */
078  public static final class SectionObjectListBuilder<T> {
079
080    private final Map<String, T> values = new HashMap<>();
081    private final Class<? extends T> type;
082
083    private SectionObjectListBuilder(Class<? extends T> type) {
084      this.type = Objects.requireNonNull(type, "type");
085      if (SectionObjectList.class.isAssignableFrom(type)) {
086        throw new IllegalArgumentException("SectionObjectList<SectionObjectList>");
087      }
088      if (SectionObjectListBuilder.class.isAssignableFrom(type)) {
089        throw new IllegalArgumentException("SectionObjectList<SectionObjectListBuilder>");
090      }
091    }
092
093    /**
094     * Specify a default value held by the created {@link SectionObjectList}
095     *
096     * @param key default value key
097     * @param value default value value
098     * @return this instance for chaining
099     */
100    public SectionObjectListBuilder<T> defaultValue(String key, T value) {
101      this.values.put(key, value);
102      return this;
103    }
104
105    /**
106     * Builds a new {@link SectionObjectList} from the given parameters.
107     *
108     * @return new section object list
109     */
110    public SectionObjectList<T> build() {
111      if (values.isEmpty()) {
112        throw new IllegalStateException(
113            "No defaults for SectionObjectList<" + type.getSimpleName() + ">");
114      }
115      return new SectionObjectList<>(type, values);
116    }
117  }
118}