// Path: graphql-rest/src/main/java/org/objectstyle/graphql/rest/json/JacksonReaderWriter.java
// public class JacksonReaderWriter implements JsonReader, JsonWriter {
// 
//     private ObjectMapper sharedMapper;
//     private JsonFactory sharedFactory;
// 
//     public JacksonReaderWriter() {
// 
//         // fun Jackson API with circular dependencies ... so we create a mapper
//         // first, and grab implicitly created factory from it
//         this.sharedMapper = new ObjectMapper();
//         this.sharedFactory = sharedMapper.getFactory();
// 
//         // make sure mapper does not attempt closing streams it does not
//         // manage... why is this even a default in jackson?
//         sharedFactory.disable(Feature.AUTO_CLOSE_TARGET);
// 
//         // do not flush every time. why would we want to do that?
//         // this is having a HUGE impact on extrest serializers (5x speedup)
//         sharedMapper.disable(SerializationFeature.FLUSH_AFTER_WRITE_VALUE);
//     }
// 
//     private JsonNode parseJson(InputStream jsonStream) {
//         Objects.requireNonNull(jsonStream);
// 
//         try {
//             com.fasterxml.jackson.core.JsonParser parser = sharedFactory.createParser(jsonStream);
//             return new ObjectMapper().readTree(parser);
//         } catch (IOException e) {
//             throw new GraphQLRestException(Status.BAD_REQUEST, "Error parsing JSON", e);
//         }
//     }
// 
//     @Override
//     public <T> T read(Class<T> type, InputStream jsonStream) {
//         JsonNode jsonNode = parseJson(jsonStream);
//         try {
//             return new ObjectMapper().readValue(new TreeTraversingParser(jsonNode), type);
//         } catch (IOException e) {
//             throw new GraphQLRestException(Status.BAD_REQUEST, "Error mapping JSON to object", e);
//         }
//     }
// 
//     @Override
//     public void write(OutputStream out, JacksonWriterDelegate delegate) {
//         // TODO: UTF-8 is hardcoded...
//         try (JsonGenerator generator = sharedFactory.createGenerator(out, JsonEncoding.UTF8)) {
//             delegate.write(generator);
//         } catch (IOException e) {
//             throw new GraphQLRestException(Status.INTERNAL_SERVER_ERROR, "Error writing JSON", e);
//         }
//     }
// 
// }
// 
// Path: graphql-rest/src/main/java/org/objectstyle/graphql/rest/json/JsonReader.java
// public interface JsonReader {
// 
//     <T> T read(Class<T> type, InputStream jsonStream);
// }
// 
// Path: graphql-rest/src/main/java/org/objectstyle/graphql/rest/json/JsonWriter.java
// public interface JsonWriter {
// 
//     void write(OutputStream out, JacksonWriterDelegate delegate);
// }
// 
// Path: graphql-cayenne/src/main/java/org/objectstyle/graphql/cayenne/orm/DefaultSchemaTranslator.java
// public class DefaultSchemaTranslator implements SchemaTranslator {
// 
//     private ObjectContext selectContext;
// 
//     public DefaultSchemaTranslator(ObjectContext selectContext) {
//         this.selectContext = selectContext;
//     }
// 
//     @Override
//     public GraphQLSchema toGraphQL() {
//         return SchemaBuilder.builder(selectContext).mutationType(MutationType.builder(selectContext).build())
//                 .build();
//     }
// }
// 
// Path: graphql-cayenne/src/main/java/org/objectstyle/graphql/cayenne/orm/SchemaTranslator.java
// public interface SchemaTranslator {
// 
// 	GraphQLSchema toGraphQL();
// }


import com.google.inject.*;
import io.bootique.jersey.JerseyModule;
import io.bootique.ConfigModule;
import org.apache.cayenne.configuration.server.ServerRuntime;
import org.objectstyle.graphql.rest.json.JacksonReaderWriter;
import org.objectstyle.graphql.rest.json.JsonReader;
import org.objectstyle.graphql.rest.json.JsonWriter;
import org.objectstyle.graphql.cayenne.orm.DefaultSchemaTranslator;
import org.objectstyle.graphql.cayenne.orm.SchemaTranslator;
import graphql.GraphQL;
import graphql.schema.GraphQLSchema;
package org.objectstyle.graphql.bootique;





public class GraphQLModule extends ConfigModule {

	@Override
	public void configure(Binder binder) {

		binder.bind(JacksonReaderWriter.class).in(Singleton.class);
		binder.bind(JsonReader.class).to(JacksonReaderWriter.class);
		binder.bind(JsonWriter.class).to(JacksonReaderWriter.class);

        JerseyModule.contributeFeatures(binder).addBinding().toProvider(GraphQLFeatureProvider.class);
	}

	@Provides
	@Singleton
	GraphQL createGraphQL( SchemaTranslator translator) {
		GraphQLSchema schema = translator.toGraphQL();
        return new GraphQL(schema);
	}

