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.analysis; 017 018import org.androidtransfuse.adapter.ASTMethod; 019import org.androidtransfuse.adapter.ASTType; 020import org.androidtransfuse.adapter.PackageClass; 021import org.androidtransfuse.adapter.element.ASTElementFactory; 022import org.androidtransfuse.adapter.element.ASTTypeBuilderVisitor; 023import org.androidtransfuse.analysis.repository.InjectionNodeBuilderRepository; 024import org.androidtransfuse.analysis.repository.InjectionNodeBuilderRepositoryFactory; 025import org.androidtransfuse.annotations.Application; 026import org.androidtransfuse.experiment.ComponentDescriptor; 027import org.androidtransfuse.experiment.ScopesGeneration; 028import org.androidtransfuse.experiment.generators.ApplicationManifestEntryGenerator; 029import org.androidtransfuse.experiment.generators.ApplicationScopeSeedGenerator; 030import org.androidtransfuse.experiment.generators.ObservesExpressionGenerator; 031import org.androidtransfuse.experiment.generators.OnCreateInjectionGenerator; 032import org.androidtransfuse.gen.variableBuilder.ProviderInjectionNodeBuilderFactory; 033import org.androidtransfuse.model.InjectionSignature; 034import org.androidtransfuse.scope.ApplicationScope; 035import org.androidtransfuse.util.AndroidLiterals; 036 037import javax.inject.Inject; 038import javax.lang.model.type.TypeMirror; 039 040import static org.androidtransfuse.util.TypeMirrorUtil.getTypeMirror; 041 042/** 043 * @author John Ericksen 044 */ 045public class ApplicationAnalysis implements Analysis<ComponentDescriptor> { 046 047 private final InjectionNodeBuilderRepositoryFactory variableBuilderRepositoryFactory; 048 private final ASTElementFactory astElementFactory; 049 private final ASTTypeBuilderVisitor astTypeBuilderVisitor; 050 private final AnalysisContextFactory analysisContextFactory; 051 private final ProviderInjectionNodeBuilderFactory providerInjectionNodeBuilder; 052 private final ObservesExpressionGenerator.ObservesExpressionGeneratorFactory observesExpressionGeneratorFactory; 053 private final OnCreateInjectionGenerator.InjectionGeneratorFactory injectionGeneratorFactory; 054 private final ApplicationManifestEntryGenerator applicationManifestEntryGenerator; 055 private final ScopesGeneration.ScopesGenerationFactory scopesGenerationFactory; 056 private final ComponentAnalysis componentAnalysis; 057 private final ApplicationScopeSeedGenerator applicationScopeSeedGenerator; 058 059 @Inject 060 public ApplicationAnalysis(InjectionNodeBuilderRepositoryFactory variableBuilderRepositoryFactory, 061 ASTElementFactory astElementFactory, 062 ASTTypeBuilderVisitor astTypeBuilderVisitor, 063 AnalysisContextFactory analysisContextFactory, 064 ProviderInjectionNodeBuilderFactory providerInjectionNodeBuilder, 065 ObservesExpressionGenerator.ObservesExpressionGeneratorFactory observesExpressionGeneratorFactory, 066 OnCreateInjectionGenerator.InjectionGeneratorFactory injectionGeneratorFactory, 067 ApplicationManifestEntryGenerator applicationManifestEntryGenerator, 068 ScopesGeneration.ScopesGenerationFactory scopesGenerationFactory, 069 ComponentAnalysis componentAnalysis, 070 ApplicationScopeSeedGenerator applicationScopeSeedGenerator) { 071 this.variableBuilderRepositoryFactory = variableBuilderRepositoryFactory; 072 this.astElementFactory = astElementFactory; 073 this.astTypeBuilderVisitor = astTypeBuilderVisitor; 074 this.analysisContextFactory = analysisContextFactory; 075 this.providerInjectionNodeBuilder = providerInjectionNodeBuilder; 076 this.observesExpressionGeneratorFactory = observesExpressionGeneratorFactory; 077 this.injectionGeneratorFactory = injectionGeneratorFactory; 078 this.applicationManifestEntryGenerator = applicationManifestEntryGenerator; 079 this.scopesGenerationFactory = scopesGenerationFactory; 080 this.componentAnalysis = componentAnalysis; 081 this.applicationScopeSeedGenerator = applicationScopeSeedGenerator; 082 } 083 084 public ComponentDescriptor analyze(ASTType astType) { 085 Application applicationAnnotation = astType.getAnnotation(Application.class); 086 087 088 PackageClass applicationClassName; 089 ComponentDescriptor applicationDescriptor = null; 090 091 if (astType.extendsFrom(AndroidLiterals.APPLICATION)) { 092 //vanilla Android Application 093 PackageClass activityPackageClass = astType.getPackageClass(); 094 applicationClassName = componentAnalysis.buildComponentPackageClass(astType, activityPackageClass.getClassName(), "Application"); 095 applicationDescriptor = new ComponentDescriptor(astType, null, applicationClassName); 096 } else { 097 098 applicationClassName = componentAnalysis.buildComponentPackageClass(astType, applicationAnnotation.name(), "Application"); 099 100 TypeMirror type = getTypeMirror(applicationAnnotation, "type"); 101 102 ASTType applicationType = type == null || type.toString().equals("java.lang.Object") ? AndroidLiterals.APPLICATION : type.accept(astTypeBuilderVisitor, null); 103 104 //analyze delegate 105 AnalysisContext analysisContext = analysisContextFactory.buildAnalysisContext(buildVariableBuilderMap(applicationType)); 106 107 applicationDescriptor = new ComponentDescriptor(astType, applicationType, applicationClassName, analysisContext); 108 109 componentAnalysis.setupGenerators(applicationDescriptor, applicationType, Application.class); 110 111 applicationDescriptor.getGenerators().add(scopesGenerationFactory.build(getASTMethod("onCreate"))); 112 applicationDescriptor.getGenerators().add(injectionGeneratorFactory.build(getASTMethod("onCreate"), astType)); 113 applicationDescriptor.getGenerators().add(observesExpressionGeneratorFactory.build( 114 getASTMethod("onCreate"), 115 getASTMethod("onCreate"), 116 getASTMethod("onTerminate") 117 )); 118 applicationDescriptor.getGenerators().add(applicationScopeSeedGenerator); 119 } 120 121 //add manifest elements 122 applicationDescriptor.getGenerators().add(applicationManifestEntryGenerator); 123 124 return applicationDescriptor; 125 } 126 127 private ASTMethod getASTMethod(String methodName, ASTType... args) { 128 return astElementFactory.findMethod(AndroidLiterals.APPLICATION, methodName, args); 129 } 130 131 private InjectionNodeBuilderRepository buildVariableBuilderMap(ASTType applicationType) { 132 InjectionNodeBuilderRepository injectionNodeBuilderRepository = componentAnalysis.setupInjectionNodeBuilderRepository(applicationType, Application.class); 133 134 135 ASTType applicationScopeType = astElementFactory.getType(ApplicationScope.ApplicationScopeQualifier.class); 136 ASTType applicationProvider = astElementFactory.getType(ApplicationScope.ApplicationProvider.class); 137 injectionNodeBuilderRepository.putType(AndroidLiterals.APPLICATION, providerInjectionNodeBuilder.builderProviderBuilder(applicationProvider)); 138 injectionNodeBuilderRepository.putType(AndroidLiterals.CONTEXT, providerInjectionNodeBuilder.builderProviderBuilder(applicationProvider)); 139 injectionNodeBuilderRepository.putScoped(new InjectionSignature(AndroidLiterals.APPLICATION), applicationScopeType); 140 injectionNodeBuilderRepository.putScoped(new InjectionSignature(AndroidLiterals.CONTEXT), applicationScopeType); 141 142 /*while(!applicationType.equals(AndroidLiterals.APPLICATION) && applicationType.inheritsFrom(AndroidLiterals.APPLICATION)){ 143 injectionNodeBuilderRepository.putType(applicationType, injectionBindingBuilder.buildThis(applicationType)); 144 applicationType = applicationType.getSuperClass(); 145 }*/ 146 147 148 injectionNodeBuilderRepository.addRepository(variableBuilderRepositoryFactory.buildApplicationInjections()); 149 injectionNodeBuilderRepository.addRepository(variableBuilderRepositoryFactory.buildModuleConfiguration()); 150 151 return injectionNodeBuilderRepository; 152 153 } 154}