// Path: src/main/java/com/lowereast/guiceymongo/GuiceyMongoEvalException.java
// @SuppressWarnings("serial")
// public class GuiceyMongoEvalException extends MongoException {
// 	private static String _errorPrefix = "eval failed: { \"errno\" : -3.0 , \"errmsg\" : \"invoke failed: JS Error: ";
// 	
// 	private String _type;
// 	
// 	private GuiceyMongoEvalException(String exceptionType, String exceptionMessage) {
// 		super(exceptionMessage);
// 		_type = exceptionType;
// 	}
// 	
// 	public String getType() {
// 		return _type;
// 	}
// 	
// 	/**
// 	 * Will create a MongoEvalException if the exception passed in was created from an eval command.  Otherwise the exception passed in will be returned.
// 	 * @param e
// 	 * @return MongoEvalException if applicable, otherwise the exception passed in
// 	 */
// 	public static MongoException create(MongoException e) {
// 		String errorString = e.getMessage();
// 		if (errorString.startsWith(_errorPrefix)) {
// 			int length = _errorPrefix.length();
// 			int colonLocation = errorString.indexOf(':', length);
// 			String type = errorString.substring(length, colonLocation).trim();
// 			String message = errorString.substring(colonLocation + 1, errorString.indexOf('"', colonLocation)).trim();
// 			return new GuiceyMongoEvalException(type, message);
// 		}
// 		return e;
// 	}
// }
// 
// Path: src/main/java/com/lowereast/guiceymongo/data/DataWrapper.java
// public interface DataWrapper<T extends IsData> {
// 	T wrap(DBObject backing);
// }
// 
// Path: src/main/java/com/lowereast/guiceymongo/data/IsData.java
// public interface IsData {
// }
// 
// Path: src/main/java/com/lowereast/guiceymongo/data/IsWrapper.java
// public interface IsWrapper<T extends IsData> {
// 	DBObject getDBObject();
// }
// 
// Path: src/main/java/com/lowereast/guiceymongo/guice/GuiceyMongo.java
// public final class GuiceyMongo {
// 	private GuiceyMongo() {}
// 
// 	public static Builders.Configuration configure(String configurationName) {
// 		return new BuilderImpls.Configuration(configurationName);
// 	}
// 	
// 	public static Builders.Connection configureConnection(String connectionName) {
// 		return new BuilderImpls.Connection(connectionName);
// 	}
// 	
// 	public static Module chooseConfiguration(final String configurationName) {
// 		return new Module() {
// 			public void configure(Binder binder) {
// 				GuiceyMongoUtil.setCurrentConfiguration(binder.skipSources(GuiceyMongo.class), configurationName);
// 			}
// 		};
// 	}
// 	
// 	@SuppressWarnings("unchecked")
// 	public static Module javascriptProxy(Class<?> proxyInterface, String databaseKey) {
// 		return new JavascriptProxy(proxyInterface, databaseKey);
// 	}
// }


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.util.List;
import java.util.Map;
import com.google.inject.Binder;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.Provider;
import com.google.inject.internal.Lists;
import com.google.inject.internal.Maps;
import com.lowereast.guiceymongo.GuiceyMongoEvalException;
import com.lowereast.guiceymongo.annotation.ItemType;
import com.lowereast.guiceymongo.data.DataWrapper;
import com.lowereast.guiceymongo.data.IsData;
import com.lowereast.guiceymongo.data.IsWrapper;
import com.lowereast.guiceymongo.guice.GuiceyMongo;
import com.mongodb.DB;
import com.mongodb.DBObject;
import com.mongodb.MongoException;
	
	private static class VoidInvocation implements Invocation {
		private final String _code;
		public VoidInvocation(String methodName, Class<?>[] argumentTypes) {
			String argumentString = createArgumentString(argumentTypes.length);
			_code = "function" + argumentString + "{" + methodName + argumentString + "}";
		}
		public Object invoke(DB database, Object[] args) {
			return database.eval(_code, args);
		}
	}
	
	private interface Converter<From, To> {
		To convert(From value);
	}
	private static final Converter<Double, Integer> DoubleToIntConverter = new Converter<Double, Integer>() {
		public Integer convert(Double value) {
			return value.intValue();
		}
	};
	private static final Converter<Object, Object> NoOpConverter = new Converter<Object, Object>() {
		public Object convert(Object value) {
			return value;
		}
	};
	
	private static class DBObjectToWrapperConverter<T extends IsData> implements Converter<DBObject, T> {
		private final DataWrapper<T> _wrapper;
		public DBObjectToWrapperConverter(Class<T> dataClass) {
			try {
// Path: src/main/java/com/lowereast/guiceymongo/GuiceyMongoEvalException.java
// @SuppressWarnings("serial")
// public class GuiceyMongoEvalException extends MongoException {
// 	private static String _errorPrefix = "eval failed: { \"errno\" : -3.0 , \"errmsg\" : \"invoke failed: JS Error: ";
// 	
// 	private String _type;
// 	
// 	private GuiceyMongoEvalException(String exceptionType, String exceptionMessage) {
// 		super(exceptionMessage);
// 		_type = exceptionType;
// 	}
// 	
// 	public String getType() {
// 		return _type;
// 	}
// 	
// 	/**
// 	 * Will create a MongoEvalException if the exception passed in was created from an eval command.  Otherwise the exception passed in will be returned.
// 	 * @param e
// 	 * @return MongoEvalException if applicable, otherwise the exception passed in
// 	 */
// 	public static MongoException create(MongoException e) {
// 		String errorString = e.getMessage();
// 		if (errorString.startsWith(_errorPrefix)) {
// 			int length = _errorPrefix.length();
// 			int colonLocation = errorString.indexOf(':', length);
// 			String type = errorString.substring(length, colonLocation).trim();
// 			String message = errorString.substring(colonLocation + 1, errorString.indexOf('"', colonLocation)).trim();
// 			return new GuiceyMongoEvalException(type, message);
// 		}
// 		return e;
// 	}
// }
// 
// Path: src/main/java/com/lowereast/guiceymongo/data/DataWrapper.java
// public interface DataWrapper<T extends IsData> {
// 	T wrap(DBObject backing);
// }
// 
// Path: src/main/java/com/lowereast/guiceymongo/data/IsData.java
// public interface IsData {
// }
// 
// Path: src/main/java/com/lowereast/guiceymongo/data/IsWrapper.java
// public interface IsWrapper<T extends IsData> {
// 	DBObject getDBObject();
// }
// 
// Path: src/main/java/com/lowereast/guiceymongo/guice/GuiceyMongo.java
// public final class GuiceyMongo {
// 	private GuiceyMongo() {}
// 
// 	public static Builders.Configuration configure(String configurationName) {
// 		return new BuilderImpls.Configuration(configurationName);
// 	}
// 	
// 	public static Builders.Connection configureConnection(String connectionName) {
// 		return new BuilderImpls.Connection(connectionName);
// 	}
// 	
// 	public static Module chooseConfiguration(final String configurationName) {
// 		return new Module() {
// 			public void configure(Binder binder) {
// 				GuiceyMongoUtil.setCurrentConfiguration(binder.skipSources(GuiceyMongo.class), configurationName);
// 			}
// 		};
// 	}
// 	
// 	@SuppressWarnings("unchecked")
// 	public static Module javascriptProxy(Class<?> proxyInterface, String databaseKey) {
// 		return new JavascriptProxy(proxyInterface, databaseKey);
// 	}
// }


// Path: src/main/java/com/lowereast/guiceymongo/guice/spi/JavascriptProxy.java
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.util.List;
import java.util.Map;
import com.google.inject.Binder;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.Provider;
import com.google.inject.internal.Lists;
import com.google.inject.internal.Maps;
import com.lowereast.guiceymongo.GuiceyMongoEvalException;
import com.lowereast.guiceymongo.annotation.ItemType;
import com.lowereast.guiceymongo.data.DataWrapper;
import com.lowereast.guiceymongo.data.IsData;
import com.lowereast.guiceymongo.data.IsWrapper;
import com.lowereast.guiceymongo.guice.GuiceyMongo;
import com.mongodb.DB;
import com.mongodb.DBObject;
import com.mongodb.MongoException;

	
	private static class VoidInvocation implements Invocation {
		private final String _code;
		public VoidInvocation(String methodName, Class<?>[] argumentTypes) {
			String argumentString = createArgumentString(argumentTypes.length);
			_code = "function" + argumentString + "{" + methodName + argumentString + "}";
		}
		public Object invoke(DB database, Object[] args) {
			return database.eval(_code, args);
		}
	}
	
	private interface Converter<From, To> {
		To convert(From value);
	}
	private static final Converter<Double, Integer> DoubleToIntConverter = new Converter<Double, Integer>() {
		public Integer convert(Double value) {
			return value.intValue();
		}
	};
	private static final Converter<Object, Object> NoOpConverter = new Converter<Object, Object>() {
		public Object convert(Object value) {
			return value;
		}
	};
	
	private static class DBObjectToWrapperConverter<T extends IsData> implements Converter<DBObject, T> {
		private final DataWrapper<T> _wrapper;
		public DBObjectToWrapperConverter(Class<T> dataClass) {
			try {
				_wrapper = (DataWrapper<T>)dataClass.getField("DataWrapper").get(null);