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.*; 026import org.androidtransfuse.experiment.ComponentDescriptor; 027import org.androidtransfuse.experiment.ScopesGeneration; 028import org.androidtransfuse.experiment.generators.*; 029import org.androidtransfuse.gen.GeneratorFactory; 030import org.androidtransfuse.gen.componentBuilder.ListenerRegistrationGenerator; 031import org.androidtransfuse.gen.componentBuilder.NonConfigurationInstanceGenerator; 032import org.androidtransfuse.gen.variableBuilder.*; 033import org.androidtransfuse.intentFactory.ActivityIntentFactoryStrategy; 034import org.androidtransfuse.model.InjectionSignature; 035import org.androidtransfuse.scope.ApplicationScope; 036import org.androidtransfuse.util.AndroidLiterals; 037 038import javax.inject.Inject; 039import javax.inject.Provider; 040import javax.lang.model.type.TypeMirror; 041 042import static org.androidtransfuse.util.TypeMirrorUtil.getTypeMirror; 043 044/** 045 * Activity related Analysis 046 * 047 * @author John Ericksen 048 */ 049public class ActivityAnalysis implements Analysis<ComponentDescriptor> { 050 051 private final InjectionNodeBuilderRepositoryFactory injectionNodeBuilderRepositoryFactory; 052 private final AnalysisContextFactory analysisContextFactory; 053 private final ASTElementFactory astElementFactory; 054 private final ProviderInjectionNodeBuilderFactory providerInjectionNodeBuilder; 055 private final ASTTypeBuilderVisitor astTypeBuilderVisitor; 056 private final InjectionBindingBuilder injectionBindingBuilder; 057 private final ObservesExpressionGenerator.ObservesExpressionGeneratorFactory observesExpressionGeneratorFactory; 058 private final ViewInjectionNodeBuilder viewVariableBuilder; 059 private final ExtraInjectionNodeBuilder extraInjectionNodeBuilder; 060 private final SystemServiceBindingInjectionNodeBuilder systemServiceBindingInjectionNodeBuilder; 061 private final ResourceInjectionNodeBuilder resourceInjectionNodeBuilder; 062 private final PreferenceInjectionNodeBuilder preferenceInjectionNodeBuilder; 063 private final Provider<ActivityManifestEntryGenerator> manifestGeneratorProvider; 064 private final LayoutGenerator layoutGenerator; 065 private final LayoutHandlerGenerator layoutHandlerGenerator; 066 private final WindowFeatureGenerator windowFeatureGenerator; 067 private final GeneratorFactory generatorFactory; 068 private final ListenerRegistrationGenerator.ListerRegistrationGeneratorFactory listerRegistrationGeneratorFactory; 069 private final NonConfigurationInstanceGenerator.NonconfigurationInstanceGeneratorFactory nonConfigurationInstanceGeneratorFactory; 070 private final OnCreateInjectionGenerator.InjectionGeneratorFactory onCreateInjectionGeneratorFactory; 071 private final ScopesGeneration.ScopesGenerationFactory scopesGenerationFactory; 072 private final ComponentAnalysis componentAnalysis; 073 074 @Inject 075 public ActivityAnalysis(InjectionNodeBuilderRepositoryFactory injectionNodeBuilderRepositoryFactory, 076 AnalysisContextFactory analysisContextFactory, 077 ASTElementFactory astElementFactory, 078 ProviderInjectionNodeBuilderFactory providerInjectionNodeBuilder, 079 ASTTypeBuilderVisitor astTypeBuilderVisitor, 080 InjectionBindingBuilder injectionBindingBuilder, 081 ObservesExpressionGenerator.ObservesExpressionGeneratorFactory observesExpressionGeneratorFactory, 082 ViewInjectionNodeBuilder viewVariableBuilder, 083 ExtraInjectionNodeBuilder extraInjectionNodeBuilder, 084 SystemServiceBindingInjectionNodeBuilder systemServiceBindingInjectionNodeBuilder, 085 ResourceInjectionNodeBuilder resourceInjectionNodeBuilder, 086 PreferenceInjectionNodeBuilder preferenceInjectionNodeBuilder, 087 Provider<ActivityManifestEntryGenerator> manifestGeneratorProvider, 088 LayoutGenerator layoutGenerator, 089 LayoutHandlerGenerator layoutHandlerGenerator, 090 WindowFeatureGenerator windowFeatureGenerator, 091 GeneratorFactory generatorFactory, 092 ListenerRegistrationGenerator.ListerRegistrationGeneratorFactory listerRegistrationGeneratorFactory, 093 NonConfigurationInstanceGenerator.NonconfigurationInstanceGeneratorFactory nonConfigurationInstanceGeneratorFactory, 094 OnCreateInjectionGenerator.InjectionGeneratorFactory onCreateInjectionGeneratorFactory, 095 ScopesGeneration.ScopesGenerationFactory scopesGenerationFactory, 096 ComponentAnalysis componentAnalysis) { 097 this.injectionNodeBuilderRepositoryFactory = injectionNodeBuilderRepositoryFactory; 098 this.analysisContextFactory = analysisContextFactory; 099 this.astElementFactory = astElementFactory; 100 this.providerInjectionNodeBuilder = providerInjectionNodeBuilder; 101 this.astTypeBuilderVisitor = astTypeBuilderVisitor; 102 this.injectionBindingBuilder = injectionBindingBuilder; 103 this.observesExpressionGeneratorFactory = observesExpressionGeneratorFactory; 104 this.viewVariableBuilder = viewVariableBuilder; 105 this.extraInjectionNodeBuilder = extraInjectionNodeBuilder; 106 this.systemServiceBindingInjectionNodeBuilder = systemServiceBindingInjectionNodeBuilder; 107 this.resourceInjectionNodeBuilder = resourceInjectionNodeBuilder; 108 this.preferenceInjectionNodeBuilder = preferenceInjectionNodeBuilder; 109 this.manifestGeneratorProvider = manifestGeneratorProvider; 110 this.layoutGenerator = layoutGenerator; 111 this.layoutHandlerGenerator = layoutHandlerGenerator; 112 this.windowFeatureGenerator = windowFeatureGenerator; 113 this.generatorFactory = generatorFactory; 114 this.listerRegistrationGeneratorFactory = listerRegistrationGeneratorFactory; 115 this.nonConfigurationInstanceGeneratorFactory = nonConfigurationInstanceGeneratorFactory; 116 this.onCreateInjectionGeneratorFactory = onCreateInjectionGeneratorFactory; 117 this.scopesGenerationFactory = scopesGenerationFactory; 118 this.componentAnalysis = componentAnalysis; 119 } 120 121 public ComponentDescriptor analyze(ASTType input) { 122 123 Activity activityAnnotation = input.getAnnotation(Activity.class); 124 PackageClass activityClassName; 125 ComponentDescriptor activityDescriptor; 126 127 if (input.extendsFrom(AndroidLiterals.ACTIVITY)) { 128 //vanilla Android activity 129 PackageClass activityPackageClass = input.getPackageClass(); 130 activityClassName = componentAnalysis.buildComponentPackageClass(input, activityPackageClass.getClassName(), "Activity"); 131 activityDescriptor = new ComponentDescriptor(input, null, activityClassName); 132 } else { 133 //generated Android activity 134 activityClassName = componentAnalysis.buildComponentPackageClass(input, activityAnnotation.name(), "Activity"); 135 136 TypeMirror type = getTypeMirror(activityAnnotation, "type"); 137 138 ASTType activityType = type == null || type.toString().equals("java.lang.Object") ? AndroidLiterals.ACTIVITY : type.accept(astTypeBuilderVisitor, null); 139 140 AnalysisContext context = analysisContextFactory.buildAnalysisContext(buildVariableBuilderMap(activityType)); 141 142 activityDescriptor = new ComponentDescriptor(input, activityType, activityClassName, context); 143 144 activityDescriptor.getGenerators().add(layoutGenerator); 145 activityDescriptor.getGenerators().add(layoutHandlerGenerator); 146 activityDescriptor.getGenerators().add(windowFeatureGenerator); 147 activityDescriptor.getGenerators().add(scopesGenerationFactory.build(getASTMethod("onCreate", AndroidLiterals.BUNDLE))); 148 activityDescriptor.getGenerators().add(onCreateInjectionGeneratorFactory.build(getASTMethod("onCreate", AndroidLiterals.BUNDLE), input)); 149 //extra intent factory 150 activityDescriptor.getGenerators().add(generatorFactory.buildStrategyGenerator(ActivityIntentFactoryStrategy.class)); 151 //listener registration 152 activityDescriptor.getGenerators().add(listerRegistrationGeneratorFactory.build(getASTMethod("onCreate", AndroidLiterals.BUNDLE))); 153 //non configuration instance update 154 activityDescriptor.getGenerators().add(nonConfigurationInstanceGeneratorFactory.build(getASTMethod("onCreate", AndroidLiterals.BUNDLE))); 155 156 componentAnalysis.setupGenerators(activityDescriptor, activityType, Activity.class); 157 158 activityDescriptor.getGenerators().add(observesExpressionGeneratorFactory.build( 159 getASTMethod("onCreate", AndroidLiterals.BUNDLE), 160 getASTMethod("onResume"), 161 getASTMethod("onPause"))); 162 } 163 164 //add manifest elements 165 activityDescriptor.getGenerators().add(manifestGeneratorProvider.get()); 166 167 return activityDescriptor; 168 } 169 170 private InjectionNodeBuilderRepository buildVariableBuilderMap(ASTType activityType) { 171 172 InjectionNodeBuilderRepository injectionNodeBuilderRepository = componentAnalysis.setupInjectionNodeBuilderRepository(activityType, Activity.class); 173 174 ASTType applicationScopeType = astElementFactory.getType(ApplicationScope.ApplicationScopeQualifier.class); 175 ASTType applicationProvider = astElementFactory.getType(ApplicationScope.ApplicationProvider.class); 176 injectionNodeBuilderRepository.putType(AndroidLiterals.APPLICATION, providerInjectionNodeBuilder.builderProviderBuilder(applicationProvider)); 177 injectionNodeBuilderRepository.putType(AndroidLiterals.CONTEXT, injectionBindingBuilder.buildThis(AndroidLiterals.CONTEXT)); 178 injectionNodeBuilderRepository.putScoped(new InjectionSignature(AndroidLiterals.APPLICATION), applicationScopeType); 179 180 injectionNodeBuilderRepository.putType(AndroidLiterals.ACTIVITY, injectionBindingBuilder.buildThis(AndroidLiterals.ACTIVITY)); 181 182 while(!activityType.equals(AndroidLiterals.ACTIVITY) && activityType.inheritsFrom(AndroidLiterals.ACTIVITY)){ 183 injectionNodeBuilderRepository.putType(activityType, injectionBindingBuilder.buildThis(activityType)); 184 activityType = activityType.getSuperClass(); 185 } 186 187 injectionNodeBuilderRepository.putAnnotation(Extra.class, extraInjectionNodeBuilder); 188 injectionNodeBuilderRepository.putAnnotation(Resource.class, resourceInjectionNodeBuilder); 189 injectionNodeBuilderRepository.putAnnotation(SystemService.class, systemServiceBindingInjectionNodeBuilder); 190 injectionNodeBuilderRepository.putAnnotation(Preference.class, preferenceInjectionNodeBuilder); 191 injectionNodeBuilderRepository.putAnnotation(View.class, viewVariableBuilder); 192 193 injectionNodeBuilderRepository.addRepository( 194 injectionNodeBuilderRepositoryFactory.buildApplicationInjections()); 195 196 injectionNodeBuilderRepository.addRepository( 197 injectionNodeBuilderRepositoryFactory.buildModuleConfiguration()); 198 199 return injectionNodeBuilderRepository; 200 201 } 202 203 private ASTMethod getASTMethod(String methodName, ASTType... args) { 204 return getASTMethod(AndroidLiterals.ACTIVITY, methodName, args); 205 } 206 207 private ASTMethod getASTMethod(ASTType type, String methodName, ASTType... args) { 208 return astElementFactory.findMethod(type, methodName, args); 209 } 210}