// Path: src/main/java/com/bretpatterson/schemagen/graphql/IGraphQLObjectMapper.java
// public interface IGraphQLObjectMapper {
// 
// 	/**
// 	 * Get the object responsible for naming GraphQL types.
// 	 * @return
// 	 */
// 	ITypeNamingStrategy getTypeNamingStrategy();
// 
// 	/**
// 	 * Get an input definition for the specified type.
// 	 * @param type
// 	 */
// 	GraphQLInputType getInputType(Type type);
// 
// 	/**
// 	 * Get an output definition for the specified type.
// 	 * @param type
// 	 */
// 	GraphQLOutputType getOutputType(Type type);
// 
// 	/**
// 	 * Get the Input Type cache. This is useful for custom type mappers who
// 	 * might need to add TypeReference's to the cache when they need to process
// 	 * an object that contains a two way dependency between itself and another object.
// 	 */
// 	IGraphQLTypeCache<GraphQLInputType> getInputTypeCache();
// 
// 	/**
// 	 * Get the Input Type cache. This is useful for custom type mappers who
// 	 * might need to add TypeReference's to the cache when they need to process
// 	 * an object that contains a two way dependency between itself and another object.
// 	 */
// 	IGraphQLTypeCache<GraphQLOutputType> getOutputTypeCache();
// 
// 	/**
// 	 * Returns the object responsible for object type conversion.
// 	 * @return
// 	 */
// 	ITypeFactory getTypeFactory();
// 
// 	/**
// 	 * Get the raw type of this object for generic types
// 	 * @param type
// 	 * @return
// 	 */
// 	Class<?> getClassFromType(Type type);
// 
// 	/**
// 	 * Returns all input types created.
// 	 * @return
// 	 */
// 	Set<GraphQLType> getInputTypes();
// 
// 	/**
// 	 * Get the datafetcher factory
// 	 * @return
// 	 */
// 	IDataFetcherFactory getDataFetcherFactory() ;
// 
// 	/**
// 	 *
// 	 * @param dataFetcherFactory
// 	 */
// 	void setDataFetcherFactory(IDataFetcherFactory dataFetcherFactory);
// 
// 	/**
// 	 * Get the default datafetcher for methods
// 	 * @return
// 	 */
// 	Class<? extends IDataFetcher> getDefaultMethodDataFetcher();
// 
// 	/**
// 	 * Set the default data fetcher used for methods
// 	 * @param defaultMethodDataFetcher
// 	 */
// 	void setDefaultMethodDataFetcher(Class<? extends IDataFetcher> defaultMethodDataFetcher);
// 
// 	Collection<GraphQLFieldDefinition> getGraphQLFieldDefinitions(Optional<Object> targetObject, Type type, Class<?> classItem, Optional<List<Field>> fields, Optional<List<Method>> methods);
// }
// 
// Path: src/main/java/com/bretpatterson/schemagen/graphql/datafetchers/IMethodDataFetcher.java
// public interface IMethodDataFetcher extends IDataFetcher {
// 
// 	/**
// 	 * Called to let the data fetcher know about the Type factory registered for
// 	 * converting GraphQL deserialized data types to your Application method specific data types.
// 	 * {@link ITypeFactory}
// 	 * @param typeFactory
// 	 */
// 	void setTypeFactory(ITypeFactory typeFactory);
// 
// 	/**
// 	 * The field name that is used to invoke the query.{@link GraphQLQuery#name()}
// 	 *
// 	 * @param fieldName
// 	 */
// 	void setFieldName(String fieldName);
// 
// 	/**
// 	 * A reference to the method we will be invoking for this data fetcher.
// 	 * @param method
// 	 */
// 	void setMethod(Method method);
// 
// 	/**
// 	 * The target object the method will be invoked upon.
// 	 * @param targetObject
// 	 */
// 	void setTargetObject(Object targetObject);
// 
// 	/**
// 	 * Invokes the method on the target object with the specified arguments
// 	 * @param method the method to invoke
// 	 * @param targetObject the target object
// 	 * @param arguments the arguments to the method
// 	 * @return return value
// 	 */
// 	Object invokeMethod(DataFetchingEnvironment environment, Method method, Object targetObject, Object[] arguments);
// }


