5
5
import ch .njol .skript .lang .parser .ParserInstance ;
6
6
import org .jetbrains .annotations .NotNull ;
7
7
import org .jetbrains .annotations .Nullable ;
8
+ import org .jetbrains .annotations .Unmodifiable ;
8
9
9
- import java .util .ArrayList ;
10
- import java .util .List ;
11
- import java .util .Map ;
10
+ import java .util .*;
12
11
13
12
/**
14
13
* An EntryContainer is a data container for obtaining the values of the entries of a {@link SectionNode}.
15
14
*/
16
15
public class EntryContainer {
17
16
18
17
private final SectionNode source ;
19
- @ Nullable
20
- private final EntryValidator entryValidator ;
21
- @ Nullable
22
- private final Map <String , Node > handledNodes ;
18
+ private final @ Nullable EntryValidator entryValidator ;
19
+ private final @ Nullable Map <String , Collection <Node >> handledNodes ;
23
20
private final List <Node > unhandledNodes ;
24
21
25
22
EntryContainer (
26
- SectionNode source , @ Nullable EntryValidator entryValidator , @ Nullable Map <String , Node > handledNodes , List <Node > unhandledNodes
23
+ SectionNode source , @ Nullable EntryValidator entryValidator ,
24
+ @ Nullable Map <String , Collection <Node >> handledNodes , List <Node > unhandledNodes
27
25
) {
28
26
this .source = source ;
29
27
this .entryValidator = entryValidator ;
@@ -60,11 +58,72 @@ public List<Node> getUnhandledNodes() {
60
58
return unhandledNodes ;
61
59
}
62
60
61
+ /**
62
+ * A method for obtaining a typed entry values.
63
+ * @param key The key associated with the entry.
64
+ * @param expectedType The class representing the expected type of the entry's values.
65
+ * @param useDefaultValue Whether the default value should be used if parsing failed.
66
+ * @return The entry's values. May be empty list if the entry is missing or a parsing error occurred.
67
+ * @throws RuntimeException If the entry's value is not of the expected type.
68
+ */
69
+ @ SuppressWarnings ("unchecked" )
70
+ public <E , R extends E > @ Unmodifiable List <R > getAll (String key , Class <E > expectedType , boolean useDefaultValue ) {
71
+ List <?> parsed = getAll (key , useDefaultValue );
72
+ for (Object object : parsed ) {
73
+ if (!expectedType .isInstance (object ))
74
+ throw new RuntimeException ("Expected entry with key '" + key + "' to be '" +
75
+ expectedType + "', but got '" + object .getClass () + "'" );
76
+ }
77
+ return (List <R >) parsed ;
78
+ }
79
+
80
+ /**
81
+ * A method for obtaining an entry values with an unknown type.
82
+ * @param key The key associated with the entry.
83
+ * @param useDefaultValue Whether the default value should be used if parsing failed.
84
+ * @return The entry's values. May be empty list if the entry is missing or a parsing error occurred.
85
+ */
86
+ public @ Unmodifiable List <Object > getAll (String key , boolean useDefaultValue ) {
87
+ if (entryValidator == null || handledNodes == null )
88
+ return Collections .emptyList ();
89
+
90
+ EntryData <?> entryData = entryValidator .getEntryData ().stream ()
91
+ .filter (data -> data .getKey ().equals (key ))
92
+ .findFirst ()
93
+ .orElse (null );
94
+ if (entryData == null )
95
+ return Collections .emptyList ();
96
+
97
+ Collection <Node > nodes = handledNodes .get (key );
98
+ if (nodes == null || nodes .isEmpty ()) {
99
+ Object defaultValue = entryData .getDefaultValue ();
100
+ return defaultValue != null
101
+ ? Collections .singletonList (defaultValue )
102
+ : Collections .emptyList ();
103
+ }
104
+
105
+ List <Object > values = new LinkedList <>();
106
+ ParserInstance parser = ParserInstance .get ();
107
+ Node oldNode = parser .getNode ();
108
+ for (Node node : nodes ) {
109
+ parser .setNode (node );
110
+ Object value = entryData .getValue (node );
111
+ if (value == null && useDefaultValue )
112
+ value = entryData .getDefaultValue ();
113
+ if (value != null )
114
+ values .add (value );
115
+ }
116
+ parser .setNode (oldNode );
117
+
118
+ return Collections .unmodifiableList (values );
119
+ }
120
+
63
121
/**
64
122
* A method for obtaining a non-null, typed entry value.
65
123
* This method should ONLY be called if there is no way the entry could return null.
66
- * In general, this means that the entry has a default value (and 'useDefaultValue' is true). This is because even
67
- * though an entry may be required, parsing errors may occur that mean no value can be returned.
124
+ * In general, this means that the entry has a default value (and 'useDefaultValue' is true).
125
+ * This is because even though an entry may be required, parsing errors may occur that
126
+ * mean no value can be returned.
68
127
* It can also mean that the entry data is simple enough such that it will never return a null value.
69
128
* @param key The key associated with the entry.
70
129
* @param expectedType The class representing the expected type of the entry's value.
@@ -73,28 +132,29 @@ public List<Node> getUnhandledNodes() {
73
132
* @throws RuntimeException If the entry's value is null, or if it is not of the expected type.
74
133
*/
75
134
public <E , R extends E > R get (String key , Class <E > expectedType , boolean useDefaultValue ) {
76
- R value = getOptional (key , expectedType , useDefaultValue );
77
- if (value == null )
135
+ List < R > all = getAll (key , expectedType , useDefaultValue );
136
+ if (all . isEmpty () )
78
137
throw new RuntimeException ("Null value for asserted non-null value" );
79
- return value ;
138
+ return all . get ( 0 ); // always present
80
139
}
81
140
82
141
/**
83
142
* A method for obtaining a non-null entry value with an unknown type.
84
143
* This method should ONLY be called if there is no way the entry could return null.
85
- * In general, this means that the entry has a default value (and 'useDefaultValue' is true). This is because even
86
- * though an entry may be required, parsing errors may occur that mean no value can be returned.
144
+ * In general, this means that the entry has a default value (and 'useDefaultValue' is true).
145
+ * This is because even though an entry may be required, parsing errors may occur that
146
+ * mean no value can be returned.
87
147
* It can also mean that the entry data is simple enough such that it will never return a null value.
88
148
* @param key The key associated with the entry.
89
149
* @param useDefaultValue Whether the default value should be used if parsing failed.
90
150
* @return The entry's value.
91
151
* @throws RuntimeException If the entry's value is null.
92
152
*/
93
153
public Object get (String key , boolean useDefaultValue ) {
94
- Object parsed = getOptional (key , useDefaultValue );
95
- if (parsed == null )
154
+ List < Object > all = getAll (key , useDefaultValue );
155
+ if (all . isEmpty () )
96
156
throw new RuntimeException ("Null value for asserted non-null value" );
97
- return parsed ;
157
+ return all . get ( 0 ); // always present
98
158
}
99
159
100
160
/**
@@ -105,15 +165,9 @@ public Object get(String key, boolean useDefaultValue) {
105
165
* @return The entry's value. May be null if the entry is missing or a parsing error occurred.
106
166
* @throws RuntimeException If the entry's value is not of the expected type.
107
167
*/
108
- @ Nullable
109
- @ SuppressWarnings ("unchecked" )
110
- public <E , R extends E > R getOptional (String key , Class <E > expectedType , boolean useDefaultValue ) {
111
- Object parsed = getOptional (key , useDefaultValue );
112
- if (parsed == null )
113
- return null ;
114
- if (!expectedType .isInstance (parsed ))
115
- throw new RuntimeException ("Expected entry with key '" + key + "' to be '" + expectedType + "', but got '" + parsed .getClass () + "'" );
116
- return (R ) parsed ;
168
+ public <E , R extends E > @ Nullable R getOptional (String key , Class <E > expectedType , boolean useDefaultValue ) {
169
+ List <R > all = getAll (key , expectedType , useDefaultValue );
170
+ return all .isEmpty () ? null : all .get (0 );
117
171
}
118
172
119
173
/**
@@ -122,35 +176,9 @@ public <E, R extends E> R getOptional(String key, Class<E> expectedType, boolean
122
176
* @param useDefaultValue Whether the default value should be used if parsing failed.
123
177
* @return The entry's value. May be null if the entry is missing or a parsing error occurred.
124
178
*/
125
- @ Nullable
126
- public Object getOptional (String key , boolean useDefaultValue ) {
127
- if (entryValidator == null || handledNodes == null )
128
- return null ;
129
-
130
- EntryData <?> entryData = null ;
131
- for (EntryData <?> data : entryValidator .getEntryData ()) {
132
- if (data .getKey ().equals (key )) {
133
- entryData = data ;
134
- break ;
135
- }
136
- }
137
- if (entryData == null )
138
- return null ;
139
-
140
- Node node = handledNodes .get (key );
141
- if (node == null )
142
- return entryData .getDefaultValue ();
143
-
144
- // Update ParserInstance node for parsing
145
- ParserInstance parser = ParserInstance .get ();
146
- Node oldNode = parser .getNode ();
147
- parser .setNode (node );
148
- Object value = entryData .getValue (node );
149
- if (value == null && useDefaultValue )
150
- value = entryData .getDefaultValue ();
151
- parser .setNode (oldNode );
152
-
153
- return value ;
179
+ public @ Nullable Object getOptional (String key , boolean useDefaultValue ) {
180
+ List <Object > all = getAll (key , useDefaultValue );
181
+ return all .isEmpty () ? null : all .get (0 );
154
182
}
155
183
156
184
/**
@@ -159,7 +187,7 @@ public Object getOptional(String key, boolean useDefaultValue) {
159
187
* @return true if an entry data with the matching key was used.
160
188
*/
161
189
public boolean hasEntry (@ NotNull String key ) {
162
- return handledNodes .containsKey (key );
190
+ return handledNodes != null && handledNodes .containsKey (key );
163
191
}
164
192
165
193
}
0 commit comments