// Path: injector/src/main/java/eu/mikroskeem/shuriken/injector/Injector.java
// public interface Injector {
//     /**
//      * Instantiates object via no-args constructor
//      *
//      * @param clazz Class to instatiate
//      * @param <T> Class type
//      * @return Instatiated class with injected fields
//      */
//     <T> T getInstance(Class<T> clazz);
// 
//     /**
//      * Injects existing fields annotated
//      * with {@link javax.inject.Inject}
//      *
//      * @param instance Instance to inject
//      * @param <T> Instance type
//      * @return Injected instance (for chaining)
//      */
//     <T> T injectMembers(T instance);
// }
// 
// Path: injector/src/main/java/eu/mikroskeem/shuriken/injector/ShurikenInjector.java
// public class ShurikenInjector implements Injector {
//     private final Binder binder;
//     private ShurikenInjector(Binder binder) {
//         this.binder = binder;
//     }
// 
//     /**
//      * Create injector out of {@link eu.mikroskeem.shuriken.injector.Binder.Builder} implementation. <br>
//      * You can either use Java 8 lambdas or implement interface directly
//      * <pre>
//      * ShurikenInjector.createInjector(binder -&gt; {
//      *      binder.bind(InterfaceA.class).to(ImplementationB.class);
//      * });
//      * </pre>
//      *
//      * @param builder {@link eu.mikroskeem.shuriken.injector.Binder.Builder} implementation
//      * @return {@link Injector} instance, in this case {@link ShurikenInjector}
//      */
//     public static Injector createInjector(Binder.Builder builder) {
//         Binder binder = new Binder();
//         Ensure.notNull(builder, "Builder shouldn't be null!").configure(binder);
//         return new ShurikenInjector(binder);
//     }
// 
//     /**
//      * {@inheritDoc}
//      */
//     @Override
//     public <T> T getInstance(Class<T> clazz) {
//         return injectMembers(Reflect.wrapClass(clazz).construct().getClassInstance());
//     }
// 
//     /**
//      * {@inheritDoc}
//      */
//     @Override
//     public <T> T injectMembers(T instance) {
//         Reflect.wrapInstance(instance).getFields().forEach(this::injectField);
//         return instance;
//     }
// 
//     /* Get binding for class */
//     @SuppressWarnings("unchecked")
//     private <T> Binder.Target<T> getTarget(Class<T> clazz) {
//         return (Binder.Target<T>)binder.getBindings().get(clazz);
//     }
// 
//     /* Inject field */
//     private <T> void injectField(FieldWrapper<T> field) {
//         if(field.getAnnotation(Inject.class).isPresent()) {
//             Binder.Target<T> target;
//             Ensure.ensureCondition(
//                     (target = getTarget(field.getType())) != null,
//                     "There are no registered bindings for class: " + field.getType()
//             );
//             field.write(target.getInstance());
//         }
//     }
// }
// 
// Path: injector/src/test/java/eu/mikroskeem/test/shuriken/injector/testclasses/InterfacesTestClass.java
// public class InterfacesTestClass {
//     public interface a {}
//     public interface b {}
// 
//     public static class A implements a {
//         @Override
//         public String toString() {
//             return "a implementer A";
//         }
//     }
//     public static class B implements a {
//         @Override
//         public String toString() {
//             return "a implementer B";
//         }
//     }
//     public static class C implements b {
//         @Override
//         public String toString() {
//             return "b implementer C";
//         }
//     }
//     public static class D implements b {
//         @Override
//         public String toString() {
//             return "b implementer D";
//         }
//     }
// }
// 
// Path: injector/src/test/java/eu/mikroskeem/test/shuriken/injector/testclasses/TestClassOne.java
// public class TestClassOne {
//     @Inject @Named("name one") private Object a;
//     @Inject @Named("name two") private String b;
// 
//     public Object getA() {
//         return a;
//     }
// 
//     public String getB() {
//         return b;
//     }
// }
// 
// Path: injector/src/test/java/eu/mikroskeem/test/shuriken/injector/testclasses/TestClassTwo.java
// public class TestClassTwo {
//     @Inject private InterfacesTestClass.a a;
//     @Inject private InterfacesTestClass.b b;
// 
//     public InterfacesTestClass.a getA() {
//         return a;
//     }
// 
//     public InterfacesTestClass.b getB() {
//         return b;
//     }
// }


import eu.mikroskeem.shuriken.injector.Injector;
import eu.mikroskeem.shuriken.injector.ShurikenInjector;
import eu.mikroskeem.test.shuriken.injector.testclasses.InterfacesTestClass;
import eu.mikroskeem.test.shuriken.injector.testclasses.TestClassOne;
import eu.mikroskeem.test.shuriken.injector.testclasses.TestClassTwo;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
package eu.mikroskeem.test.shuriken.injector;



/**
 * @author Mark Vainomaa
 */
