1   /*
2    * SPDX-FileCopyrightText: none
3    * SPDX-License-Identifier: CC0-1.0
4    */
5   
6   package dev.metaschema.core.metapath.impl;
7   
8   import java.util.ArrayList;
9   import java.util.Collection;
10  import java.util.List;
11  
12  import dev.metaschema.core.metapath.item.IItem;
13  import dev.metaschema.core.metapath.item.ISequence;
14  import dev.metaschema.core.util.CollectionUtil;
15  import dev.metaschema.core.util.ObjectUtils;
16  import edu.umd.cs.findbugs.annotations.NonNull;
17  
18  /**
19   * A Metapath sequence supporting an unbounded number of items.
20   *
21   * @param <ITEM>
22   *          the Java type of the items
23   */
24  public class SequenceN<ITEM extends IItem>
25      extends AbstractSequence<ITEM> {
26    /**
27     * The singleton empty sequence instance.
28     * <p>
29     * This field is located in SequenceN rather than AbstractSequence to prevent
30     * class initialization deadlock. Since SequenceN extends AbstractSequence,
31     * AbstractSequence is always initialized first, ensuring no circular dependency
32     * when multiple threads initialize these classes concurrently.
33     */
34    @NonNull
35    private static final ISequence<?> EMPTY = new SequenceN<>();
36  
37    /**
38     * Get an immutable sequence that is empty.
39     *
40     * @param <T>
41     *          the item Java type
42     * @return the empty sequence
43     */
44    @SuppressWarnings("unchecked")
45    public static <T extends IItem> ISequence<T> empty() {
46      return (ISequence<T>) EMPTY;
47    }
48  
49    @NonNull
50    private final List<ITEM> items;
51  
52    /**
53     * Construct a new sequence with the provided items.
54     *
55     * @param items
56     *          a collection containing the items to add to the sequence
57     * @param copy
58     *          if {@code true} make a defensive copy of the list or {@code false}
59     *          otherwise
60     */
61    public SequenceN(@NonNull List<ITEM> items, boolean copy) {
62      this.items = CollectionUtil.unmodifiableList(copy ? new ArrayList<>(items) : items);
63    }
64  
65    /**
66     * Construct a new sequence with the provided items.
67     *
68     * @param items
69     *          the items to add to the sequence
70     */
71    @SafeVarargs
72    public SequenceN(@NonNull ITEM... items) {
73      this(ObjectUtils.notNull(List.of(items)), false);
74    }
75  
76    /**
77     * Construct a new sequence with the provided items.
78     *
79     * @param items
80     *          a collection containing the items to add to the sequence
81     */
82    public SequenceN(@NonNull Collection<ITEM> items) {
83      this(new ArrayList<>(items), false);
84    }
85  
86    /**
87     * Construct a new sequence with the provided items.
88     *
89     * @param items
90     *          a list containing the items to add to the sequence
91     */
92    public SequenceN(@NonNull List<ITEM> items) {
93      this(items, false);
94    }
95  
96    @Override
97    public List<ITEM> asList() {
98      return items;
99    }
100 }