001/**
002 * Copyright 2013 John Ericksen
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *    http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.androidtransfuse.gen.variableBuilder;
017
018import com.sun.codemodel.*;
019import org.androidtransfuse.TransfuseAnalysisException;
020import org.androidtransfuse.adapter.ASTJDefinedClassType;
021import org.androidtransfuse.analysis.astAnalyzer.ASTInjectionAspect;
022import org.androidtransfuse.gen.*;
023import org.androidtransfuse.gen.variableDecorator.TypedExpressionFactory;
024import org.androidtransfuse.model.FieldInjectionPoint;
025import org.androidtransfuse.model.InjectionNode;
026import org.androidtransfuse.model.MethodInjectionPoint;
027import org.androidtransfuse.model.TypedExpression;
028import org.androidtransfuse.model.r.RResource;
029import org.androidtransfuse.model.r.RResourceReferenceBuilder;
030import org.androidtransfuse.model.r.ResourceIdentifier;
031import org.androidtransfuse.util.AndroidLiterals;
032
033import javax.inject.Inject;
034
035public class FragmentViewVariableBuilder extends ConsistentTypeVariableBuilder {
036
037    private static final String FIND_VIEW_BY_ID = "findViewById";
038    private static final String FIND_VIEW_BY_TAG = "findViewWithTag";
039
040    private final JType viewType;
041    private final Integer viewId;
042    private final String viewTag;
043    private final InjectionNode viewInjectionNode;
044    private final InjectionExpressionBuilder injectionExpressionBuilder;
045    private final RResourceReferenceBuilder rResourceReferenceBuilder;
046    private final ClassGenerationUtil generationUtil;
047    private final UniqueVariableNamer variableNamer;
048    private final InvocationBuilder injectionInvocationBuilder;
049    private final RResource rResource;
050    private final ExpressionMatchingListFactory generatorFactory;
051
052    @Inject
053    public FragmentViewVariableBuilder(/*@Assisted*/ /*@Nullable*/ Integer viewId,
054                                       /*@Assisted*/ /*@Nullable*/ String viewTag,
055                                       /*@Assisted*/ InjectionNode viewInjectionNode,
056                                       /*@Assisted*/ JType viewType,
057                                       InjectionExpressionBuilder injectionExpressionBuilder,
058                                       RResourceReferenceBuilder rResourceReferenceBuilder,
059                                       ClassGenerationUtil generationUtil,
060                                       InvocationBuilder injectionInvocationBuilder,
061                                       UniqueVariableNamer variableNamer,
062                                       RResource rResource,
063                                       TypedExpressionFactory typedExpressionFactory,
064                                       ExpressionMatchingListFactory generatorFactory) {
065        super(AndroidLiterals.VIEW, typedExpressionFactory);
066        this.viewId = viewId;
067        this.viewTag = viewTag;
068        this.viewInjectionNode = viewInjectionNode;
069        this.viewType = viewType;
070        this.injectionExpressionBuilder = injectionExpressionBuilder;
071        this.rResourceReferenceBuilder = rResourceReferenceBuilder;
072        this.generationUtil = generationUtil;
073        this.injectionInvocationBuilder = injectionInvocationBuilder;
074        this.variableNamer = variableNamer;
075        this.rResource = rResource;
076        this.generatorFactory = generatorFactory;
077    }
078
079    @Override
080    public JExpression buildExpression(InjectionBuilderContext injectionBuilderContext, InjectionNode injectionNode) {
081        try {
082            injectionExpressionBuilder.setupInjectionRequirements(injectionBuilderContext, injectionNode);
083
084            TypedExpression contextVar = injectionExpressionBuilder.buildVariable(injectionBuilderContext, viewInjectionNode);
085
086            JExpression viewExpression;
087            if (viewId != null) {
088                ResourceIdentifier viewResourceIdentifier = rResource.getResourceIdentifier(viewId);
089                JExpression viewIdRef = rResourceReferenceBuilder.buildReference(viewResourceIdentifier);
090                viewExpression = contextVar.getExpression().invoke(FIND_VIEW_BY_ID).arg(viewIdRef);
091            } else {
092                //viewTag is not null
093                //<Fragment>.getView().findViewWithTag(...)
094                viewExpression = contextVar.getExpression().invoke(FIND_VIEW_BY_TAG).arg(JExpr.lit(viewTag));
095            }
096
097            if (injectionNode.containsAspect(ASTInjectionAspect.class)) {
098                return inject(injectionNode.getAspect(ASTInjectionAspect.class), injectionBuilderContext, injectionNode, viewExpression);
099            } else {
100                return viewExpression;
101            }
102        } catch (JClassAlreadyExistsException e) {
103            throw new TransfuseAnalysisException("JClassAlreadyExistsException while generating injection: " + injectionNode.getClassName(), e);
104        }
105    }
106
107    public JVar inject(ASTInjectionAspect injectionAspect, InjectionBuilderContext injectionBuilderContext, InjectionNode injectionNode, JExpression viewExpression) throws JClassAlreadyExistsException {
108        JVar variableRef;
109        JType nodeType = generationUtil.type(injectionNode.getASTType());
110
111        if (injectionAspect.getAssignmentType().equals(ASTInjectionAspect.InjectionAssignmentType.LOCAL)) {
112            variableRef = injectionBuilderContext.getBlock().decl(nodeType, variableNamer.generateName(injectionNode));
113        } else {
114            variableRef = injectionBuilderContext.getDefinedClass().field(JMod.PRIVATE, nodeType, variableNamer.generateName(injectionNode));
115        }
116        JBlock block = injectionBuilderContext.getBlock();
117
118
119        block.assign(variableRef, JExpr.cast(viewType, viewExpression));
120
121        for (ASTInjectionAspect.InjectionGroup injectionGroup : injectionAspect.getGroups()) {
122            //field injection
123            for (FieldInjectionPoint fieldInjectionPoint : injectionGroup.getFieldInjectionPoints()) {
124                block.add(
125                        injectionInvocationBuilder.buildFieldSet(
126                                new ASTJDefinedClassType(injectionBuilderContext.getDefinedClass()),
127                                injectionBuilderContext.getVariableMap().get(fieldInjectionPoint.getInjectionNode()),
128                                fieldInjectionPoint,
129                                variableRef));
130            }
131
132            //method injection
133            for (MethodInjectionPoint methodInjectionPoint : injectionGroup.getMethodInjectionPoints()) {
134                block.add(
135                        injectionInvocationBuilder.buildMethodCall(
136                                new ASTJDefinedClassType(injectionBuilderContext.getDefinedClass()),
137                                methodInjectionPoint.getRootContainingType(),
138                                methodInjectionPoint.getMethod(),
139                                generatorFactory.build(injectionBuilderContext.getVariableMap(), methodInjectionPoint.getInjectionNodes()),
140                                new TypedExpression(methodInjectionPoint.getContainingType(), variableRef)));
141            }
142        }
143
144        return variableRef;
145    }
146}