package com.mastfrog.settings;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Provider;
import com.google.inject.Stage;
import com.google.inject.TypeLiteral;
import com.google.inject.matcher.Matcher;
import com.google.inject.matcher.Matchers;
import com.google.inject.spi.TypeEncounter;
import com.google.inject.spi.TypeListener;
import com.mastfrog.guicy.annotations.Namespace;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import static org.junit.Assert.*;
import org.junit.Test;
/**
*
* @author tim
*/
public class XTest {
@Test
public void test() {
MM mm = new MM();
Injector inj = Guice.createInjector(mm);
IFace i = inj.getInstance(IFace.class);
assertNotNull(i);
}
public static class MM extends AbstractModule {
private final ThreadLocal<TypeLiteral<?>> loc = new ThreadLocal<>();
@Override
@SuppressWarnings("unchecked")
protected void configure() {
bind(IFace.class).to(Implementation.class);
bind(Settings.class).toProvider(new P());
Matcher<? super TypeLiteral<?>> m;
m = Matchers.only(TypeLiteral.get(IFace.class));
m = new Matcher() {
@Override
public boolean matches(Object t) {
System.out.println("MATCHES " + t + " type " + t.getClass());
if (t instanceof TypeLiteral) {
}
return true;
}
@Override
public Matcher and(Matcher other) {
return this;
}
@Override
public Matcher or(Matcher other) {
return this;
}
};
binder().bindListener(m, new TypeListener() {
@Override
public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) {
if (type.getRawType() == Stage.class) {
Thread.dumpStack();
return;
}
if (type.getRawType() == P.class) {
return;
}
System.out.println("HEAR " + type);
loc.set(type);
}
});
}
Namespace findNamespace(TypeLiteral<?> l) {
return findNamespace(l, new HashSet<TypeLiteral<?>>());
}
Namespace findNamespace(TypeLiteral<?> l, Set<TypeLiteral<?>> seen) {
Namespace ns = l.getRawType().getAnnotation(Namespace.class);
if (ns == null) {
Package pk = l.getRawType().getPackage();
ns = pk.getAnnotation(Namespace.class);
}
if (ns == null) {
Class<?> sup = l.getRawType().getSuperclass();
if (sup != Object.class) {
TypeLiteral supType = TypeLiteral.get(sup);
if (!seen.contains(supType)) {
ns = findNamespace(supType, seen);
}
}
if (ns == null) {
for (Class<?> iface : l.getRawType().getInterfaces()) {
TypeLiteral<?> tl = TypeLiteral.get(iface);
if (!seen.contains(tl)) {
ns = findNamespace(tl, seen);
}
if (ns != null) {
break;
}
}
}
}
return ns;
}
class P implements Provider<Settings> {
@Override
public Settings get() {
TypeLiteral<?> l = loc.get();
Namespace ns = null;
if (loc.get() != null) {
ns = findNamespace(loc.get());
}
System.out.println("TL IS " + l);
try {
String namespace = ns == null ? "default" : ns.value();
Settings s = new SettingsBuilder(namespace).add("bar", namespace.equals("foo") ? "true" : "false").build();
return s;
} catch (IOException ex) {
throw new Error(ex);
}
}
}
}
@Namespace("foo")
public interface IFace {
public Boolean getFoo();
}
@Namespace("foo")
public static class Implementation implements IFace {
private final Settings settings;
@Inject
public Implementation(Settings settings) {
System.out.println("INJECTED SETTINGS IS " + settings);
this.settings = settings;
}
@Override
public Boolean getFoo() {
return settings.getBoolean("bar");
}
}
}