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.config;
017
018import com.sun.codemodel.JCodeModel;
019import com.sun.codemodel.JDefinedClass;
020import org.androidtransfuse.CodeGenerationScope;
021import org.androidtransfuse.ConfigurationRepository;
022import org.androidtransfuse.ConfigurationScope;
023import org.androidtransfuse.TransfuseAnnotationProcessor;
024import org.androidtransfuse.adapter.ASTFactory;
025import org.androidtransfuse.adapter.ASTType;
026import org.androidtransfuse.analysis.ConfigurationRepositoryImpl;
027import org.androidtransfuse.analysis.module.ModuleRepository;
028import org.androidtransfuse.analysis.repository.InjectionNodeBuilderRepository;
029import org.androidtransfuse.analysis.repository.InjectionNodeBuilderRepositoryFactory;
030import org.androidtransfuse.analysis.repository.InjectionNodeBuilderRepositoryProvider;
031import org.androidtransfuse.annotations.*;
032import org.androidtransfuse.bootstrap.BootstrapModule;
033import org.androidtransfuse.bootstrap.Namespace;
034import org.androidtransfuse.gen.ClassGenerationStrategy;
035import org.androidtransfuse.gen.InjectionBuilderContextFactory;
036import org.androidtransfuse.gen.InstantiationStrategyFactory;
037import org.androidtransfuse.gen.invocationBuilder.DefaultInvocationBuilderStrategy;
038import org.androidtransfuse.gen.invocationBuilder.InvocationBuilderStrategy;
039import org.androidtransfuse.gen.variableDecorator.ExpressionDecoratorFactory;
040import org.androidtransfuse.gen.variableDecorator.VariableExpressionBuilder;
041import org.androidtransfuse.gen.variableDecorator.VariableExpressionBuilderFactory;
042import org.androidtransfuse.model.manifest.Manifest;
043import org.androidtransfuse.model.r.RResource;
044import org.androidtransfuse.processor.*;
045import org.androidtransfuse.transaction.ScopedTransactionBuilder;
046import org.androidtransfuse.transaction.TransactionProcessor;
047import org.androidtransfuse.transaction.TransactionProcessorChannel;
048import org.androidtransfuse.transaction.TransactionProcessorPool;
049import org.androidtransfuse.util.Generated;
050import org.androidtransfuse.util.Logger;
051import org.androidtransfuse.util.ManifestLocator;
052import org.androidtransfuse.util.MessagerLogger;
053import org.androidtransfuse.validation.Validator;
054
055import javax.annotation.processing.Filer;
056import javax.annotation.processing.Messager;
057import javax.annotation.processing.ProcessingEnvironment;
058import javax.inject.Named;
059import javax.inject.Provider;
060import javax.inject.Singleton;
061import javax.lang.model.util.Elements;
062import javax.xml.bind.JAXBContext;
063import java.io.File;
064import java.util.Map;
065
066@BootstrapModule
067@DefineScopes({
068        @DefineScope(annotation = CodeGenerationScope.class, scope = ThreadLocalScope.class),
069        @DefineScope(annotation = ConfigurationScope.class, scope = MapScope.class)
070})
071@Bindings({
072        @Bind(type = ModuleRepository.class, to = InjectionNodeBuilderRepositoryFactory.class),
073        @Bind(type = InvocationBuilderStrategy.class, to = DefaultInvocationBuilderStrategy.class)
074})
075@BindProviders({
076        @BindProvider(type = JAXBContext.class, provider = JAXBContextProvider.class),
077        @BindProvider(type = VariableExpressionBuilder.class, provider = ExpressionDecoratorFactory.class),
078        @BindProvider(type = GeneratorRepository.class, provider = GeneratorRepositoryProvider.class),
079        @BindProvider(type = InjectionNodeBuilderRepository.class, provider = InjectionNodeBuilderRepositoryProvider.class)
080})
081@Install({
082        ASTFactory.class,
083        InjectionNodeBuilderRepositoryFactory.class,
084        VariableExpressionBuilderFactory.class,
085        InjectionBuilderContextFactory.class,
086        InstantiationStrategyFactory.class})
087@Namespace("Transfuse")
088public class TransfuseAndroidModule {
089
090    public static final String ORIGINAL_MANIFEST = "originalManifest";
091    public static final String MANIFEST_FILE = "manifestFile";
092
093    @Provides
094    @CodeGenerationScope
095    public Validator provideValidator(@Named(Validator.LOG_PREPEND) String prepend, Messager messager){
096        return new Validator(prepend, messager);
097    }
098
099    @Provides
100    @Singleton
101    public ConfigurationRepository getRepository(ConfigurationRepositoryImpl repository){
102        return repository;
103    }
104
105    @Provides
106    public ClassGenerationStrategy getClassGenerationStrategy(){
107        return new ClassGenerationStrategy(Generated.class, TransfuseAnnotationProcessor.class.getName());
108    }
109
110    @Provides
111    @CodeGenerationScope
112    public JCodeModel getJCodeModel(){
113        return new JCodeModel();
114    }
115
116    @Provides
117    @Singleton
118    public Elements getElements(ProcessingEnvironment processingEnvironment){
119        return processingEnvironment.getElementUtils();
120    }
121
122    @Provides
123    @Singleton
124    public Messager getMessenger(ProcessingEnvironment processingEnvironment){
125        return processingEnvironment.getMessager();
126    }
127
128    @Provides
129    @Singleton
130    public Logger getLogger(ProcessingEnvironment processingEnvironment){
131        return new MessagerLogger(getLogPreprend(), processingEnvironment.getMessager());
132    }
133
134    @Provides
135    @Named(Validator.LOG_PREPEND)
136    public String getLogPreprend(){
137        return "Transfuse: ";
138    }
139
140    @Provides
141    @Singleton
142    public Filer getFiler(ProcessingEnvironment processingEnvironment){
143        return new SynchronizedFiler(processingEnvironment.getFiler());
144    }
145
146    @Provides
147    @Named(ManifestLocator.ANDROID_MANIFEST_FILE_OPTION)
148    public String getManifestFileLocation(ProcessingEnvironment processingEnvironment){
149        return processingEnvironment.getOptions().get(ManifestLocator.ANDROID_MANIFEST_FILE_OPTION);
150    }
151
152    @Provides
153    @Named(GenerateModuleProcessor.MANIFEST_PROCESSING_OPTION)
154    public String getManifestProcessing(ProcessingEnvironment processingEnvironment){
155        return processingEnvironment.getOptions().get(GenerateModuleProcessor.MANIFEST_PROCESSING_OPTION);
156    }
157
158    @Provides
159    @Singleton
160    public ProcessingEnvironment getProcessingEnvironment(){
161        throw new OutOfScopeException("Expected seeded object, unable to construct directly.");
162    }
163
164    @Provides
165    @ConfigurationScope
166    public RResource getRResource(){
167        throw new OutOfScopeException("Expected seeded object, unable to construct directly.");
168    }
169
170    @Provides
171    @ConfigurationScope
172    @Named(MANIFEST_FILE)
173    public File getManifestFile(){
174        throw new OutOfScopeException("Expected seeded object, unable to construct directly.");
175    }
176
177    @Provides
178    @ConfigurationScope
179    @Named(ORIGINAL_MANIFEST)
180    public Manifest getManifest(){
181        throw new OutOfScopeException("Expected seeded object, unable to construct directly.");
182    }
183
184    @Provides
185    public FactoryProcessor getFactoryProcessor(Provider<FactoryTransactionWorker> factoryTransactionWorkerProvider,
186                                                Provider<FactoriesTransactionWorker> factoriesTransactionWorkerProvider,
187                                                ScopedTransactionBuilder scopedTransactionBuilder) {
188        TransactionProcessorPool<Provider<ASTType>, JDefinedClass> factoryProcessor =
189                new TransactionProcessorPool<Provider<ASTType>, JDefinedClass>();
190        TransactionProcessorPool<Map<Provider<ASTType>, JDefinedClass>, Void> factoriesProcessor =
191                new TransactionProcessorPool<Map<Provider<ASTType>, JDefinedClass>, Void>();
192
193        TransactionProcessor processor =
194                new TransactionProcessorChannel<Provider<ASTType>, JDefinedClass, Void>(
195                        factoryProcessor,
196                        factoriesProcessor,
197                        scopedTransactionBuilder.buildFactory(factoriesTransactionWorkerProvider));
198
199        return new FactoryProcessor(processor, factoryProcessor, scopedTransactionBuilder.buildFactory(factoryTransactionWorkerProvider));
200    }
201}