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