Skip to content

Commit 4703692

Browse files
authored
Merge pull request graphql-java#3720 from AlexandreCarlton/add-equals-hashcode-for-graphqlerrorimpl
Implement equals/hashCode for GraphqlErrorImpl
2 parents 1491db6 + 25a3b9f commit 4703692

File tree

2 files changed

+98
-1
lines changed

2 files changed

+98
-1
lines changed

src/main/java/graphql/GraphqlErrorBuilder.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import java.util.ArrayList;
1010
import java.util.List;
1111
import java.util.Map;
12+
import java.util.Objects;
1213

1314
import static graphql.Assert.assertNotNull;
1415

@@ -132,6 +133,18 @@ public GraphQLError build() {
132133
return new GraphqlErrorImpl(message, locations, errorType, path, extensions);
133134
}
134135

136+
/**
137+
* A simple implementation of a {@link GraphQLError}.
138+
* <p>
139+
* This provides {@link #hashCode()} and {@link #equals(Object)} methods that afford comparison with other
140+
* {@link GraphQLError} implementations. However, the values provided in the following fields <b>must</b>
141+
* in turn implement {@link #hashCode()} and {@link #equals(Object)} for this to function correctly:
142+
* <ul>
143+
* <li>the values in the {@link #getPath()} {@link List}.
144+
* <li>the {@link #getErrorType()} {@link ErrorClassification}.
145+
* <li>the values in the {@link #getExtensions()} {@link Map}.
146+
* </ul>
147+
*/
135148
private static class GraphqlErrorImpl implements GraphQLError {
136149
private final String message;
137150
private final List<SourceLocation> locations;
@@ -176,6 +189,28 @@ public Map<String, Object> getExtensions() {
176189
public String toString() {
177190
return message;
178191
}
192+
193+
@Override
194+
public boolean equals(Object o) {
195+
if (this == o) return true;
196+
if (!(o instanceof GraphQLError)) return false;
197+
GraphQLError that = (GraphQLError) o;
198+
return Objects.equals(getMessage(), that.getMessage())
199+
&& Objects.equals(getLocations(), that.getLocations())
200+
&& Objects.equals(getErrorType(), that.getErrorType())
201+
&& Objects.equals(getPath(), that.getPath())
202+
&& Objects.equals(getExtensions(), that.getExtensions());
203+
}
204+
205+
@Override
206+
public int hashCode() {
207+
return Objects.hash(
208+
getMessage(),
209+
getLocations(),
210+
getErrorType(),
211+
getPath(),
212+
getExtensions());
213+
}
179214
}
180215

181216
/**

src/test/groovy/graphql/GraphqlErrorBuilderTest.groovy

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,4 +152,66 @@ class GraphqlErrorBuilderTest extends Specification {
152152
error.path == null
153153

154154
}
155-
}
155+
156+
def "implements equals/hashCode correctly for matching errors"() {
157+
when:
158+
def firstError = toGraphQLError(first)
159+
def secondError = toGraphQLError(second)
160+
161+
then:
162+
firstError == secondError
163+
firstError.hashCode() == secondError.hashCode()
164+
165+
where:
166+
first | second
167+
[message: "msg"] | [message: "msg"]
168+
[message: "msg", locations: [new SourceLocation(1, 2)]] | [message: "msg", locations: [new SourceLocation(1, 2)]]
169+
[message: "msg", errorType: ErrorType.InvalidSyntax] | [message: "msg", errorType: ErrorType.InvalidSyntax]
170+
[message: "msg", path: ["items", 1, "item"]] | [message: "msg", path: ["items", 1, "item"]]
171+
[message: "msg", extensions: [aBoolean: true, aString: "foo"]] | [message: "msg", extensions: [aBoolean: true, aString: "foo"]]
172+
}
173+
174+
def "implements equals/hashCode correctly for different errors"() {
175+
when:
176+
def firstError = toGraphQLError(first)
177+
def secondError = toGraphQLError(second)
178+
179+
then:
180+
firstError != secondError
181+
firstError.hashCode() != secondError.hashCode()
182+
183+
where:
184+
first | second
185+
[message: "msg"] | [message: "different msg"]
186+
[message: "msg", locations: [new SourceLocation(1, 2)]] | [message: "msg", locations: [new SourceLocation(3, 4)]]
187+
[message: "msg", errorType: ErrorType.InvalidSyntax] | [message: "msg", errorType: ErrorType.DataFetchingException]
188+
[message: "msg", path: ["items", "1", "item"]] | [message: "msg", path: ["items"]]
189+
[message: "msg", extensions: [aBoolean: false]] | [message: "msg", extensions: [aString: "foo"]]
190+
}
191+
192+
private static GraphQLError toGraphQLError(Map<String, Object> errorFields) {
193+
def errorBuilder = GraphQLError.newError();
194+
errorFields.forEach { key, value ->
195+
if (value != null) {
196+
switch (key) {
197+
case "message":
198+
errorBuilder.message(value as String);
199+
break;
200+
case "locations":
201+
errorBuilder.locations(value as List<SourceLocation>);
202+
break;
203+
case "errorType":
204+
errorBuilder.errorType(value as ErrorClassification);
205+
break;
206+
case "path":
207+
errorBuilder.path(value as List<Object>);
208+
break;
209+
case "extensions":
210+
errorBuilder.extensions(value as Map<String, Object>);
211+
break;
212+
}
213+
}
214+
}
215+
return errorBuilder.build();
216+
}
217+
}

0 commit comments

Comments
 (0)