public class InjectorTester {
    @Test
    public void testBindingInjecting() throws Exception {
        Injector injector = ShurikenInjector.createInjector(binder -> {
           binder.bind(InterfacesTestClass.a.class).to(InterfacesTestClass.A.class);
           binder.bind(InterfacesTestClass.b.class).to(InterfacesTestClass.C.class);
        });

// Path: injector/src/main/java/eu/mikroskeem/shuriken/injector/Injector.java
// public interface Injector {
//     /**
//      * Instantiates object via no-args constructor
//      *
//      * @param clazz Class to instatiate
//      * @param <T> Class type
//      * @return Instatiated class with injected fields
//      */
//     <T> T getInstance(Class<T> clazz);
// 
//     /**
//      * Injects existing fields annotated
//      * with {@link javax.inject.Inject}
//      *
//      * @param instance Instance to inject
//      * @param <T> Instance type
//      * @return Injected instance (for chaining)
//      */
//     <T> T injectMembers(T instance);
// }
// 
// Path: injector/src/main/java/eu/mikroskeem/shuriken/injector/ShurikenInjector.java
// public class ShurikenInjector implements Injector {
//     private final Binder binder;
//     private ShurikenInjector(Binder binder) {
//         this.binder = binder;
//     }
// 
//     /**
//      * Create injector out of {@link eu.mikroskeem.shuriken.injector.Binder.Builder} implementation. <br>
//      * You can either use Java 8 lambdas or implement interface directly
//      * <pre>
//      * ShurikenInjector.createInjector(binder -&gt; {
//      *      binder.bind(InterfaceA.class).to(ImplementationB.class);
//      * });
//      * </pre>
//      *
//      * @param builder {@link eu.mikroskeem.shuriken.injector.Binder.Builder} implementation
//      * @return {@link Injector} instance, in this case {@link ShurikenInjector}
//      */
//     public static Injector createInjector(Binder.Builder builder) {
//         Binder binder = new Binder();
//         Ensure.notNull(builder, "Builder shouldn't be null!").configure(binder);
//         return new ShurikenInjector(binder);
//     }
// 
//     /**
//      * {@inheritDoc}
//      */
//     @Override
//     public <T> T getInstance(Class<T> clazz) {
//         return injectMembers(Reflect.wrapClass(clazz).construct().getClassInstance());
//     }
// 
//     /**
//      * {@inheritDoc}
//      */
//     @Override
//     public <T> T injectMembers(T instance) {
//         Reflect.wrapInstance(instance).getFields().forEach(this::injectField);
//         return instance;
//     }
// 
//     /* Get binding for class */
//     @SuppressWarnings("unchecked")
//     private <T> Binder.Target<T> getTarget(Class<T> clazz) {
//         return (Binder.Target<T>)binder.getBindings().get(clazz);
//     }
// 
//     /* Inject field */
//     private <T> void injectField(FieldWrapper<T> field) {
//         if(field.getAnnotation(Inject.class).isPresent()) {
//             Binder.Target<T> target;
//             Ensure.ensureCondition(
//                     (target = getTarget(field.getType())) != null,
//                     "There are no registered bindings for class: " + field.getType()
//             );
//             field.write(target.getInstance());
//         }
//     }
// }
// 
// Path: injector/src/test/java/eu/mikroskeem/test/shuriken/injector/testclasses/InterfacesTestClass.java
// public class InterfacesTestClass {
//     public interface a {}
//     public interface b {}
// 
//     public static class A implements a {
//         @Override
//         public String toString() {
//             return "a implementer A";
//         }
//     }
//     public static class B implements a {
//         @Override
//         public String toString() {
//             return "a implementer B";
//         }
//     }
//     public static class C implements b {
//         @Override
//         public String toString() {
//             return "b implementer C";
//         }
//     }
//     public static class D implements b {
//         @Override
//         public String toString() {
//             return "b implementer D";
//         }
//     }
// }
// 
// Path: injector/src/test/java/eu/mikroskeem/test/shuriken/injector/testclasses/TestClassOne.java
// public class TestClassOne {
//     @Inject @Named("name one") private Object a;
//     @Inject @Named("name two") private String b;
// 
//     public Object getA() {
//         return a;
//     }
// 
//     public String getB() {
//         return b;
//     }
// }
// 
// Path: injector/src/test/java/eu/mikroskeem/test/shuriken/injector/testclasses/TestClassTwo.java
// public class TestClassTwo {
//     @Inject private InterfacesTestClass.a a;
//     @Inject private InterfacesTestClass.b b;
// 
//     public InterfacesTestClass.a getA() {
//         return a;
//     }
// 
//     public InterfacesTestClass.b getB() {
//         return b;
//     }
// }


// Path: injector/src/test/java/eu/mikroskeem/test/shuriken/injector/InjectorTester.java
import eu.mikroskeem.shuriken.injector.Injector;
import eu.mikroskeem.shuriken.injector.ShurikenInjector;
import eu.mikroskeem.test.shuriken.injector.testclasses.InterfacesTestClass;
import eu.mikroskeem.test.shuriken.injector.testclasses.TestClassOne;
import eu.mikroskeem.test.shuriken.injector.testclasses.TestClassTwo;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

package eu.mikroskeem.test.shuriken.injector;



/**
 * @author Mark Vainomaa
 */
public class InjectorTester {
    @Test
    public void testBindingInjecting() throws Exception {
        Injector injector = ShurikenInjector.createInjector(binder -> {
           binder.bind(InterfacesTestClass.a.class).to(InterfacesTestClass.A.class);
           binder.bind(InterfacesTestClass.b.class).to(InterfacesTestClass.C.class);
        });

        TestClassTwo t1 = injector.getInstance(TestClassTwo.class);