Skip to content

Commit 17dffdb

Browse files
authored
Merge pull request #4086 from graphql-java/ban-map-of
Prohibit Map.of and provide alternative methods
2 parents 9c92725 + 11d1357 commit 17dffdb

File tree

3 files changed

+383
-2
lines changed

3 files changed

+383
-2
lines changed

src/main/java/graphql/normalized/ExecutableNormalizedOperationToAstCompiler.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import graphql.schema.GraphQLObjectType;
2525
import graphql.schema.GraphQLSchema;
2626
import graphql.schema.GraphQLUnmodifiedType;
27+
import graphql.util.LinkedHashMapFactory;
2728
import org.jspecify.annotations.NonNull;
2829
import org.jspecify.annotations.Nullable;
2930

@@ -100,7 +101,7 @@ public static CompilerResult compileToDocument(@NonNull GraphQLSchema schema,
100101
@Nullable String operationName,
101102
@NonNull List<ExecutableNormalizedField> topLevelFields,
102103
@Nullable VariablePredicate variablePredicate) {
103-
return compileToDocument(schema, operationKind, operationName, topLevelFields, Map.of(), variablePredicate);
104+
return compileToDocument(schema, operationKind, operationName, topLevelFields, LinkedHashMapFactory.of(), variablePredicate);
104105
}
105106

