1 package net.sumaris.server.http.graphql;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 import com.fasterxml.jackson.databind.ObjectMapper;
26 import com.google.common.collect.Lists;
27 import com.google.common.collect.Maps;
28 import graphql.ExceptionWhileDataFetching;
29 import graphql.ExecutionResult;
30 import graphql.GraphQLError;
31 import graphql.GraphQLException;
32 import graphql.execution.AbortExecutionException;
33 import graphql.execution.ExecutionPath;
34 import graphql.servlet.GenericGraphQLError;
35 import net.sumaris.core.exception.SumarisBusinessException;
36 import net.sumaris.core.exception.SumarisTechnicalException;
37 import net.sumaris.server.exception.ErrorCodes;
38 import net.sumaris.server.exception.ErrorHelper;
39 import org.apache.commons.collections4.CollectionUtils;
40 import org.apache.commons.lang3.StringUtils;
41 import org.springframework.dao.DataRetrievalFailureException;
42 import org.springframework.security.access.AccessDeniedException;
43
44 import java.io.IOException;
45 import java.util.HashMap;
46 import java.util.List;
47 import java.util.Map;
48
49 public class GraphQLHelper {
50
51 private GraphQLHelper() {
52
53 }
54
55
56 public static Map<String, Object> getVariables(Map<String, Object> request, ObjectMapper objectMapper) {
57 Object variablesObj = request.get("variables");
58 if (variablesObj == null) {
59 return Maps.newHashMap();
60 }
61 if (variablesObj instanceof String) {
62 String variableStr = (String) variablesObj;
63 if (StringUtils.isBlank(variableStr)) {
64 return null;
65 }
66
67 try {
68 return objectMapper.readValue(variableStr, Map.class);
69 } catch (IOException e) {
70 throw new SumarisTechnicalException(ErrorCodes.INVALID_QUERY_VARIABLES, e);
71 }
72 } else if (variablesObj instanceof Map) {
73 return (Map<String, Object>) variablesObj;
74 }
75 else {
76 throw new SumarisTechnicalException(ErrorCodes.INVALID_QUERY_VARIABLES, "Unable to read param [variables] from the GraphQL request");
77 }
78 }
79
80 public static Map<String, Object> processExecutionResult(ExecutionResult executionResult) {
81 if (CollectionUtils.isEmpty(executionResult.getErrors())) return executionResult.toSpecification();
82
83 Map<String, Object> specifications = Maps.newHashMap();
84 specifications.putAll(executionResult.toSpecification());
85
86 List<Map<String, Object>> errors = Lists.newArrayList();
87 for (GraphQLError error: executionResult.getErrors()) {
88 error = processGraphQLError(error);
89 Map<String, Object> newError = Maps.newLinkedHashMap();
90 newError.put("message", error.getMessage());
91 newError.put("locations", error.getLocations());
92 newError.put("path", error.getPath());
93 errors.add(newError);
94 }
95 specifications.put("errors", errors);
96
97 return specifications;
98 }
99
100 public static Map<String, Object> processError(Throwable throwable) {
101
102 Map<String, Object> payload = Maps.newHashMap();
103 List<Map<String, Object>> errors = Lists.newArrayList();
104
105 Throwable cause = getSqlExceptionOrRootCause(throwable);
106 GraphQLError error = tryCreateGraphQLError(cause);
107 if (error == null) {
108 error = new GenericGraphQLError(cause.getMessage());
109 }
110
111 Map<String, Object> newError = Maps.newLinkedHashMap();
112 newError.put("message", error.getMessage());
113 newError.put("locations", error.getLocations());
114 newError.put("path", error.getPath());
115 errors.add(newError);
116
117 payload.put("errors", errors);
118
119 return payload;
120 }
121
122 public static GraphQLError processGraphQLError(final GraphQLError error) {
123 if (error instanceof ExceptionWhileDataFetching) {
124 ExceptionWhileDataFetching exError = (ExceptionWhileDataFetching) error;
125 Throwable baseException = getSqlExceptionOrRootCause(exError.getException());
126
127
128 GraphQLError result = tryCreateGraphQLError(baseException);
129 if (result != null) return result;
130
131 return new ExceptionWhileDataFetching(ExecutionPath.fromList(exError.getPath()),
132 new GraphQLException(baseException.getMessage()),
133 exError.getLocations().get(0));
134 }
135 return error;
136 }
137
138 public static GraphQLError tryCreateGraphQLError(final Throwable error) {
139 Throwable cause = getSqlExceptionOrRootCause(error);
140
141 if (cause instanceof SumarisBusinessException) {
142 SumarisBusinessExceptionmaris/core/exception/SumarisBusinessException.html#SumarisBusinessException">SumarisBusinessException exception = (SumarisBusinessException) cause;
143 return new AbortExecutionException(toJsonErrorString(exception.getCode(), error.getMessage()));
144 }
145 else if (cause instanceof SumarisTechnicalException) {
146 SumarisTechnicalExceptionaris/core/exception/SumarisTechnicalException.html#SumarisTechnicalException">SumarisTechnicalException exception = (SumarisTechnicalException) cause;
147 return new AbortExecutionException(toJsonErrorString(exception.getCode(), error.getMessage()));
148 }
149
150
151 else if (cause instanceof java.sql.SQLException) {
152 return new AbortExecutionException(toJsonErrorString(ErrorCodes.INTERNAL_ERROR, error.getMessage()));
153 }
154
155
156 else if (cause instanceof DataRetrievalFailureException) {
157 DataRetrievalFailureException exception = (DataRetrievalFailureException) cause;
158 return new AbortExecutionException(toJsonErrorString(ErrorCodes.NOT_FOUND, exception.getMessage()));
159 }
160
161
162 else if (cause instanceof AccessDeniedException) {
163 return new AbortExecutionException(toJsonErrorString(ErrorCodes.UNAUTHORIZED, cause.getMessage()));
164 }
165
166 return null;
167 }
168
169
170 public static Throwable getSqlExceptionOrRootCause(Throwable t) {
171 if (t instanceof java.sql.SQLException) {
172 return t;
173 }
174 if (t.getCause() != null) {
175 return getSqlExceptionOrRootCause(t.getCause());
176 }
177 return t;
178 }
179
180 public static String toJsonErrorString(int code, String message) {
181 return ErrorHelper.toJsonErrorString(code, message);
182 }
183
184
185 }