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.experiment.generators;
017
018import com.sun.codemodel.JBlock;
019import com.sun.codemodel.JClassAlreadyExistsException;
020import org.androidtransfuse.adapter.ASTMethod;
021import org.androidtransfuse.adapter.ASTParameter;
022import org.androidtransfuse.adapter.ASTType;
023import org.androidtransfuse.analysis.InjectionPointFactory;
024import org.androidtransfuse.annotations.Factory;
025import org.androidtransfuse.experiment.*;
026import org.androidtransfuse.gen.InjectionFragmentGenerator;
027import org.androidtransfuse.gen.InstantiationStrategyFactory;
028import org.androidtransfuse.gen.variableBuilder.InjectionBindingBuilder;
029import org.androidtransfuse.model.MethodDescriptor;
030import org.androidtransfuse.util.TransfuseRuntimeException;
031import org.androidtransfuse.validation.Validator;
032
033import javax.inject.Inject;
034
035/**
036 * @author John Ericksen
037 */
038public class OnCreateInjectionGenerator implements Generation {
039
040    private final ASTMethod method;
041    private final ASTType target;
042    private final InjectionFragmentGenerator injectionFragmentGenerator;
043    private final InstantiationStrategyFactory instantiationStrategyFactory;
044    private final InjectionBindingBuilder injectionBindingBuilder;
045    private final InjectionPointFactory injectionPointFactory;
046    private final Validator validator;
047
048    @Factory
049    public interface InjectionGeneratorFactory {
050        OnCreateInjectionGenerator build(ASTMethod method, ASTType target);
051    }
052
053    @Inject
054    public OnCreateInjectionGenerator(/*@Assisted*/ASTMethod method,
055                                      /*@Assisted*/ASTType target,
056                                      InjectionFragmentGenerator injectionFragmentGenerator,
057                                      InstantiationStrategyFactory instantiationStrategyFactory,
058                                      InjectionBindingBuilder injectionBindingBuilder,
059                                      InjectionPointFactory injectionPointFactory,
060                                      Validator validator) {
061        this.method = method;
062        this.injectionFragmentGenerator = injectionFragmentGenerator;
063        this.instantiationStrategyFactory = instantiationStrategyFactory;
064        this.target = target;
065        this.injectionBindingBuilder = injectionBindingBuilder;
066        this.injectionPointFactory = injectionPointFactory;
067        this.validator = validator;
068    }
069
070    @Override
071    public void schedule(final ComponentBuilder builder, final ComponentDescriptor descriptor) {
072
073        builder.add(method, GenerationPhase.INJECTION, new ComponentMethodGenerator() {
074            @Override
075            public void generate(MethodDescriptor methodDescriptor, JBlock block) {
076                for (ASTParameter astParameter : methodDescriptor.getASTMethod().getParameters()) {
077                    builder.getAnalysisContext().getInjectionNodeBuilders().putType(astParameter.getASTType(), injectionBindingBuilder.buildExpression(methodDescriptor.getParameter(astParameter)));
078                }
079
080                descriptor.setRootInjectionNode(injectionPointFactory.buildInjectionNode(target, builder.getAnalysisContext()));
081
082                if(!validator.isInError()) {
083
084                    try {
085                        injectionFragmentGenerator.buildFragment(
086                                block,
087                                instantiationStrategyFactory.buildMethodStrategy(block, builder.getScopes()),
088                                builder.getDefinedClass(),
089                                descriptor.getRootInjectionNode(),
090                                builder.getScopes(),
091                                builder.getExpressionMap());
092                    } catch (JClassAlreadyExistsException e) {
093                        throw new TransfuseRuntimeException("Class already exists", e);
094                    }
095                }
096            }
097        });
098    }
099}