	@Provides
	@Singleton
	SchemaTranslator createSchemaTranslator(ServerRuntime cayenneRuntime) {
// Path: graphql-rest/src/main/java/org/objectstyle/graphql/rest/json/JacksonReaderWriter.java
// public class JacksonReaderWriter implements JsonReader, JsonWriter {
// 
//     private ObjectMapper sharedMapper;
//     private JsonFactory sharedFactory;
// 
//     public JacksonReaderWriter() {
// 
//         // fun Jackson API with circular dependencies ... so we create a mapper
//         // first, and grab implicitly created factory from it
//         this.sharedMapper = new ObjectMapper();
//         this.sharedFactory = sharedMapper.getFactory();
// 
//         // make sure mapper does not attempt closing streams it does not
//         // manage... why is this even a default in jackson?
//         sharedFactory.disable(Feature.AUTO_CLOSE_TARGET);
// 
//         // do not flush every time. why would we want to do that?
//         // this is having a HUGE impact on extrest serializers (5x speedup)
//         sharedMapper.disable(SerializationFeature.FLUSH_AFTER_WRITE_VALUE);
//     }
// 
//     private JsonNode parseJson(InputStream jsonStream) {
//         Objects.requireNonNull(jsonStream);
// 
//         try {
//             com.fasterxml.jackson.core.JsonParser parser = sharedFactory.createParser(jsonStream);
//             return new ObjectMapper().readTree(parser);
//         } catch (IOException e) {
//             throw new GraphQLRestException(Status.BAD_REQUEST, "Error parsing JSON", e);
//         }
//     }
// 
//     @Override
//     public <T> T read(Class<T> type, InputStream jsonStream) {
//         JsonNode jsonNode = parseJson(jsonStream);
//         try {
//             return new ObjectMapper().readValue(new TreeTraversingParser(jsonNode), type);
//         } catch (IOException e) {
//             throw new GraphQLRestException(Status.BAD_REQUEST, "Error mapping JSON to object", e);
//         }
//     }
// 
//     @Override
//     public void write(OutputStream out, JacksonWriterDelegate delegate) {
//         // TODO: UTF-8 is hardcoded...
//         try (JsonGenerator generator = sharedFactory.createGenerator(out, JsonEncoding.UTF8)) {
//             delegate.write(generator);
//         } catch (IOException e) {
//             throw new GraphQLRestException(Status.INTERNAL_SERVER_ERROR, "Error writing JSON", e);
//         }
//     }
// 
// }
// 
// Path: graphql-rest/src/main/java/org/objectstyle/graphql/rest/json/JsonReader.java
// public interface JsonReader {
// 
//     <T> T read(Class<T> type, InputStream jsonStream);
// }
// 
// Path: graphql-rest/src/main/java/org/objectstyle/graphql/rest/json/JsonWriter.java
// public interface JsonWriter {
// 
//     void write(OutputStream out, JacksonWriterDelegate delegate);
// }
// 
// Path: graphql-cayenne/src/main/java/org/objectstyle/graphql/cayenne/orm/DefaultSchemaTranslator.java
// public class DefaultSchemaTranslator implements SchemaTranslator {
// 
//     private ObjectContext selectContext;
// 
//     public DefaultSchemaTranslator(ObjectContext selectContext) {
//         this.selectContext = selectContext;
//     }
// 
//     @Override
//     public GraphQLSchema toGraphQL() {
//         return SchemaBuilder.builder(selectContext).mutationType(MutationType.builder(selectContext).build())
//                 .build();
//     }
// }
// 
// Path: graphql-cayenne/src/main/java/org/objectstyle/graphql/cayenne/orm/SchemaTranslator.java
// public interface SchemaTranslator {
// 
// 	GraphQLSchema toGraphQL();
// }


// Path: graphql-bootique/src/main/java/org/objectstyle/graphql/bootique/GraphQLModule.java
import com.google.inject.*;
import io.bootique.jersey.JerseyModule;
import io.bootique.ConfigModule;
import org.apache.cayenne.configuration.server.ServerRuntime;
import org.objectstyle.graphql.rest.json.JacksonReaderWriter;
import org.objectstyle.graphql.rest.json.JsonReader;
import org.objectstyle.graphql.rest.json.JsonWriter;
import org.objectstyle.graphql.cayenne.orm.DefaultSchemaTranslator;
import org.objectstyle.graphql.cayenne.orm.SchemaTranslator;
import graphql.GraphQL;
import graphql.schema.GraphQLSchema;

package org.objectstyle.graphql.bootique;





public class GraphQLModule extends ConfigModule {

	@Override
	public void configure(Binder binder) {

		binder.bind(JacksonReaderWriter.class).in(Singleton.class);
		binder.bind(JsonReader.class).to(JacksonReaderWriter.class);
		binder.bind(JsonWriter.class).to(JacksonReaderWriter.class);

        JerseyModule.contributeFeatures(binder).addBinding().toProvider(GraphQLFeatureProvider.class);
	}

	@Provides
	@Singleton
	GraphQL createGraphQL( SchemaTranslator translator) {
		GraphQLSchema schema = translator.toGraphQL();
        return new GraphQL(schema);
	}

	@Provides
	@Singleton
	SchemaTranslator createSchemaTranslator(ServerRuntime cayenneRuntime) {
		return new DefaultSchemaTranslator(cayenneRuntime.newContext());