import com.bretpatterson.schemagen.graphql.IDataFetcherFactory;
import com.bretpatterson.schemagen.graphql.IGraphQLObjectMapper;
import com.bretpatterson.schemagen.graphql.datafetchers.IMethodDataFetcher;
import com.google.common.base.Optional;
import com.google.common.base.Throwables;
import graphql.schema.DataFetcher;
import graphql.schema.PropertyDataFetcher;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.security.InvalidParameterException;
package com.bretpatterson.schemagen.graphql.impl;


/**
 * The Default DataFetcher Factory. This only supports custom datafetchers of type IMethodDataFetcher
 */
public class DefaultDataFetcherFactory implements IDataFetcherFactory {

	@Override
	public DataFetcher newFieldDataFetcher(final IGraphQLObjectMapper objectMapper, final Optional<Object> targetObject, final Field field, String fieldName, Class<? extends DataFetcher> dataFetcher) {
		if (dataFetcher != null) {
			try {
				return dataFetcher.newInstance();
			} catch (IllegalAccessException | InstantiationException ex) {
				throw Throwables.propagate(ex);
			}
		} else {
			return new PropertyDataFetcher(fieldName);
		}
	}

	@Override
	public DataFetcher newMethodDataFetcher(final IGraphQLObjectMapper graphQLObjectMapper,
			final Optional<Object> targetObject,
			final Method method,
			final String fieldName,
			final Class<? extends DataFetcher> dataFetcher) {
		DataFetcher dataFetcherObject;
		try {
			dataFetcherObject = dataFetcher.newInstance();
// Path: src/main/java/com/bretpatterson/schemagen/graphql/IGraphQLObjectMapper.java
// public interface IGraphQLObjectMapper {
// 
// 	/**
// 	 * Get the object responsible for naming GraphQL types.
// 	 * @return
// 	 */
// 	ITypeNamingStrategy getTypeNamingStrategy();
// 
// 	/**
// 	 * Get an input definition for the specified type.
// 	 * @param type
// 	 */
// 	GraphQLInputType getInputType(Type type);
// 
// 	/**
// 	 * Get an output definition for the specified type.
// 	 * @param type
// 	 */
// 	GraphQLOutputType getOutputType(Type type);
// 
// 	/**
// 	 * Get the Input Type cache. This is useful for custom type mappers who
// 	 * might need to add TypeReference's to the cache when they need to process
// 	 * an object that contains a two way dependency between itself and another object.
// 	 */
// 	IGraphQLTypeCache<GraphQLInputType> getInputTypeCache();
// 
// 	/**
// 	 * Get the Input Type cache. This is useful for custom type mappers who
// 	 * might need to add TypeReference's to the cache when they need to process
// 	 * an object that contains a two way dependency between itself and another object.
// 	 */
// 	IGraphQLTypeCache<GraphQLOutputType> getOutputTypeCache();
// 
// 	/**
// 	 * Returns the object responsible for object type conversion.
// 	 * @return
// 	 */
// 	ITypeFactory getTypeFactory();
// 
// 	/**
// 	 * Get the raw type of this object for generic types
// 	 * @param type
// 	 * @return
// 	 */
// 	Class<?> getClassFromType(Type type);
// 
// 	/**
// 	 * Returns all input types created.
// 	 * @return
// 	 */
// 	Set<GraphQLType> getInputTypes();
// 
// 	/**
// 	 * Get the datafetcher factory
// 	 * @return
// 	 */
// 	IDataFetcherFactory getDataFetcherFactory() ;
// 
// 	/**
// 	 *
// 	 * @param dataFetcherFactory
// 	 */
// 	void setDataFetcherFactory(IDataFetcherFactory dataFetcherFactory);
// 
// 	/**
// 	 * Get the default datafetcher for methods
// 	 * @return
// 	 */
// 	Class<? extends IDataFetcher> getDefaultMethodDataFetcher();
// 
// 	/**
// 	 * Set the default data fetcher used for methods
// 	 * @param defaultMethodDataFetcher
// 	 */
// 	void setDefaultMethodDataFetcher(Class<? extends IDataFetcher> defaultMethodDataFetcher);
// 
// 	Collection<GraphQLFieldDefinition> getGraphQLFieldDefinitions(Optional<Object> targetObject, Type type, Class<?> classItem, Optional<List<Field>> fields, Optional<List<Method>> methods);
// }
// 
// Path: src/main/java/com/bretpatterson/schemagen/graphql/datafetchers/IMethodDataFetcher.java
// public interface IMethodDataFetcher extends IDataFetcher {
// 
// 	/**
// 	 * Called to let the data fetcher know about the Type factory registered for
// 	 * converting GraphQL deserialized data types to your Application method specific data types.
// 	 * {@link ITypeFactory}
// 	 * @param typeFactory
// 	 */
// 	void setTypeFactory(ITypeFactory typeFactory);
// 
// 	/**
// 	 * The field name that is used to invoke the query.{@link GraphQLQuery#name()}
// 	 *
// 	 * @param fieldName
// 	 */
// 	void setFieldName(String fieldName);
// 
// 	/**
// 	 * A reference to the method we will be invoking for this data fetcher.
// 	 * @param method
// 	 */
// 	void setMethod(Method method);
// 
// 	/**
// 	 * The target object the method will be invoked upon.
// 	 * @param targetObject
// 	 */
// 	void setTargetObject(Object targetObject);
// 
// 	/**
// 	 * Invokes the method on the target object with the specified arguments
// 	 * @param method the method to invoke
// 	 * @param targetObject the target object
// 	 * @param arguments the arguments to the method
// 	 * @return return value
// 	 */
// 	Object invokeMethod(DataFetchingEnvironment environment, Method method, Object targetObject, Object[] arguments);
// }


// Path: src/main/java/com/bretpatterson/schemagen/graphql/impl/DefaultDataFetcherFactory.java
import com.bretpatterson.schemagen.graphql.IDataFetcherFactory;
import com.bretpatterson.schemagen.graphql.IGraphQLObjectMapper;
import com.bretpatterson.schemagen.graphql.datafetchers.IMethodDataFetcher;
import com.google.common.base.Optional;
import com.google.common.base.Throwables;
import graphql.schema.DataFetcher;
import graphql.schema.PropertyDataFetcher;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.security.InvalidParameterException;

package com.bretpatterson.schemagen.graphql.impl;


/**
 * The Default DataFetcher Factory. This only supports custom datafetchers of type IMethodDataFetcher
 */
public class DefaultDataFetcherFactory implements IDataFetcherFactory {

	@Override
	public DataFetcher newFieldDataFetcher(final IGraphQLObjectMapper objectMapper, final Optional<Object> targetObject, final Field field, String fieldName, Class<? extends DataFetcher> dataFetcher) {
		if (dataFetcher != null) {
			try {
				return dataFetcher.newInstance();
			} catch (IllegalAccessException | InstantiationException ex) {
				throw Throwables.propagate(ex);
			}
		} else {
			return new PropertyDataFetcher(fieldName);
		}
	}

	@Override
	public DataFetcher newMethodDataFetcher(final IGraphQLObjectMapper graphQLObjectMapper,
			final Optional<Object> targetObject,
			final Method method,
			final String fieldName,
			final Class<? extends DataFetcher> dataFetcher) {
		DataFetcher dataFetcherObject;
		try {
			dataFetcherObject = dataFetcher.newInstance();
			if (!IMethodDataFetcher.class.isAssignableFrom(dataFetcher)) {