Skip to content

Commit

Permalink
Merge pull request #264 from singh-sardar/bugfix/graphql-constructor-…
Browse files Browse the repository at this point in the history
…annotation

bugfix for MethodDataFetcher:buildArg #262
  • Loading branch information
yarinvak authored Oct 30, 2020
2 parents 0fafe62 + 80af2df commit 6246639
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 18 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
*/
package graphql.annotations.annotationTypes;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/***
* When using object as argument of query or mutation, a HashMap Constructor is used to initialize
* the object fields. In order to identify the correct constructor this annotation must be used, otherwise
* the object fields will be null
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.CONSTRUCTOR)
public @interface GraphQLConstructor {
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
/**
* Copyright 2016 Yurii Rashkovskii
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
Expand All @@ -15,6 +13,7 @@
package graphql.annotations.dataFetchers;

import graphql.annotations.annotationTypes.GraphQLBatched;
import graphql.annotations.annotationTypes.GraphQLConstructor;
import graphql.annotations.annotationTypes.GraphQLInvokeDetached;
import graphql.annotations.annotationTypes.GraphQLName;
import graphql.annotations.processor.ProcessingElementsContainer;
Expand Down Expand Up @@ -68,10 +67,9 @@ public MethodDataFetcher(Method method, TypeFunction typeFunction, ProcessingEle
public T get(DataFetchingEnvironment environment) {
try {
T obj;
if (Modifier.isStatic(method.getModifiers())){
if (Modifier.isStatic(method.getModifiers())) {
return (T) method.invoke(null, invocationArgs(environment, container));
}
else if (method.isAnnotationPresent(GraphQLBatched.class) || method.isAnnotationPresent(GraphQLInvokeDetached.class)) {
} else if (method.isAnnotationPresent(GraphQLBatched.class) || method.isAnnotationPresent(GraphQLInvokeDetached.class)) {
obj = newInstance((Class<T>) method.getDeclaringClass());
} else if (!method.getDeclaringClass().isInstance(environment.getSource())) {
obj = newInstance((Class<T>) method.getDeclaringClass(), environment.getSource());
Expand Down Expand Up @@ -130,21 +128,19 @@ private Object buildArg(Type p, GraphQLType graphQLType, Object arg) {
}
if (p instanceof Class<?> && graphQLType instanceof GraphQLInputObjectType) {
Constructor<?> constructors[] = ((Class) p).getConstructors();
for (Constructor<?> constructor : constructors) {
Parameter[] parameters = constructor.getParameters();
if (parameters.length == 1 && parameters[0].getType().isAssignableFrom(arg.getClass())) {
return constructNewInstance(constructor, arg);
} else {
List<Object> objects = new ArrayList<>();
Map map = (Map) arg;
for (Parameter parameter : parameters) {
String name = toGraphqlName(parameter.getAnnotation(GraphQLName.class) != null ? parameter.getAnnotation(GraphQLName.class).value() : parameter.getName());
objects.add(buildArg(parameter.getParameterizedType(), ((GraphQLInputObjectType) graphQLType).getField(name).getType(), map.get(name)));
}
return constructNewInstance(constructor, objects.toArray(new Object[objects.size()]));
Constructor<?> constructor = getBuildArgConstructor(constructors);
Parameter[] parameters = constructor.getParameters();
if (parameters.length == 1 && parameters[0].getType().isAssignableFrom(arg.getClass())) {
return constructNewInstance(constructor, arg);
} else {
List<Object> objects = new ArrayList<>();
Map map = (Map) arg;
for (Parameter parameter : parameters) {
String name = toGraphqlName(parameter.getAnnotation(GraphQLName.class) != null ? parameter.getAnnotation(GraphQLName.class).value() : parameter.getName());
objects.add(buildArg(parameter.getParameterizedType(), ((GraphQLInputObjectType) graphQLType).getField(name).getType(), map.get(name)));
}
return constructNewInstance(constructor, objects.toArray(new Object[objects.size()]));
}
return null;
} else if (p instanceof ParameterizedType && graphQLType instanceof GraphQLList) {
List<Object> list = new ArrayList<>();
Type subType = ((ParameterizedType) p).getActualTypeArguments()[0];
Expand All @@ -160,6 +156,24 @@ private Object buildArg(Type p, GraphQLType graphQLType, Object arg) {
}
}


/***
* return the constructor to call in order to build the object
* @param constructors Object constructors
* @return the annotated constructor if present else return the first constructor
*/
private Constructor getBuildArgConstructor(Constructor<?> constructors[]) {
if (constructors != null) {
for (Constructor<?> constructor : constructors) {
if (constructor.isAnnotationPresent(GraphQLConstructor.class)) {
return constructor;
}
}
return constructors[0];
}
return null;
}

private Object getGraphQLFieldValue(Object source, String fieldName) throws IllegalAccessException, NoSuchFieldException, InvocationTargetException {
Object methodValue = getValueFromMethod(source, fieldName);
if (methodValue != null) return methodValue;
Expand Down

0 comments on commit 6246639

Please sign in to comment.