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.processor;
017
018import com.google.common.collect.ImmutableMap;
019import com.google.common.collect.ImmutableSet;
020import com.sun.codemodel.JDefinedClass;
021import org.androidtransfuse.adapter.ASTType;
022import org.androidtransfuse.analysis.*;
023import org.androidtransfuse.annotations.*;
024import org.androidtransfuse.config.ScopesGeneratorWorker;
025import org.androidtransfuse.experiment.ComponentDescriptor;
026import org.androidtransfuse.gen.AnalysisGenerationFactory;
027import org.androidtransfuse.gen.ComponentsGenerator;
028import org.androidtransfuse.gen.PackageHelperGeneratorAdapter;
029import org.androidtransfuse.transaction.*;
030
031import javax.inject.Inject;
032import javax.inject.Provider;
033import java.lang.annotation.Annotation;
034import java.util.HashMap;
035import java.util.Map;
036
037/**
038 * Configures the Processor chain
039 *
040 *[ditaa]
041 * --
042 *     +---------+             +--------------+    +----------+          +-----------------+
043 * -+->| Modules +-------+--+->| Component(s) +-+->| Manifest |---+-+-+->| Package Helpers |
044 *  |  +---------+       |  |  +--------------+ |  +----------+   | | |  +-----------------+
045 *  |                    |  |                   |                 | | |
046 *  |  +---------------+ |  |                   |  +------------+ | | |  +-----------------+
047 *  +->| ImplementedBy +-+  |                   +->| Components |-+ | +->| Virtual Proxies |
048 *     +---------------+    |                      +------------+   | |  +-----------------+
049 *                          |                                       | |
050 *                          |  +-------------+     +-----------+    | |  +-------------+
051 *                          +->| Factory(s)  +---->| Factories +----+ +->| Scopes Util |
052 *                             +-------------+     +-----------+         +-------------+
053 * --
054 * @author John Ericksen
055 */
056public class GeneratorRepositoryProvider implements Provider<GeneratorRepository> {
057
058    private final FactoryProcessor factoryProcessor;
059    private final AnalysisGenerationFactory analysisGenerationFactory;
060    private final Provider<ActivityAnalysis> activityAnalysisProvider;
061    private final Provider<BroadcastReceiverAnalysis> broadcastReceiverAnalysisProvider;
062    private final Provider<ServiceAnalysis> serviceAnalysisProvider;
063    private final Provider<FragmentAnalysis> fragmentAnalysisProvider;
064    private final Provider<ApplicationAnalysis> applicationAnalysisProvider;
065    private final AnalysisGenerationTransactionProcessorBuilderFactory processorFactory;
066    private final GenerateModuleProcessor generateModuleProcessor;
067    private final Provider<PackageHelperGeneratorAdapter> packageHelperTransactionWorkerProvider;
068    private final ModuleProcessorBuilder moduleProcessorBuilder;
069    private final ImplementedByProcessorBuilder implementedByProcessorBuilder;
070    private final TransactionProcessorPool<Map<Provider<ASTType>, JDefinedClass>, JDefinedClass> componentsRepositoryProcessor;
071    private final Provider<ComponentsGenerator> componentsGeneratorProvider;
072    private final Provider<VirtualProxyTransactionWorker> virtualProxyTransactionWorkerProvider;
073    private final Provider<ScopesGeneratorWorker> scopesGeneratorWorkerProvider;
074    private final ScopedTransactionBuilder scopedTransactionBuilder;
075
076    @Inject
077    public GeneratorRepositoryProvider(FactoryProcessor factoryProcessor,
078                                       AnalysisGenerationFactory analysisGenerationFactory,
079                                       Provider<ActivityAnalysis> activityAnalysisProvider,
080                                       Provider<BroadcastReceiverAnalysis> broadcastReceiverAnalysisProvider,
081                                       Provider<ServiceAnalysis> serviceAnalysisProvider,
082                                       Provider<FragmentAnalysis> fragmentAnalysisProvider,
083                                       Provider<ApplicationAnalysis> applicationAnalysisProvider,
084                                       AnalysisGenerationTransactionProcessorBuilderFactory processorFactory,
085                                       GenerateModuleProcessor generateModuleProcessor,
086                                       Provider<PackageHelperGeneratorAdapter> packageHelperTransactionWorkerProvider,
087                                       ModuleProcessorBuilder moduleProcessorBuilder,
088                                       ImplementedByProcessorBuilder implementedByProcessorBuilder,
089                                       TransactionProcessorPool<Map<Provider<ASTType>, JDefinedClass>, JDefinedClass> componentsRepositoryProcessor,
090                                       Provider<ComponentsGenerator> componentsGeneratorProvider,
091                                       Provider<VirtualProxyTransactionWorker> virtualProxyTransactionWorkerProvider,
092                                       Provider<ScopesGeneratorWorker> scopesGeneratorWorkerProvider,
093                                       ScopedTransactionBuilder scopedTransactionBuilder) {
094        this.factoryProcessor = factoryProcessor;
095        this.analysisGenerationFactory = analysisGenerationFactory;
096        this.activityAnalysisProvider = activityAnalysisProvider;
097        this.broadcastReceiverAnalysisProvider = broadcastReceiverAnalysisProvider;
098        this.serviceAnalysisProvider = serviceAnalysisProvider;
099        this.fragmentAnalysisProvider = fragmentAnalysisProvider;
100        this.applicationAnalysisProvider = applicationAnalysisProvider;
101        this.processorFactory = processorFactory;
102        this.generateModuleProcessor = generateModuleProcessor;
103        this.packageHelperTransactionWorkerProvider = packageHelperTransactionWorkerProvider;
104        this.moduleProcessorBuilder = moduleProcessorBuilder;
105        this.implementedByProcessorBuilder = implementedByProcessorBuilder;
106        this.componentsRepositoryProcessor = componentsRepositoryProcessor;
107        this.componentsGeneratorProvider = componentsGeneratorProvider;
108        this.virtualProxyTransactionWorkerProvider = virtualProxyTransactionWorkerProvider;
109        this.scopesGeneratorWorkerProvider = scopesGeneratorWorkerProvider;
110        this.scopedTransactionBuilder = scopedTransactionBuilder;
111    }
112
113    @Override
114    public GeneratorRepository get() {
115
116        ImmutableMap.Builder<Class<? extends Annotation>, TransactionProcessorBuilder<Provider<ASTType>, ?>> processorMapBuilder = ImmutableMap.builder();
117        ImmutableSet.Builder<TransactionProcessor<Provider<ASTType>, JDefinedClass>> componentProcessors = ImmutableSet.builder();
118
119        // Module and ImplementedBy configuration processing
120        processorMapBuilder.put(TransfuseModule.class, moduleProcessorBuilder);
121        processorMapBuilder.put(ImplementedBy.class, implementedByProcessorBuilder);
122
123        TransactionProcessor<Provider<ASTType>, Void> configurationProcessors = new TransactionProcessorComposite<Provider<ASTType>, Void>(
124                ImmutableSet.of(moduleProcessorBuilder.getTransactionProcessor(),
125                        implementedByProcessorBuilder.getTransactionProcessor()));
126
127        // Component processing
128        Map<Class<? extends Annotation>, Provider<? extends Analysis<ComponentDescriptor>>> analyzers =
129                new HashMap<Class<? extends Annotation>, Provider<? extends Analysis<ComponentDescriptor>>>();
130        analyzers.put(Application.class, applicationAnalysisProvider);
131        analyzers.put(Activity.class, activityAnalysisProvider);
132        analyzers.put(BroadcastReceiver.class, broadcastReceiverAnalysisProvider);
133        analyzers.put(Service.class, serviceAnalysisProvider);
134        analyzers.put(Fragment.class, fragmentAnalysisProvider);
135
136        for (Map.Entry<Class<? extends Annotation>, Provider<? extends Analysis<ComponentDescriptor>>> providerEntry : analyzers.entrySet()) {
137            Provider<TransactionWorker<Provider<ASTType>, JDefinedClass>> workerProvider = analysisGenerationFactory.buildAnalysisGenerationProvider(providerEntry.getValue());
138            AnalysisGenerationTransactionProcessorBuilder processorBuilder = processorFactory.buildBuilder(workerProvider);
139
140            componentProcessors.add(processorBuilder.getTransactionProcessor());
141
142            processorMapBuilder.put(providerEntry.getKey(), processorBuilder);
143        }
144
145        TransactionProcessor<Provider<ASTType>, JDefinedClass> componentsProcessor = new TransactionProcessorComposite<Provider<ASTType>, JDefinedClass>(componentProcessors.build());
146
147        // Manifest processing (depends on components)
148        TransactionProcessor<Void, Void> manifestProcessor = new TransactionProcessorPredefined(ImmutableSet.of(new Transaction<Void, Void>(generateModuleProcessor)));
149        TransactionProcessor<Void, Void> componentProcessorCompletion = new TransactionProcessorChain(
150
151                new TransactionProcessorChannel<Provider<ASTType>, JDefinedClass, JDefinedClass>(
152                        componentsProcessor,
153                        componentsRepositoryProcessor,
154                        scopedTransactionBuilder.buildFactory(componentsGeneratorProvider)),
155                manifestProcessor);
156
157        ImmutableSet.Builder<TransactionProcessor<?, ?>> configurationDependentBuilders = ImmutableSet.builder();
158
159        configurationDependentBuilders.add(componentProcessorCompletion);
160
161        processorMapBuilder.put(Factory.class, factoryProcessor);
162
163        // Package Helper processing (to be run last)
164        TransactionProcessor<Void, Void> packageHelperProcessor = new TransactionProcessorPredefined(
165                ImmutableSet.of(
166                        scopedTransactionBuilder.build(packageHelperTransactionWorkerProvider),
167                        scopedTransactionBuilder.build(virtualProxyTransactionWorkerProvider),
168                        scopedTransactionBuilder.build(scopesGeneratorWorkerProvider)));
169
170        TransactionProcessor<?, ?> configurationDependentProcessors =
171                new TransactionProcessorComposite(configurationDependentBuilders.build());
172
173        TransactionProcessor<Void, Void> processor = new TransactionProcessorChain(configurationProcessors,
174                new TransactionProcessorChain(factoryProcessor.getTransactionProcessor(),
175                new TransactionProcessorChain(configurationDependentProcessors, packageHelperProcessor)));
176
177        return new GeneratorRepository(processorMapBuilder.build(), processor);
178    }
179}