106107
/**
@@ -151,7 +152,7 @@ public static CompilerResult compileToDocumentWithDeferSupport(@NonNull GraphQLS
151152
@NonNull List<ExecutableNormalizedField> topLevelFields,
152153
@Nullable VariablePredicate variablePredicate
153154
) {
154-
return compileToDocumentWithDeferSupport(schema, operationKind, operationName, topLevelFields, Map.of(), variablePredicate);
155+
return compileToDocumentWithDeferSupport(schema, operationKind, operationName, topLevelFields, LinkedHashMapFactory.of(), variablePredicate);
155156
}
156157

157158
/**
Lines changed: 344 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,344 @@
1+
package graphql.util;
2+
3+
import graphql.Internal;
4+
5+
import java.util.LinkedHashMap;
6+
import java.util.Map;
7+
8+
/**
9+
* Factory class for creating LinkedHashMap instances with insertion order preservation.
10+
* Use this instead of Map.of() to ensure consistent serialization order.
11+
* <p>
12+
* This class provides static factory methods similar to Map.of() but returns mutable LinkedHashMap
13+
* instances that preserve insertion order, which is important for consistent serialization.
14+
*/
15+
@Internal
16+
public final class LinkedHashMapFactory {
17+
18+
private LinkedHashMapFactory() {
19+
// utility class
20+
}
21+
22+
/**
23+
* Returns an empty LinkedHashMap.
24+
*
25+
* @param <K> the key type
26+
* @param <V> the value type
27+
* @return an empty LinkedHashMap
28+
*/
29+
public static <K, V> Map<K, V> of() {
30+
return new LinkedHashMap<>();
31+
}
32+
33+
/**
34+
* Returns a LinkedHashMap containing a single mapping.
35+
*
36+
* @param <K> the key type
37+
* @param <V> the value type
38+
* @param k1 the mapping's key
39+
* @param v1 the mapping's value
40+
* @return a LinkedHashMap containing the specified mapping
41+
*/
42+
public static <K, V> Map<K, V> of(K k1, V v1) {
43+
Map<K, V> map = new LinkedHashMap<>(1);
44+
map.put(k1, v1);
45+
return map;
46+
}
47+
48+
/**
49+
* Returns a LinkedHashMap containing two mappings.
50+
*
51+
* @param <K> the key type
52+
* @param <V> the value type
53+
* @param k1 the first mapping's key
54+
* @param v1 the first mapping's value
55+
* @param k2 the second mapping's key
56+
* @param v2 the second mapping's value
57+
* @return a LinkedHashMap containing the specified mappings
58+
*/
59+
public static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2) {
60+
Map<K, V> map = new LinkedHashMap<>(2);
61+
map.put(k1, v1);
62+
map.put(k2, v2);
63+
return map;
64+
}
65+
66+
/**
67+
* Returns a LinkedHashMap containing three mappings.
68+
*
69+
* @param <K> the key type
70+
* @param <V> the value type
71+
* @param k1 the first mapping's key
72+
* @param v1 the first mapping's value
73+
* @param k2 the second mapping's key
74+
* @param v2 the second mapping's value
75+
* @param k3 the third mapping's key
76+
* @param v3 the third mapping's value
77+
* @return a LinkedHashMap containing the specified mappings
78+
*/
79+
public static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) {
80+
Map<K, V> map = new LinkedHashMap<>(3);
81+
map.put(k1, v1);
82+
map.put(k2, v2);
83+
map.put(k3, v3);
84+
return map;
85+
}
86+
87+
/**
88+
* Returns a LinkedHashMap containing four mappings.
89+
*
90+
* @param <K> the key type
91+
* @param <V> the value type
92+
* @param k1 the first mapping's key
93+
* @param v1 the first mapping's value
94+
* @param k2 the second mapping's key
95+
* @param v2 the second mapping's value
96+
* @param k3 the third mapping's key
97+
* @param v3 the third mapping's value
98+
* @param k4 the fourth mapping's key
99+
* @param v4 the fourth mapping's value
100+
* @return a LinkedHashMap containing the specified mappings
101+
*/
102+
public static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
103+
Map<K, V> map = new LinkedHashMap<>(4);
104+
map.put(k1, v1);
105+
map.put(k2, v2);
106+
map.put(k3, v3);
107+
map.put(k4, v4);
108+
return map;
109+
}
110+
111+
/**
112+
* Returns a LinkedHashMap containing five mappings.
113+
*
114+
* @param <K> the key type
115+
* @param <V> the value type
116+
* @param k1 the first mapping's key
117+
* @param v1 the first mapping's value
118+
* @param k2 the second mapping's key
119+
* @param v2 the second mapping's value
120+
* @param k3 the third mapping's key
121+
* @param v3 the third mapping's value
122+
* @param k4 the fourth mapping's key
123+
* @param v4 the fourth mapping's value
124+
* @param k5 the fifth mapping's key
125+
* @param v5 the fifth mapping's value
126+
* @return a LinkedHashMap containing the specified mappings
127+
*/
128+
public static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
129+
Map<K, V> map = new LinkedHashMap<>(5);
130+
map.put(k1, v1);
131+
map.put(k2, v2);
132+
map.put(k3, v3);
133+
map.put(k4, v4);
134+
map.put(k5, v5);
135+
return map;
136+
}
137+
138+
/**
139+
* Returns a LinkedHashMap containing six mappings.
140+
*
141+
* @param <K> the key type
142+
* @param <V> the value type
143+
* @param k1 the first mapping's key
144+
* @param v1 the first mapping's value
145+
* @param k2 the second mapping's key
146+
* @param v2 the second mapping's value
147+
* @param k3 the third mapping's key
148+
* @param v3 the third mapping's value
149+
* @param k4 the fourth mapping's key
150+
* @param v4 the fourth mapping's value
151+
* @param k5 the fifth mapping's key
152+
* @param v5 the fifth mapping's value
153+
* @param k6 the sixth mapping's key
154+
* @param v6 the sixth mapping's value
155+
* @return a LinkedHashMap containing the specified mappings
156+
*/
157+
public static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6) {
158+
Map<K, V> map = new LinkedHashMap<>(6);
159+
map.put(k1, v1);
160+
map.put(k2, v2);
161+
map.put(k3, v3);
162+
map.put(k4, v4);
163+
map.put(k5, v5);
164+
map.put(k6, v6);
165+
return map;
166+
}
167+
168+
/**
169+
* Returns a LinkedHashMap containing seven mappings.
170+
*
171+
* @param <K> the key type
172+
* @param <V> the value type
173+
* @param k1 the first mapping's key
174+
* @param v1 the first mapping's value
175+
* @param k2 the second mapping's key
176+
* @param v2 the second mapping's value
177+
* @param k3 the third mapping's key
178+
* @param v3 the third mapping's value
179+
* @param k4 the fourth mapping's key
180+
* @param v4 the fourth mapping's value
181+
* @param k5 the fifth mapping's key
182+
* @param v5 the fifth mapping's value
183+
* @param k6 the sixth mapping's key
184+
* @param v6 the sixth mapping's value
185+
* @param k7 the seventh mapping's key
186+
* @param v7 the seventh mapping's value
187+
* @return a LinkedHashMap containing the specified mappings
188+
*/
189+
public static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7) {
190+
Map<K, V> map = new LinkedHashMap<>(7);
191+
map.put(k1, v1);
192+
map.put(k2, v2);
193+
map.put(k3, v3);
194+
map.put(k4, v4);
195+
map.put(k5, v5);
196+
map.put(k6, v6);
197+
map.put(k7, v7);
198+
return map;
199+
}
200+
201+
/**
202+
* Returns a LinkedHashMap containing eight mappings.
203+
*
204+
* @param <K> the key type
205+
* @param <V> the value type
206+
* @param k1 the first mapping's key
207+
* @param v1 the first mapping's value
208+
* @param k2 the second mapping's key
209+
* @param v2 the second mapping's value
210+
* @param k3 the third mapping's key
211+
* @param v3 the third mapping's value
212+
* @param k4 the fourth mapping's key
213+
* @param v4 the fourth mapping's value
214+
* @param k5 the fifth mapping's key
215+
* @param v5 the fifth mapping's value
216+
* @param k6 the sixth mapping's key
217+
* @param v6 the sixth mapping's value
218+
* @param k7 the seventh mapping's key
219+
* @param v7 the seventh mapping's value
220+
* @param k8 the eighth mapping's key
221+
* @param v8 the eighth mapping's value
222+
* @return a LinkedHashMap containing the specified mappings
223+
*/
224+
public static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8) {
225+
Map<K, V> map = new LinkedHashMap<>(8);
226+
map.put(k1, v1);
227+
map.put(k2, v2);
228+
map.put(k3, v3);
229+
map.put(k4, v4);
230+
map.put(k5, v5);
231+
map.put(k6, v6);
232+
map.put(k7, v7);
233+
map.put(k8, v8);
234+
return map;
235+
}
236+
237+
/**
238+
* Returns a LinkedHashMap containing nine mappings.
239+
*
240+
* @param <K> the key type
241+
* @param <V> the value type
242+
* @param k1 the first mapping's key
243+
* @param v1 the first mapping's value
244+
* @param k2 the second mapping's key
245+
* @param v2 the second mapping's value
246+
* @param k3 the third mapping's key
247+
* @param v3 the third mapping's value
248+
* @param k4 the fourth mapping's key
249+
* @param v4 the fourth mapping's value
250+
* @param k5 the fifth mapping's key
251+
* @param v5 the fifth mapping's value
252+
* @param k6 the sixth mapping's key
253+
* @param v6 the sixth mapping's value
254+
* @param k7 the seventh mapping's key
255+
* @param v7 the seventh mapping's value
256+
* @param k8 the eighth mapping's key
257+
* @param v8 the eighth mapping's value
258+
* @param k9 the ninth mapping's key
259+
* @param v9 the ninth mapping's value
260+
* @return a LinkedHashMap containing the specified mappings
261+
*/
262+
public static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9) {
263+
Map<K, V> map = new LinkedHashMap<>(9);
264+
map.put(k1, v1);
265+
map.put(k2, v2);
266+
map.put(k3, v3);
267+
map.put(k4, v4);
268+
map.put(k5, v5);
269+
map.put(k6, v6);
270+
map.put(k7, v7);
271+
map.put(k8, v8);
272+
map.put(k9, v9);
273+
return map;
274+
}
275+
276+
/**
277+
* Returns a LinkedHashMap containing ten mappings.
278+
*
279+
* @param <K> the key type
280+
* @param <V> the value type
281+
* @param k1 the first mapping's key
282+
* @param v1 the first mapping's value
283+
* @param k2 the second mapping's key
284+
* @param v2 the second mapping's value
285+
* @param k3 the third mapping's key
286+
* @param v3 the third mapping's value
287+
* @param k4 the fourth mapping's key
288+
* @param v4 the fourth mapping's value
289+
* @param k5 the fifth mapping's key
290+
* @param v5 the fifth mapping's value
291+
* @param k6 the sixth mapping's key
292+
* @param v6 the sixth mapping's value
293+
* @param k7 the seventh mapping's key
294+
* @param v7 the seventh mapping's value
295+
* @param k8 the eighth mapping's key
296+
* @param v8 the eighth mapping's value
297+
* @param k9 the ninth mapping's key
298+
* @param v9 the ninth mapping's value
299+
* @param k10 the tenth mapping's key
300+
* @param v10 the tenth mapping's value
301+
* @return a LinkedHashMap containing the specified mappings
302+
*/
303+
public static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9, K k10, V v10) {
304+
Map<K, V> map = new LinkedHashMap<>(10);
305+
map.put(k1, v1);
306+
map.put(k2, v2);
307+
map.put(k3, v3);
308+
map.put(k4, v4);
309+
map.put(k5, v5);
310+
map.put(k6, v6);
311+
map.put(k7, v7);
312+
map.put(k8, v8);
313+
map.put(k9, v9);
314+
map.put(k10, v10);
315+
return map;
316+
}
317+
318+
/**
319+
* Returns a LinkedHashMap containing mappings derived from the given arguments.
320+
* <p>
321+
* This method is provided for cases where more than 10 key-value pairs are needed.
322+
* It accepts alternating keys and values.
323+
*
324+
* @param <K> the key type
325+
* @param <V> the value type
326+
* @param keyValues alternating keys and values
327+
* @return a LinkedHashMap containing the specified mappings
328+
* @throws IllegalArgumentException if an odd number of arguments is provided
329+
*/
330+
@SuppressWarnings("unchecked")
331+
public static <K, V> Map<K, V> ofEntries(Object... keyValues) {
332+
if (keyValues.length % 2 != 0) {
333+
throw new IllegalArgumentException("keyValues must contain an even number of arguments (key-value pairs)");
334+
}
335+
336+
Map<K, V> map = new LinkedHashMap<>(keyValues.length / 2);
337+
for (int i = 0; i < keyValues.length; i += 2) {
338+
K key = (K) keyValues[i];
339+
V value = (V) keyValues[i + 1];
340+
map.put(key, value);
341+
}
342+
return map;
343+
}
344+
}

0 commit comments

Comments
 (0)