|
1 | 1 | package graphql; |
2 | 2 |
|
| 3 | +import com.google.common.collect.ImmutableList; |
| 4 | +import com.google.common.collect.ImmutableMap; |
3 | 5 | import graphql.schema.GraphQLArgument; |
4 | 6 | import graphql.schema.GraphQLDirective; |
5 | 7 | import graphql.util.FpKit; |
6 | 8 |
|
| 9 | +import java.util.Collection; |
7 | 10 | import java.util.List; |
8 | 11 | import java.util.Map; |
9 | 12 | import java.util.Optional; |
| 13 | +import java.util.stream.Collectors; |
| 14 | + |
| 15 | +import static graphql.Assert.assertNotNull; |
| 16 | +import static graphql.collect.ImmutableKit.emptyList; |
10 | 17 |
|
11 | 18 | @Internal |
12 | 19 | public class DirectivesUtil { |
13 | 20 |
|
14 | | - public static Map<String, GraphQLDirective> directivesByName(List<GraphQLDirective> directiveList) { |
15 | | - return FpKit.getByName(directiveList, GraphQLDirective::getName, FpKit.mergeFirst()); |
| 21 | + |
| 22 | + public static Map<String, GraphQLDirective> nonRepeatableDirectivesByName(List<GraphQLDirective> directives) { |
| 23 | + // filter the repeatable directives |
| 24 | + List<GraphQLDirective> singletonDirectives = directives.stream() |
| 25 | + .filter(d -> !d.isRepeatable()).collect(Collectors.toList()); |
| 26 | + |
| 27 | + return FpKit.getByName(singletonDirectives, GraphQLDirective::getName); |
16 | 28 | } |
17 | 29 |
|
18 | | - public static Optional<GraphQLDirective> directiveByName(List<GraphQLDirective> directives, String directiveName) { |
19 | | - for (GraphQLDirective directive : directives) { |
20 | | - if (directive.getName().equals(directiveName)) { |
21 | | - return Optional.of(directive); |
22 | | - } |
| 30 | + public static Map<String, ImmutableList<GraphQLDirective>> allDirectivesByName(List<GraphQLDirective> directives) { |
| 31 | + |
| 32 | + return ImmutableMap.copyOf(FpKit.groupingBy(directives, GraphQLDirective::getName)); |
| 33 | + } |
| 34 | + |
| 35 | + public static GraphQLDirective nonRepeatedDirectiveByNameWithAssert(Map<String, List<GraphQLDirective>> directives, String directiveName) { |
| 36 | + List<GraphQLDirective> directiveList = directives.get(directiveName); |
| 37 | + if (directiveList == null || directiveList.isEmpty()) { |
| 38 | + return null; |
23 | 39 | } |
24 | | - return Optional.empty(); |
| 40 | + Assert.assertTrue(isAllNonRepeatable(directiveList), () -> String.format("'%s' is a repeatable directive and you have used a non repeatable access method", directiveName)); |
| 41 | + return directiveList.get(0); |
25 | 42 | } |
26 | 43 |
|
27 | | - public static Optional<GraphQLArgument> directiveWithArg(List<GraphQLDirective> directiveList, String directiveName, String argumentName) { |
28 | | - GraphQLDirective directive = directiveByName(directiveList, directiveName).orElse(null); |
| 44 | + public static Optional<GraphQLArgument> directiveWithArg(List<GraphQLDirective> directives, String directiveName, String argumentName) { |
| 45 | + GraphQLDirective directive = nonRepeatableDirectivesByName(directives).get(directiveName); |
29 | 46 | GraphQLArgument argument = null; |
30 | 47 | if (directive != null) { |
31 | 48 | argument = directive.getArgument(argumentName); |
32 | 49 | } |
33 | 50 | return Optional.ofNullable(argument); |
34 | 51 | } |
| 52 | + |
| 53 | + |
| 54 | + public static boolean isAllNonRepeatable(List<GraphQLDirective> directives) { |
| 55 | + if (directives == null || directives.isEmpty()) { |
| 56 | + return false; |
| 57 | + } |
| 58 | + for (GraphQLDirective graphQLDirective : directives) { |
| 59 | + if (graphQLDirective.isRepeatable()) { |
| 60 | + return false; |
| 61 | + } |
| 62 | + } |
| 63 | + return true; |
| 64 | + } |
| 65 | + |
| 66 | + public static List<GraphQLDirective> enforceAdd(List<GraphQLDirective> targetList, GraphQLDirective newDirective) { |
| 67 | + assertNotNull(targetList, () -> "directive list can't be null"); |
| 68 | + assertNotNull(newDirective, () -> "directive can't be null"); |
| 69 | + |
| 70 | + // check whether the newDirective is repeatable in advance, to avoid needless operations |
| 71 | + if (newDirective.isNonRepeatable()) { |
| 72 | + Map<String, ImmutableList<GraphQLDirective>> map = allDirectivesByName(targetList); |
| 73 | + assertNonRepeatable(newDirective, map); |
| 74 | + } |
| 75 | + targetList.add(newDirective); |
| 76 | + return targetList; |
| 77 | + } |
| 78 | + |
| 79 | + public static List<GraphQLDirective> enforceAddAll(List<GraphQLDirective> targetList, List<GraphQLDirective> newDirectives) { |
| 80 | + assertNotNull(targetList, () -> "directive list can't be null"); |
| 81 | + assertNotNull(newDirectives, () -> "directive list can't be null"); |
| 82 | + Map<String, ImmutableList<GraphQLDirective>> map = allDirectivesByName(targetList); |
| 83 | + for (GraphQLDirective newDirective : newDirectives) { |
| 84 | + assertNonRepeatable(newDirective, map); |
| 85 | + targetList.add(newDirective); |
| 86 | + } |
| 87 | + return targetList; |
| 88 | + } |
| 89 | + |
| 90 | + private static void assertNonRepeatable(GraphQLDirective directive, Map<String, ImmutableList<GraphQLDirective>> mapOfDirectives) { |
| 91 | + if (directive.isNonRepeatable()) { |
| 92 | + List<GraphQLDirective> currentDirectives = mapOfDirectives.getOrDefault(directive.getName(), emptyList()); |
| 93 | + int currentSize = currentDirectives.size(); |
| 94 | + if (currentSize > 0) { |
| 95 | + Assert.assertShouldNeverHappen("%s is a non repeatable directive but there is already one present in this list", directive.getName()); |
| 96 | + } |
| 97 | + } |
| 98 | + } |
| 99 | + |
| 100 | + public static GraphQLDirective getFirstDirective(String name, Map<String, List<GraphQLDirective>> allDirectivesByName) { |
| 101 | + List<GraphQLDirective> directives = allDirectivesByName.getOrDefault(name, emptyList()); |
| 102 | + if (directives.isEmpty()) { |
| 103 | + return null; |
| 104 | + } |
| 105 | + return directives.get(0); |
| 106 | + } |
| 107 | + |
| 108 | + /** |
| 109 | + * A holder class that breaks a list of directives into maps to be more easily accessible in using classes |
| 110 | + */ |
| 111 | + public static class DirectivesHolder { |
| 112 | + |
| 113 | + private final ImmutableMap<String, List<GraphQLDirective>> allDirectivesByName; |
| 114 | + private final ImmutableMap<String, GraphQLDirective> nonRepeatableDirectivesByName; |
| 115 | + private final List<GraphQLDirective> allDirectives; |
| 116 | + |
| 117 | + public DirectivesHolder(Collection<GraphQLDirective> allDirectives) { |
| 118 | + this.allDirectives = ImmutableList.copyOf(allDirectives); |
| 119 | + this.allDirectivesByName = ImmutableMap.copyOf(FpKit.groupingBy(allDirectives, GraphQLDirective::getName)); |
| 120 | + // filter out the repeatable directives |
| 121 | + List<GraphQLDirective> nonRepeatableDirectives = allDirectives.stream() |
| 122 | + .filter(d -> !d.isRepeatable()).collect(Collectors.toList()); |
| 123 | + this.nonRepeatableDirectivesByName = ImmutableMap.copyOf(FpKit.getByName(nonRepeatableDirectives, GraphQLDirective::getName)); |
| 124 | + } |
| 125 | + |
| 126 | + public ImmutableMap<String, List<GraphQLDirective>> getAllDirectivesByName() { |
| 127 | + return allDirectivesByName; |
| 128 | + } |
| 129 | + |
| 130 | + public ImmutableMap<String, GraphQLDirective> getDirectivesByName() { |
| 131 | + return nonRepeatableDirectivesByName; |
| 132 | + } |
| 133 | + |
| 134 | + public List<GraphQLDirective> getDirectives() { |
| 135 | + return allDirectives; |
| 136 | + } |
| 137 | + |
| 138 | + public GraphQLDirective getDirective(String directiveName) { |
| 139 | + List<GraphQLDirective> directiveList = allDirectivesByName.get(directiveName); |
| 140 | + if (directiveList == null || directiveList.isEmpty()) { |
| 141 | + return null; |
| 142 | + } |
| 143 | + Assert.assertTrue(isAllNonRepeatable(directiveList), () -> String.format("'%s' is a repeatable directive and you have used a non repeatable access method", directiveName)); |
| 144 | + return directiveList.get(0); |
| 145 | + |
| 146 | + } |
| 147 | + |
| 148 | + public List<GraphQLDirective> getDirectives(String directiveName) { |
| 149 | + return allDirectivesByName.getOrDefault(directiveName, emptyList()); |
| 150 | + } |
| 151 | + } |
35 | 152 | } |
0 commit comments