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.module;
017
018import com.google.common.collect.ImmutableList;
019import com.google.common.collect.ImmutableMap;
020import org.androidtransfuse.Plugin;
021import org.androidtransfuse.Plugins;
022import org.androidtransfuse.adapter.ASTAnnotation;
023import org.androidtransfuse.adapter.ASTMethod;
024import org.androidtransfuse.adapter.ASTType;
025import org.androidtransfuse.adapter.classes.ASTClassFactory;
026import org.androidtransfuse.analysis.repository.InjectionNodeBuilderRepository;
027import org.androidtransfuse.annotations.*;
028import org.androidtransfuse.transaction.AbstractCompletionTransactionWorker;
029
030import javax.inject.Inject;
031import javax.inject.Provider;
032
033/**
034 * Central module processor class.  Scans the input AST elements for the appropriate annotations and registers
035 * the results with the given processor.
036 *
037 * @author John Ericksen
038 */
039public class ModuleTransactionWorker extends AbstractCompletionTransactionWorker<Provider<ASTType>, Void> {
040
041    private final ImmutableMap<ASTType, MethodProcessor> methodProcessors;
042    private final ImmutableMap<ASTType, TypeProcessor> typeProcessors;
043    private final ModuleRepository moduleRepository;
044    private final Provider<InjectionNodeBuilderRepository> injectionNodeBuilderRepositoryProvider;
045
046    @Inject
047    public ModuleTransactionWorker(BindProcessor bindProcessor,
048                                   BindProviderProcessor bindProviderProcessor,
049                                   BindInterceptorProcessor bindInterceptorProcessor,
050                                   BindingConfigurationFactory configurationFactory,
051                                   ProvidesProcessor providesProcessor,
052                                   ASTClassFactory astClassFactory,
053                                   UsesPermissionProcessor usesPermissionProcessor,
054                                   UsesSdkProcessor usesSdkProcessor,
055                                   DefineScopeProcessor defineScopeProcessor,
056                                   PermissionProcessor permissionProcessor,
057                                   UsesFeatureProcessor usesFeatureProcessor,
058                                   ModuleRepository moduleRepository,
059                                   PluginProcessor pluginProcessor,
060                                   Provider<InjectionNodeBuilderRepository> injectionNodeBuilderRepositoryProvider) {
061        this.moduleRepository = moduleRepository;
062        this.injectionNodeBuilderRepositoryProvider = injectionNodeBuilderRepositoryProvider;
063        ImmutableMap.Builder<ASTType, MethodProcessor> methodProcessorsBuilder = ImmutableMap.builder();
064
065        methodProcessorsBuilder.put(astClassFactory.getType(Provides.class), providesProcessor);
066
067        this.methodProcessors = methodProcessorsBuilder.build();
068
069        ImmutableMap.Builder<ASTType, TypeProcessor> typeProcessorsBuilder = ImmutableMap.builder();
070        typeProcessorsBuilder.put(astClassFactory.getType(BindInterceptor.class), bindInterceptorProcessor);
071        typeProcessorsBuilder.put(astClassFactory.getType(BindInterceptors.class),
072                configurationFactory.buildConfigurationComposite(bindInterceptorProcessor));
073        typeProcessorsBuilder.put(astClassFactory.getType(BindProvider.class), bindProviderProcessor);
074        typeProcessorsBuilder.put(astClassFactory.getType(BindProviders.class),
075                configurationFactory.buildConfigurationComposite(bindProviderProcessor));
076        typeProcessorsBuilder.put(astClassFactory.getType(Bind.class), bindProcessor);
077        typeProcessorsBuilder.put(astClassFactory.getType(Bindings.class),
078                configurationFactory.buildConfigurationComposite(bindProcessor));
079        typeProcessorsBuilder.put(astClassFactory.getType(UsesPermission.class), usesPermissionProcessor);
080        typeProcessorsBuilder.put(astClassFactory.getType(UsesPermissions.class),
081                configurationFactory.buildConfigurationComposite(usesPermissionProcessor));
082        typeProcessorsBuilder.put(astClassFactory.getType(Permission.class),permissionProcessor);
083        typeProcessorsBuilder.put(astClassFactory.getType(Permissions.class),
084                configurationFactory.buildConfigurationComposite(permissionProcessor));
085        typeProcessorsBuilder.put(astClassFactory.getType(UsesFeature.class), usesFeatureProcessor);
086        typeProcessorsBuilder.put(astClassFactory.getType(UsesFeatures.class),
087                configurationFactory.buildConfigurationComposite(usesFeatureProcessor));
088        typeProcessorsBuilder.put(astClassFactory.getType(UsesSdk.class), usesSdkProcessor);
089        typeProcessorsBuilder.put(astClassFactory.getType(DefineScope.class), defineScopeProcessor);
090        typeProcessorsBuilder.put(astClassFactory.getType(DefineScopes.class),
091                configurationFactory.buildConfigurationComposite(defineScopeProcessor));
092        typeProcessorsBuilder.put(astClassFactory.getType(Plugin.class), pluginProcessor);
093        typeProcessorsBuilder.put(astClassFactory.getType(Plugins.class),
094                configurationFactory.buildConfigurationComposite(pluginProcessor));
095
096        typeProcessors = typeProcessorsBuilder.build();
097    }
098
099    @Override
100    public Void innerRun(Provider<ASTType> astTypeProvider) {
101
102        ASTType type = astTypeProvider.get();
103
104        ImmutableList.Builder<ModuleConfiguration> configurations = ImmutableList.builder();
105
106        for (ASTAnnotation typeAnnotation : type.getAnnotations()) {
107            if(typeProcessors.containsKey(typeAnnotation.getASTType())){
108                TypeProcessor typeProcessor = typeProcessors.get(typeAnnotation.getASTType());
109
110                configurations.add(typeProcessor.process(type, typeAnnotation));
111            }
112        }
113
114        for (ASTMethod astMethod : type.getMethods()) {
115            for (ASTAnnotation astAnnotation : astMethod.getAnnotations()) {
116                if (methodProcessors.containsKey(astAnnotation.getASTType())) {
117                    MethodProcessor methodProcessor = methodProcessors.get(astAnnotation.getASTType());
118
119                    configurations.add(methodProcessor.process(type, astMethod, astAnnotation));
120                }
121            }
122        }
123
124        InjectionNodeBuilderRepository repository = injectionNodeBuilderRepositoryProvider.get();
125        for (ModuleConfiguration moduleConfiguration : configurations.build()) {
126            moduleConfiguration.setConfiguration(repository);
127        }
128        moduleRepository.addModuleRepository(repository);
129
130        return null;
131    }
132}