/**
* 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.Application;
import org.androidtransfuse.experiment.ComponentDescriptor;
import org.androidtransfuse.experiment.ScopesGeneration;
import org.androidtransfuse.experiment.generators.ApplicationManifestEntryGenerator;
import org.androidtransfuse.experiment.generators.ApplicationScopeSeedGenerator;
import org.androidtransfuse.experiment.generators.ObservesExpressionGenerator;
import org.androidtransfuse.experiment.generators.OnCreateInjectionGenerator;
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 ApplicationAnalysis implements Analysis<ComponentDescriptor> {
private final InjectionNodeBuilderRepositoryFactory variableBuilderRepositoryFactory;
private final ASTElementFactory astElementFactory;
private final ASTTypeBuilderVisitor astTypeBuilderVisitor;
private final AnalysisContextFactory analysisContextFactory;
private final ObservesExpressionGenerator.ObservesExpressionGeneratorFactory observesExpressionGeneratorFactory;
private final OnCreateInjectionGenerator.InjectionGeneratorFactory injectionGeneratorFactory;
private final ApplicationManifestEntryGenerator applicationManifestEntryGenerator;
private final ScopesGeneration.ScopesGenerationFactory scopesGenerationFactory;
private final ComponentAnalysis componentAnalysis;
private final ApplicationScopeSeedGenerator applicationScopeSeedGenerator;
@Inject
public ApplicationAnalysis(InjectionNodeBuilderRepositoryFactory variableBuilderRepositoryFactory,
ASTElementFactory astElementFactory,
ASTTypeBuilderVisitor astTypeBuilderVisitor,
AnalysisContextFactory analysisContextFactory,
ObservesExpressionGenerator.ObservesExpressionGeneratorFactory observesExpressionGeneratorFactory,
OnCreateInjectionGenerator.InjectionGeneratorFactory injectionGeneratorFactory,
ApplicationManifestEntryGenerator applicationManifestEntryGenerator,
ScopesGeneration.ScopesGenerationFactory scopesGenerationFactory,
ComponentAnalysis componentAnalysis,
ApplicationScopeSeedGenerator applicationScopeSeedGenerator) {
this.variableBuilderRepositoryFactory = variableBuilderRepositoryFactory;
this.astElementFactory = astElementFactory;
this.astTypeBuilderVisitor = astTypeBuilderVisitor;
this.analysisContextFactory = analysisContextFactory;
this.observesExpressionGeneratorFactory = observesExpressionGeneratorFactory;
this.injectionGeneratorFactory = injectionGeneratorFactory;
this.applicationManifestEntryGenerator = applicationManifestEntryGenerator;
this.scopesGenerationFactory = scopesGenerationFactory;
this.componentAnalysis = componentAnalysis;
this.applicationScopeSeedGenerator = applicationScopeSeedGenerator;
}
public ComponentDescriptor analyze(ASTType astType) {
Application applicationAnnotation = astType.getAnnotation(Application.class);
PackageClass applicationClassName;
ComponentDescriptor applicationDescriptor = null;
if (astType.inherits(AndroidLiterals.APPLICATION)) {
//vanilla Android Application
PackageClass activityPackageClass = astType.getPackageClass();
applicationClassName = componentAnalysis.buildComponentPackageClass(astType, activityPackageClass.getClassName(), "Application");
applicationDescriptor = new ComponentDescriptor(astType, null, applicationClassName);
} else {
applicationClassName = componentAnalysis.buildComponentPackageClass(astType, applicationAnnotation.name(), "Application");
TypeMirror type = getTypeMirror(applicationAnnotation, "type");
ASTType applicationType = type == null || type.toString().equals("java.lang.Object") ? AndroidLiterals.APPLICATION : type.accept(astTypeBuilderVisitor, null);
//analyze delegate
AnalysisContext analysisContext = analysisContextFactory.buildAnalysisContext(buildVariableBuilderMap(applicationType));
applicationDescriptor = new ComponentDescriptor(astType, applicationType, applicationClassName, analysisContext);
componentAnalysis.setupGenerators(applicationDescriptor, applicationType, Application.class);
applicationDescriptor.getGenerators().add(scopesGenerationFactory.build(getASTMethod("onCreate")));
applicationDescriptor.getGenerators().add(injectionGeneratorFactory.build(getASTMethod("onCreate"), astType));
applicationDescriptor.getGenerators().add(observesExpressionGeneratorFactory.build(
getASTMethod("onCreate"),
getASTMethod("onTerminate"),
getASTMethod("onCreate"),
getASTMethod("onTerminate")
));
applicationDescriptor.getGenerators().add(applicationScopeSeedGenerator);
}
//add manifest elements
applicationDescriptor.getGenerators().add(applicationManifestEntryGenerator);
return applicationDescriptor;
}
private ASTMethod getASTMethod(String methodName, ASTType... args) {
return astElementFactory.findMethod(AndroidLiterals.APPLICATION, methodName, args);
}
private InjectionNodeBuilderRepository buildVariableBuilderMap(ASTType applicationType) {
InjectionNodeBuilderRepository injectionNodeBuilderRepository = componentAnalysis.setupInjectionNodeBuilderRepository(applicationType, Application.class);
injectionNodeBuilderRepository.addRepository(variableBuilderRepositoryFactory.buildModuleConfiguration());
return injectionNodeBuilderRepository;
}
}