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.astAnalyzer;
017
018import com.google.common.collect.ImmutableList;
019import com.google.common.collect.ImmutableMap;
020import org.androidtransfuse.adapter.*;
021import org.androidtransfuse.analysis.AnalysisContext;
022import org.androidtransfuse.analysis.repository.RegistrationGeneratorFactory;
023import org.androidtransfuse.annotations.RegisterListener;
024import org.androidtransfuse.gen.componentBuilder.RegistrationGenerator;
025import org.androidtransfuse.model.InjectionNode;
026
027import java.util.ArrayList;
028import java.util.Arrays;
029import java.util.List;
030import java.util.Map;
031
032/**
033 * @author John Ericksen
034 */
035public class RegistrationAnalyzer implements ASTAnalysis {
036
037    private ImmutableMap<ASTType, RegistrationGeneratorFactory> generatorFactories;
038
039    public RegistrationAnalyzer(ImmutableMap<ASTType, RegistrationGeneratorFactory> generatorFactories) {
040        this.generatorFactories = generatorFactories;
041    }
042
043    @Override
044    public void analyzeType(InjectionNode injectionNode, final ASTType astType, AnalysisContext context) {
045        analyze(astType, astType, injectionNode, context);
046    }
047
048    @Override
049    public void analyzeMethod(InjectionNode injectionNode, ASTType concreteType, final ASTMethod astMethod, AnalysisContext context) {
050        analyze(astMethod, astMethod.getReturnType(), injectionNode, context);
051    }
052
053    @Override
054    public void analyzeField(InjectionNode injectionNode, ASTType concreteType, final ASTField astField, AnalysisContext context) {
055        analyze(astField, astField.getASTType(), injectionNode, context);
056    }
057
058    private <T> void analyze(ASTBase astBase, ASTType astType, InjectionNode injectionNode, AnalysisContext context) {
059        if (astBase.isAnnotated(RegisterListener.class)) {
060            ASTAnnotation registerAnnotation = astBase.getASTAnnotation(RegisterListener.class);
061
062            ASTType[] interfaces = registerAnnotation.getProperty("interfaces", ASTType[].class);
063
064            List<ASTType> interfaceList = new ArrayList<ASTType>();
065            if (interfaces != null) {
066                interfaceList.addAll(Arrays.asList(interfaces));
067            }
068
069            List<RegistrationGenerator> generators = getRegistrationGenerators(injectionNode, astBase, astType, interfaceList, registerAnnotation, context);
070
071            if (!generators.isEmpty()) {
072                RegistrationAspect registrationAspect = getRegistrationAspect(injectionNode);
073                registrationAspect.addRegistrationBuilders(generators);
074            }
075        }
076    }
077
078    private ImmutableList<RegistrationGenerator> getRegistrationGenerators(InjectionNode injectionNode, ASTBase astBase, ASTType astType, List<ASTType> interfaceList, ASTAnnotation registerAnnotation, AnalysisContext context) {
079
080        ImmutableList.Builder<RegistrationGenerator> generators = ImmutableList.builder();
081
082        for (Map.Entry<ASTType, RegistrationGeneratorFactory> generatorFactoryEntry : generatorFactories.entrySet()) {
083            if ((interfaceList.isEmpty() || interfaceList.contains(generatorFactoryEntry.getKey()))
084                    && astType.inheritsFrom(generatorFactoryEntry.getKey())) {
085                generators.add(generatorFactoryEntry.getValue().buildRegistrationGenerator(injectionNode, astBase, registerAnnotation, context));
086            }
087        }
088
089        return generators.build();
090    }
091
092    private RegistrationAspect getRegistrationAspect(InjectionNode injectionNode) {
093        if (!injectionNode.containsAspect(RegistrationAspect.class)) {
094            injectionNode.addAspect(new RegistrationAspect());
095        }
096        return injectionNode.getAspect(RegistrationAspect.class);
097    }
098}