/**
* Copyright 2011-2015 John Ericksen
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.androidtransfuse.analysis;
import org.androidtransfuse.adapter.ASTMethod;
import org.androidtransfuse.adapter.ASTType;
import org.androidtransfuse.adapter.PackageClass;
import org.androidtransfuse.adapter.element.ASTElementFactory;
import org.androidtransfuse.adapter.element.ASTTypeBuilderVisitor;
import org.androidtransfuse.analysis.repository.InjectionNodeBuilderRepository;
import org.androidtransfuse.analysis.repository.InjectionNodeBuilderRepositoryFactory;
import org.androidtransfuse.annotations.BroadcastReceiver;
import org.androidtransfuse.experiment.ComponentDescriptor;
import org.androidtransfuse.experiment.ScopesGeneration;
import org.androidtransfuse.experiment.generators.BroadcastReceiverManifestEntryGenerator;
import org.androidtransfuse.experiment.generators.IntentFactoryGenerator;
import org.androidtransfuse.experiment.generators.OnCreateInjectionGenerator;
import org.androidtransfuse.gen.variableBuilder.InjectionBindingBuilder;
import org.androidtransfuse.util.AndroidLiterals;
import javax.inject.Inject;
import javax.lang.model.type.TypeMirror;
import static org.androidtransfuse.util.TypeMirrorUtil.getTypeMirror;
/**
* @author John Ericksen
*/
public class BroadcastReceiverAnalysis implements Analysis<ComponentDescriptor> {
private final InjectionNodeBuilderRepositoryFactory injectionNodeBuilderRepositoryFactory;
private final ASTTypeBuilderVisitor astTypeBuilderVisitor;
private final AnalysisContextFactory analysisContextFactory;
private final InjectionBindingBuilder injectionBindingBuilder;
private final BroadcastReceiverManifestEntryGenerator manifestEntryGenerator;
private final ASTElementFactory astElementFactory;
private final OnCreateInjectionGenerator.InjectionGeneratorFactory onCreateInjectionGeneratorFactory;
private final ScopesGeneration.ScopesGenerationFactory scopesGenerationFactory;
private final ComponentAnalysis componentAnalysis;
private final IntentFactoryGenerator intentFactoryGenerator;
@Inject
public BroadcastReceiverAnalysis(InjectionNodeBuilderRepositoryFactory injectionNodeBuilderRepositoryFactory,
ASTTypeBuilderVisitor astTypeBuilderVisitor,
AnalysisContextFactory analysisContextFactory,
InjectionBindingBuilder injectionBindingBuilder,
BroadcastReceiverManifestEntryGenerator manifestEntryGenerator,
ASTElementFactory astElementFactory,
OnCreateInjectionGenerator.InjectionGeneratorFactory onCreateInjectionGeneratorFactory,
ScopesGeneration.ScopesGenerationFactory scopesGenerationFactory,
ComponentAnalysis componentAnalysis,
IntentFactoryGenerator intentFactoryGenerator) {
this.injectionNodeBuilderRepositoryFactory = injectionNodeBuilderRepositoryFactory;
this.astTypeBuilderVisitor = astTypeBuilderVisitor;
this.analysisContextFactory = analysisContextFactory;
this.injectionBindingBuilder = injectionBindingBuilder;
this.manifestEntryGenerator = manifestEntryGenerator;
this.astElementFactory = astElementFactory;
this.onCreateInjectionGeneratorFactory = onCreateInjectionGeneratorFactory;
this.scopesGenerationFactory = scopesGenerationFactory;
this.componentAnalysis = componentAnalysis;
this.intentFactoryGenerator = intentFactoryGenerator;
}
public ComponentDescriptor analyze(ASTType astType) {
BroadcastReceiver broadcastReceiverAnnotation = astType.getAnnotation(BroadcastReceiver.class);
ComponentDescriptor receiverDescriptor;
if (astType.inherits(AndroidLiterals.BROADCAST_RECEIVER)) {
//vanilla Android broadcast receiver
PackageClass activityPackageClass = astType.getPackageClass();
PackageClass receiverClassName = componentAnalysis.buildComponentPackageClass(astType, activityPackageClass.getClassName(), "BroadcastReceiver");
receiverDescriptor = new ComponentDescriptor(astType, null, receiverClassName);
} else {
PackageClass receiverClassName = componentAnalysis.buildComponentPackageClass(astType, broadcastReceiverAnnotation.name(), "BroadcastReceiver");
TypeMirror type = getTypeMirror(broadcastReceiverAnnotation, "type");
ASTType receiverType = type == null || type.toString().equals("java.lang.Object") ? AndroidLiterals.BROADCAST_RECEIVER : type.accept(astTypeBuilderVisitor, null);
InjectionNodeBuilderRepository injectionNodeBuilderRepository = componentAnalysis.setupInjectionNodeBuilderRepository(receiverType, BroadcastReceiver.class);
injectionNodeBuilderRepository.addRepository(
injectionNodeBuilderRepositoryFactory.buildModuleConfiguration());
if(type != null) {
ASTType applicationASTType = type.accept(astTypeBuilderVisitor, null);
while(!applicationASTType.equals(AndroidLiterals.BROADCAST_RECEIVER) && applicationASTType.inherits(AndroidLiterals.BROADCAST_RECEIVER)){
injectionNodeBuilderRepository.putType(applicationASTType, injectionBindingBuilder.buildThis(applicationASTType));
applicationASTType = applicationASTType.getSuperClass();
}
}
AnalysisContext analysisContext = analysisContextFactory.buildAnalysisContext(injectionNodeBuilderRepository);
receiverDescriptor = new ComponentDescriptor(astType, receiverType, receiverClassName, analysisContext);
receiverDescriptor.getGenerators().add(scopesGenerationFactory.build(getASTMethod("onReceive", AndroidLiterals.CONTEXT, AndroidLiterals.INTENT)));
receiverDescriptor.getGenerators().add(onCreateInjectionGeneratorFactory.build(getASTMethod("onReceive", AndroidLiterals.CONTEXT, AndroidLiterals.INTENT), astType));
componentAnalysis.setupGenerators(receiverDescriptor, receiverType, BroadcastReceiver.class);
}
receiverDescriptor.getGenerators().add(manifestEntryGenerator);
receiverDescriptor.getGenerators().add(intentFactoryGenerator);
return receiverDescriptor;
}
private ASTMethod getASTMethod(String methodName, ASTType... args) {
return getASTMethod(AndroidLiterals.BROADCAST_RECEIVER, methodName, args);
}
private ASTMethod getASTMethod(ASTType type, String methodName, ASTType... args) {
return astElementFactory.findMethod(type, methodName, args);
}
}