Permalink
Browse files

Allow @when ate class level in modules

If a @when is defined for the whole module, all methods will inherit of the
specified condition.
Method will ne be allowed to use @when if the module define one at the class level.
  • Loading branch information...
a-peyrard committed Feb 8, 2015
1 parent 05bcab4 commit f1d5b05467fb9de9584ae813d1ec0f0a76cf87ad
@@ -6,6 +6,7 @@
import com.google.common.base.Function;
+import com.google.common.base.Optional;
import com.google.common.collect.Iterables;
import org.junit.AfterClass;
import org.junit.Before;
@@ -15,6 +16,7 @@
import java.util.Set;
import restx.factory.Factory;
import restx.factory.Name;
+import restx.factory.conditional.components.TestInterfaces;
import restx.factory.conditional.components.TestModuleWithConditional;
/**
@@ -86,4 +88,25 @@ public void should_provide_component_if_condition_is_verified_and_use_name_and_p
pioneer = factory.getComponent(Name.of(TestModuleWithConditional.Pioneer.class, "physics"));
assertThat(pioneer.name()).isEqualTo("Pierre Currie");
}
+
+ @Test
+ public void should_use_modules_condition_on_all_its_components() {
+ Factory factory = Factory.newInstance();
+ TestInterfaces.Resolver resolver = factory.getComponent(TestInterfaces.Resolver.class);
+ assertThat(resolver.resolve("foo")).isEqualTo("prod:foo");
+ Optional<TestInterfaces.Workspace> workspace = factory.queryByClass(TestInterfaces.Workspace.class).findOneAsComponent();
+ assertThat(workspace.isPresent()).isFalse();
+ String dbType = factory.getComponent(Name.of(String.class, "db.type"));
+ assertThat(dbType).isEqualTo("postgres");
+
+ overrideComponents().set("my-mode", "dev");
+
+ factory = Factory.newInstance();
+ resolver = factory.getComponent(TestInterfaces.Resolver.class);
+ assertThat(resolver.resolve("foo")).isEqualTo("dev:foo");
+ workspace = factory.queryByClass(TestInterfaces.Workspace.class).findOneAsComponent();
+ assertThat(workspace.isPresent()).isTrue();
+ dbType = factory.getComponent(Name.of(String.class, "db.type"));
+ assertThat(dbType).isEqualTo("derby");
+ }
}
@@ -0,0 +1,27 @@
+package restx.factory.conditional.components;
+
+import javax.inject.Named;
+import restx.factory.Module;
+import restx.factory.Provides;
+
+/**
+ * @author apeyrard
+ */
+@Module
+public class TestClassicModule {
+
+ @Provides
+ public TestInterfaces.Resolver prodResolver() {
+ return new TestInterfaces.Resolver() {
+ @Override
+ public String resolve(String constraint) {
+ return "prod:"+constraint;
+ }
+ };
+ }
+
+ @Provides @Named("db.type")
+ public String dbType() {
+ return "postgres";
+ }
+}
@@ -0,0 +1,43 @@
+package restx.factory.conditional.components;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+import javax.inject.Named;
+import restx.factory.Alternative;
+import restx.factory.Module;
+import restx.factory.Provides;
+import restx.factory.When;
+
+/**
+ * @author apeyrard
+ */
+@Module(priority = -100)
+@When(name = "my-mode", value = "dev")
+public class TestDevModule {
+
+ @Alternative(to = TestInterfaces.Resolver.class, named = "prodResolver")
+ public TestInterfaces.Resolver devResolver() {
+ return new TestInterfaces.Resolver() {
+ @Override
+ public String resolve(String constraint) {
+ return "dev:"+constraint;
+ }
+ };
+ }
+
+ @Provides
+ public TestInterfaces.Workspace workspace() {
+ return new TestInterfaces.Workspace() {
+ @Override
+ public List<String> modules() {
+ return ImmutableList.of("mod1", "mod2");
+ }
+ };
+ }
+
+ @Provides @Named("db.type")
+ public String dbType() {
+ return "derby";
+ }
+}
@@ -0,0 +1,17 @@
+package restx.factory.conditional.components;
+
+import java.util.List;
+
+/**
+ * @author apeyrard
+ */
+public class TestInterfaces {
+
+ public static interface Resolver {
+ String resolve(String constraint);
+ }
+
+ public static interface Workspace {
+ List<String> modules();
+ }
+}
@@ -81,6 +81,7 @@ private void processModules(RoundEnvironment roundEnv) throws IOException {
}
TypeElement typeElem = (TypeElement) annotation;
Module mod = typeElem.getAnnotation(Module.class);
+ When classWhen = typeElem.getAnnotation(When.class);
ModuleClass module = new ModuleClass(typeElem.getQualifiedName().toString(), typeElem, mod.priority());
for (Element element : typeElem.getEnclosedElements()) {
@@ -93,64 +94,79 @@ private void processModules(RoundEnvironment roundEnv) throws IOException {
&& element.getKind() == ElementKind.METHOD) {
ExecutableElement exec = (ExecutableElement) element;
- When when = exec.getAnnotation(When.class);
+ When methodWhen = exec.getAnnotation(When.class);
// multiple cases, provides only, provides with when, and alternative
- if (provides != null && when == null) {
+ if (provides != null && methodWhen == null && classWhen == null) {
// add a provider method to the module
processProviderMethod(mod, module, provides, exec);
- } else if (provides != null) {
- // we need to create a conditional provider method
- processConditionalProviderMethod(
- mod,
- module,
- exec.getReturnType().toString(),
- getInjectionName(exec.getAnnotation(Named.class)).or(exec.getSimpleName().toString()),
- provides.priority() == 0 ? mod.priority() : provides.priority(),
- when,
- "Conditional",
- exec
- );
- } else if (alternative != null) {
- // when annotation is required with alternative
- if (when == null) {
- error("an Alternative MUST be annotated with @When to tell when it must be activated", exec);
- continue;
- }
-
- TypeElement alternativeTo = null;
- try {
- alternative.to();
- } catch (MirroredTypeException mte) {
- alternativeTo = asTypeElement(mte.getTypeMirror());
- }
-
- String namedAttribute = alternative.named();
- Optional<String> injectionName = getInjectionName(alternativeTo.getAnnotation(Named.class));
- String componentName;
- if (!namedAttribute.isEmpty()) {
- // the conditional component name is the one specified in @Alternative annotation
- componentName = namedAttribute;
- } else if (injectionName.isPresent()) {
- // or the Name of the reference class
- componentName = injectionName.get();
+ } else {
+
+ // When can be either defined at class level, or on the method. But both are not allowed.
+ When whenToUse;
+ if (classWhen != null) {
+ if (methodWhen != null) {
+ error("the module class is annotated with @When, so methods are not allowed to be annotated with @When", exec);
+ continue;
+ }
+ whenToUse = classWhen;
} else {
- // or the simple name of the produced class
- componentName = alternativeTo.getSimpleName().toString();
+ whenToUse = methodWhen;
}
- // add a conditional provider method to the module
- processConditionalProviderMethod(
- mod,
- module,
- alternativeTo.getQualifiedName().toString(),
- componentName,
- alternative.priority(),
- when,
- "Alternative",
- exec
- );
+ if (provides != null) {
+ // we need to create a conditional provider method
+ processConditionalProviderMethod(
+ mod,
+ module,
+ exec.getReturnType().toString(),
+ getInjectionName(exec.getAnnotation(Named.class)).or(exec.getSimpleName().toString()),
+ provides.priority() == 0 ? mod.priority() : provides.priority(),
+ whenToUse,
+ "Conditional",
+ exec
+ );
+ } else if (alternative != null) {
+ // when annotation is required with alternative
+ if (whenToUse == null) {
+ error("an Alternative MUST be annotated with @When to tell when it must be activated, or the whole module must be annotated with @When", exec);
+ continue;
+ }
+
+ TypeElement alternativeTo = null;
+ try {
+ alternative.to();
+ } catch (MirroredTypeException mte) {
+ alternativeTo = asTypeElement(mte.getTypeMirror());
+ }
+
+ String namedAttribute = alternative.named();
+ Optional<String> injectionName = getInjectionName(alternativeTo.getAnnotation(Named.class));
+ String componentName;
+ if (!namedAttribute.isEmpty()) {
+ // the conditional component name is the one specified in @Alternative annotation
+ componentName = namedAttribute;
+ } else if (injectionName.isPresent()) {
+ // or the Name of the reference class
+ componentName = injectionName.get();
+ } else {
+ // or the simple name of the produced class
+ componentName = alternativeTo.getSimpleName().toString();
+ }
+
+ // add a conditional provider method to the module
+ processConditionalProviderMethod(
+ mod,
+ module,
+ alternativeTo.getQualifiedName().toString(),
+ componentName,
+ alternative.priority(),
+ whenToUse,
+ "Alternative",
+ exec
+ );
+ }
}
}
}

0 comments on commit f1d5b05

Please sign in to comment.