/**
* Copyright 2011-2015 John Ericksen
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.androidtransfuse.analysis;
import org.androidtransfuse.adapter.ASTType;
import org.androidtransfuse.adapter.classes.ASTClassFactory;
import org.androidtransfuse.analysis.astAnalyzer.ASTInjectionAspect;
import org.androidtransfuse.analysis.astAnalyzer.VirtualProxyAspect;
import org.androidtransfuse.bootstrap.Bootstrap;
import org.androidtransfuse.bootstrap.Bootstraps;
import org.androidtransfuse.gen.variableBuilder.VariableBuilder;
import org.androidtransfuse.gen.variableBuilder.VariableInjectionBuilder;
import org.androidtransfuse.gen.variableBuilder.VariableInjectionBuilderFactory;
import org.androidtransfuse.model.ConstructorInjectionPoint;
import org.androidtransfuse.model.FieldInjectionPoint;
import org.androidtransfuse.model.InjectionNode;
import org.androidtransfuse.model.MethodInjectionPoint;
import org.junit.Before;
import org.junit.Test;
import javax.inject.Inject;
import javax.inject.Provider;
import static org.junit.Assert.*;
/**
* @author John Ericksen
*/
@Bootstrap
public class AnalyzerTest {
//A -> E -> F
// |
// `-> B -> C -> D
// |
// `-> F
public interface B {
}
public static class A {
private B b;
private E e;
@Inject
public void setMultiVariables(B b, E e) {
this.b = b;
this.e = e;
}
}
public static class BImpl implements B {
@Inject
private C c;
private F f;
@Inject
public BImpl(F f) {
this.f = f;
}
}
public static class C {
@Inject
private D d;
}
public static class D {
//back link
private B b;
@Inject
public D(B b) {
this.b = b;
}
}
public static class E {
private F f;
@Inject
public E(F f) {
this.f = f;
}
}
public static class F {
//empty
}
@Inject
private Analyzer analyzer;
@Inject
private Provider<VariableInjectionBuilder> variableInjectionBuilderProvider;
@Inject
private ASTClassFactory astClassFactory;
@Inject
private SimpleAnalysisContextFactory analysisContextFactory;
private AnalysisContext analysisContext;
@Inject
private VariableInjectionBuilderFactory variableInjectionBuilderFactory;
@Before
public void setup() {
Bootstraps.inject(this);
analysisContext = analysisContextFactory.buildContext();
analysisContext.getInjectionNodeBuilders().putType(B.class,
variableInjectionBuilderFactory.buildVariableInjectionNodeBuilder(astClassFactory.getType(BImpl.class)));
}
@Test
public void testBackLinkAnalysis() {
ASTType astType = astClassFactory.getType(A.class);
InjectionNode injectionNode = analyzer.analyze(astType, astType, analysisContext);
injectionNode.addAspect(VariableBuilder.class, variableInjectionBuilderProvider.get());
//A -> B && A -> E
assertEquals(1, countMethodInjectionPoints(injectionNode.getAspect(ASTInjectionAspect.class)));
MethodInjectionPoint bInjectionPoint = injectionNode.getAspect(ASTInjectionAspect.class).getCurrentGroup().getMethodInjectionPoints().iterator().next();
assertEquals(2, bInjectionPoint.getInjectionNodes().size());
//A -> B
InjectionNode bInjectionNode = bInjectionPoint.getInjectionNodes().get(0);
assertTrue(isProxyRequired(bInjectionNode));
assertEquals(BImpl.class.getCanonicalName(), bInjectionNode.getClassName());
//A -> E
InjectionNode eInjectionNode = bInjectionPoint.getInjectionNodes().get(1);
assertFalse(isProxyRequired(eInjectionNode));
assertEquals(E.class.getCanonicalName(), eInjectionNode.getClassName());
//B -> C
assertEquals(1, countFieldInjectionPoints(bInjectionNode.getAspect(ASTInjectionAspect.class)));
FieldInjectionPoint cInjectionPoint = bInjectionNode.getAspect(ASTInjectionAspect.class).getCurrentGroup().getFieldInjectionPoints().iterator().next();
InjectionNode cInjectionNode = cInjectionPoint.getInjectionNode();
assertFalse(isProxyRequired(cInjectionNode));
assertEquals(C.class.getCanonicalName(), cInjectionNode.getClassName());
//B -> F
ConstructorInjectionPoint fNonBackLinkInjectionPoint = bInjectionNode.getAspect(ASTInjectionAspect.class).getConstructorInjectionPoint();
assertEquals(1, fNonBackLinkInjectionPoint.getInjectionNodes().size());
InjectionNode fInjectionNode = fNonBackLinkInjectionPoint.getInjectionNodes().get(0);
assertFalse(isProxyRequired(fInjectionNode));
assertEquals(F.class.getCanonicalName(), fInjectionNode.getClassName());
//E -> F
ConstructorInjectionPoint fNonBackLinkInjectionPoint2 = eInjectionNode.getAspect(ASTInjectionAspect.class).getConstructorInjectionPoint();
assertEquals(1, fNonBackLinkInjectionPoint2.getInjectionNodes().size());
InjectionNode fInjectionNode2 = fNonBackLinkInjectionPoint2.getInjectionNodes().get(0);
assertFalse(isProxyRequired(fInjectionNode2));
//C -> D
assertEquals(1, countFieldInjectionPoints(cInjectionNode.getAspect(ASTInjectionAspect.class)));
FieldInjectionPoint dInjectionPoint = cInjectionNode.getAspect(ASTInjectionAspect.class).getCurrentGroup().getFieldInjectionPoints().iterator().next();
InjectionNode dInjectionNode = dInjectionPoint.getInjectionNode();
assertFalse(isProxyRequired(dInjectionNode));
assertEquals(D.class.getCanonicalName(), dInjectionNode.getClassName());
//D -> B back link
ConstructorInjectionPoint bBackLinkInjectionPoint = dInjectionNode.getAspect(ASTInjectionAspect.class).getConstructorInjectionPoint();
assertEquals(1, bBackLinkInjectionPoint.getInjectionNodes().size());
InjectionNode bBackLinkInjectionNode = bBackLinkInjectionPoint.getInjectionNodes().get(0);
assertEquals(BImpl.class.getCanonicalName(), bBackLinkInjectionNode.getClassName());
assertTrue(isProxyRequired(bBackLinkInjectionNode));
//B -> F and E -> F difference
assertNotSame(fInjectionNode, fInjectionNode2);
assertFalse(fInjectionNode.equals(fInjectionNode2));
}
private int countFieldInjectionPoints(ASTInjectionAspect aspect) {
int count = 0;
for (ASTInjectionAspect.InjectionGroup injectionGroup : aspect.getGroups()) {
count += injectionGroup.getFieldInjectionPoints().size();
}
return count;
}
private int countMethodInjectionPoints(ASTInjectionAspect aspect) {
int count = 0;
for (ASTInjectionAspect.InjectionGroup injectionGroup : aspect.getGroups()) {
count += injectionGroup.getMethodInjectionPoints().size();
}
return count;
}
private boolean isProxyRequired(InjectionNode injectionNode) {
VirtualProxyAspect proxyAspect = injectionNode.getAspect(VirtualProxyAspect.class);
return proxyAspect != null && proxyAspect.isProxyRequired();
}
}