1
2
3
4
5
6 package gov.nist.secauto.metaschema.core.metapath.function;
7
8 import gov.nist.secauto.metaschema.core.metapath.ISequence;
9 import gov.nist.secauto.metaschema.core.metapath.InvalidTypeMetapathException;
10 import gov.nist.secauto.metaschema.core.metapath.item.IItem;
11
12 import java.util.Objects;
13
14 import edu.umd.cs.findbugs.annotations.NonNull;
15
16
17
18
19
20 public enum Occurrence {
21
22
23
24 ZERO("", true, Occurrence::handleZero),
25
26
27
28 ZERO_OR_ONE("?", true, Occurrence::handleZeroOrOne),
29
30
31
32 ONE("", false, Occurrence::handleOne),
33
34
35
36 ZERO_OR_MORE("*", true, Occurrence::handleZeroOrMore),
37
38
39
40 ONE_OR_MORE("+", false, Occurrence::handleOneOrMore);
41
42 @NonNull
43 private final String indicator;
44 private final boolean optional;
45 @NonNull
46 private final ISequenceHandler sequenceHandler;
47
48 Occurrence(@NonNull String indicator, boolean optional, @NonNull ISequenceHandler sequenceHandler) {
49 Objects.requireNonNull(indicator, "indicator");
50 this.indicator = indicator;
51 this.optional = optional;
52 this.sequenceHandler = sequenceHandler;
53 }
54
55
56
57
58
59
60 @NonNull
61 public String getIndicator() {
62 return indicator;
63 }
64
65
66
67
68
69
70
71 public boolean isOptional() {
72 return optional;
73 }
74
75
76
77
78
79
80
81 @NonNull
82 public ISequenceHandler getSequenceHandler() {
83 return sequenceHandler;
84 }
85
86 @NonNull
87 private static <T extends IItem> ISequence<T> handleZero(@NonNull ISequence<T> sequence) {
88 int size = sequence.size();
89 if (size != 0) {
90 throw new InvalidTypeMetapathException(
91 null,
92 String.format("an empty sequence expected, but size is '%d'", size));
93 }
94 return ISequence.empty();
95 }
96
97 @NonNull
98 private static <T extends IItem> ISequence<T> handleOne(@NonNull ISequence<T> sequence) {
99 int size = sequence.size();
100 if (size != 1) {
101 throw new InvalidTypeMetapathException(
102 null,
103 String.format("a sequence of one expected, but size is '%d'", size));
104 }
105
106 T item = sequence.getFirstItem(true);
107 return item == null ? ISequence.empty() : ISequence.of(item);
108 }
109
110 @NonNull
111 private static <T extends IItem> ISequence<T> handleZeroOrOne(@NonNull ISequence<T> sequence) {
112 int size = sequence.size();
113 if (size > 1) {
114 throw new InvalidTypeMetapathException(
115 null,
116 String.format("a sequence of zero or one expected, but size is '%d'", size));
117 }
118
119 T item = sequence.getFirstItem(false);
120 return item == null ? ISequence.empty() : ISequence.of(item);
121 }
122
123 @NonNull
124 private static <T extends IItem> ISequence<T> handleZeroOrMore(@NonNull ISequence<T> sequence) {
125 return sequence;
126 }
127
128 @NonNull
129 private static <T extends IItem> ISequence<T> handleOneOrMore(@NonNull ISequence<T> sequence) {
130 int size = sequence.size();
131 if (size < 1) {
132 throw new InvalidTypeMetapathException(
133 null,
134 String.format("a sequence of one or more expected, but size is '%d'", size));
135 }
136 return sequence;
137 }
138
139 @FunctionalInterface
140 public interface ISequenceHandler {
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155 @NonNull
156 <T extends IItem> ISequence<T> handle(@NonNull ISequence<T> sequence);
157 }
158 }