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.BroadcastReceiver; 026import org.androidtransfuse.experiment.ComponentDescriptor; 027import org.androidtransfuse.experiment.ScopesGeneration; 028import org.androidtransfuse.experiment.generators.BroadcastReceiverManifestEntryGenerator; 029import org.androidtransfuse.experiment.generators.OnCreateInjectionGenerator; 030import org.androidtransfuse.gen.variableBuilder.InjectionBindingBuilder; 031import org.androidtransfuse.gen.variableBuilder.ProviderInjectionNodeBuilderFactory; 032import org.androidtransfuse.model.InjectionSignature; 033import org.androidtransfuse.scope.ApplicationScope; 034import org.androidtransfuse.util.AndroidLiterals; 035 036import javax.inject.Inject; 037import javax.lang.model.type.TypeMirror; 038 039import static org.androidtransfuse.util.TypeMirrorUtil.getTypeMirror; 040 041/** 042 * @author John Ericksen 043 */ 044public class BroadcastReceiverAnalysis implements Analysis<ComponentDescriptor> { 045 046 private final InjectionNodeBuilderRepositoryFactory injectionNodeBuilderRepositoryFactory; 047 private final ASTTypeBuilderVisitor astTypeBuilderVisitor; 048 private final AnalysisContextFactory analysisContextFactory; 049 private final InjectionBindingBuilder injectionBindingBuilder; 050 private final BroadcastReceiverManifestEntryGenerator manifestEntryGenerator; 051 private final ASTElementFactory astElementFactory; 052 private final ProviderInjectionNodeBuilderFactory providerInjectionNodeBuilder; 053 private final OnCreateInjectionGenerator.InjectionGeneratorFactory onCreateInjectionGeneratorFactory; 054 private final ScopesGeneration.ScopesGenerationFactory scopesGenerationFactory; 055 private final ComponentAnalysis componentAnalysis; 056 057 @Inject 058 public BroadcastReceiverAnalysis(InjectionNodeBuilderRepositoryFactory injectionNodeBuilderRepositoryFactory, 059 ASTTypeBuilderVisitor astTypeBuilderVisitor, 060 AnalysisContextFactory analysisContextFactory, 061 InjectionBindingBuilder injectionBindingBuilder, 062 BroadcastReceiverManifestEntryGenerator manifestEntryGenerator, 063 ASTElementFactory astElementFactory, 064 ProviderInjectionNodeBuilderFactory providerInjectionNodeBuilder, 065 OnCreateInjectionGenerator.InjectionGeneratorFactory onCreateInjectionGeneratorFactory, 066 ScopesGeneration.ScopesGenerationFactory scopesGenerationFactory, 067 ComponentAnalysis componentAnalysis) { 068 this.injectionNodeBuilderRepositoryFactory = injectionNodeBuilderRepositoryFactory; 069 this.astTypeBuilderVisitor = astTypeBuilderVisitor; 070 this.analysisContextFactory = analysisContextFactory; 071 this.injectionBindingBuilder = injectionBindingBuilder; 072 this.manifestEntryGenerator = manifestEntryGenerator; 073 this.astElementFactory = astElementFactory; 074 this.providerInjectionNodeBuilder = providerInjectionNodeBuilder; 075 this.onCreateInjectionGeneratorFactory = onCreateInjectionGeneratorFactory; 076 this.scopesGenerationFactory = scopesGenerationFactory; 077 this.componentAnalysis = componentAnalysis; 078 } 079 080 public ComponentDescriptor analyze(ASTType astType) { 081 082 BroadcastReceiver broadcastReceiverAnnotation = astType.getAnnotation(BroadcastReceiver.class); 083 084 ComponentDescriptor receiverDescriptor; 085 086 if (astType.extendsFrom(AndroidLiterals.BROADCAST_RECEIVER)) { 087 //vanilla Android broadcast receiver 088 PackageClass activityPackageClass = astType.getPackageClass(); 089 PackageClass receiverClassName = componentAnalysis.buildComponentPackageClass(astType, activityPackageClass.getClassName(), "BroadcastReceiver"); 090 receiverDescriptor = new ComponentDescriptor(astType, null, receiverClassName); 091 } else { 092 PackageClass receiverClassName = componentAnalysis.buildComponentPackageClass(astType, broadcastReceiverAnnotation.name(), "BroadcastReceiver"); 093 094 TypeMirror type = getTypeMirror(broadcastReceiverAnnotation, "type"); 095 ASTType receiverType = type == null || type.toString().equals("java.lang.Object") ? AndroidLiterals.BROADCAST_RECEIVER : type.accept(astTypeBuilderVisitor, null); 096 097 InjectionNodeBuilderRepository injectionNodeBuilderRepository = componentAnalysis.setupInjectionNodeBuilderRepository(receiverType, BroadcastReceiver.class); 098 ASTType applicationScopeType = astElementFactory.getType(ApplicationScope.ApplicationScopeQualifier.class); 099 ASTType applicationProvider = astElementFactory.getType(ApplicationScope.ApplicationProvider.class); 100 injectionNodeBuilderRepository.putType(AndroidLiterals.APPLICATION, providerInjectionNodeBuilder.builderProviderBuilder(applicationProvider)); 101 injectionNodeBuilderRepository.putScoped(new InjectionSignature(AndroidLiterals.APPLICATION), applicationScopeType); 102 103 injectionNodeBuilderRepository.addRepository( 104 injectionNodeBuilderRepositoryFactory.buildApplicationInjections()); 105 106 injectionNodeBuilderRepository.addRepository( 107 injectionNodeBuilderRepositoryFactory.buildModuleConfiguration()); 108 109 if(type != null) { 110 ASTType applicationASTType = type.accept(astTypeBuilderVisitor, null); 111 112 while(!applicationASTType.equals(AndroidLiterals.BROADCAST_RECEIVER) && applicationASTType.inheritsFrom(AndroidLiterals.BROADCAST_RECEIVER)){ 113 injectionNodeBuilderRepository.putType(applicationASTType, injectionBindingBuilder.buildThis(applicationASTType)); 114 applicationASTType = applicationASTType.getSuperClass(); 115 } 116 } 117 118 AnalysisContext analysisContext = analysisContextFactory.buildAnalysisContext(injectionNodeBuilderRepository); 119 120 receiverDescriptor = new ComponentDescriptor(astType, receiverType, receiverClassName, analysisContext); 121 122 receiverDescriptor.getGenerators().add(scopesGenerationFactory.build(getASTMethod("onReceive", AndroidLiterals.CONTEXT, AndroidLiterals.INTENT))); 123 124 receiverDescriptor.getGenerators().add(onCreateInjectionGeneratorFactory.build(getASTMethod("onReceive", AndroidLiterals.CONTEXT, AndroidLiterals.INTENT), astType)); 125 126 componentAnalysis.setupGenerators(receiverDescriptor, receiverType, BroadcastReceiver.class); 127 } 128 129 receiverDescriptor.getGenerators().add(manifestEntryGenerator); 130 131 return receiverDescriptor; 132 } 133 134 private ASTMethod getASTMethod(String methodName, ASTType... args) { 135 return getASTMethod(AndroidLiterals.BROADCAST_RECEIVER, methodName, args); 136 } 137 138 private ASTMethod getASTMethod(ASTType type, String methodName, ASTType... args) { 139 return astElementFactory.findMethod(type, methodName, args); 140 } 141}