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; 017 018import com.google.common.base.Function; 019import com.google.common.collect.FluentIterable; 020import org.androidtransfuse.ComponentBuilder; 021import org.androidtransfuse.ConfigurationRepository; 022import org.androidtransfuse.EventMapping; 023import org.androidtransfuse.InjectionMapping; 024import org.androidtransfuse.adapter.ASTType; 025import org.androidtransfuse.adapter.classes.ASTClassFactory; 026import org.androidtransfuse.util.matcher.Matcher; 027 028import javax.inject.Inject; 029import javax.inject.Singleton; 030import java.lang.annotation.Annotation; 031import java.util.*; 032 033/** 034 * @author John Ericksen 035 */ 036@Singleton 037public class ConfigurationRepositoryImpl implements ConfigurationRepository{ 038 039 private final ASTClassFactory astClassFactory; 040 041 private final Map<Matcher<AnnotatedType>, Configuration> configurations = new HashMap<Matcher<AnnotatedType>, Configuration>(); 042 043 private static class Configuration{ 044 private final List<EventMapping> events = new ArrayList<EventMapping>(); 045 private final List<InjectionMapping> mappings = new ArrayList<InjectionMapping>(); 046 private final List<SuperCallMapping> superCalls = new ArrayList<SuperCallMapping>(); 047 private final Set<Class<?>> callThroughEvents = new HashSet<Class<?>>(); 048 private final Map<ASTType, ListenableMethod> listeners = new HashMap<ASTType, ListenableMethod>(); 049 private Registration registraion = null; 050 } 051 052 @Inject 053 public ConfigurationRepositoryImpl(ASTClassFactory astClassFactory) { 054 this.astClassFactory = astClassFactory; 055 } 056 057 private List<Configuration> findConfigurations(ASTType type, Class<? extends Annotation> annotation){ 058 AnnotatedType signature = new AnnotatedType(type, astClassFactory.getType(annotation)); 059 List<Configuration> matched = new ArrayList<Configuration>(); 060 for (Map.Entry<Matcher<AnnotatedType>,Configuration> configurationEntry : configurations.entrySet()) { 061 if(configurationEntry.getKey().matches(signature)){ 062 matched.add(configurationEntry.getValue()); 063 } 064 } 065 return matched; 066 } 067 068 private Configuration getConfiguration(ASTType type, Class<? extends Annotation> annotation){ 069 AnnotatedTypeMatcher annotatedTypeMatcher = new AnnotatedTypeMatcher(type, astClassFactory.getType(annotation)); 070 if(!configurations.containsKey(annotatedTypeMatcher)){ 071 configurations.put(annotatedTypeMatcher, new Configuration()); 072 } 073 return configurations.get(annotatedTypeMatcher); 074 } 075 076 @Override 077 public void addRegistration(Class<? extends Annotation> componentAnnotation, ASTType componentType, String methodName, List<ASTType> parameters) { 078 getConfiguration(componentType, componentAnnotation).registraion = new Registration(methodName, parameters); 079 } 080 081 @Override 082 public void addSuperCall(Class<? extends Annotation> componentAnnotation, ASTType componentType, String methodName, List<ASTType> parameters) { 083 getConfiguration(componentType, componentAnnotation).superCalls.add(new SuperCallMapping(methodName, parameters)); 084 } 085 086 @Override 087 public ComponentBuilder component(Class<? extends Annotation> annotation) { 088 return new ComponentBuilder(this, annotation); 089 } 090 091 @Override 092 public void addEvent(Class<? extends Annotation> componentType, ASTType type, EventMapping eventMapping) { 093 getConfiguration(type, componentType).events.add(eventMapping); 094 } 095 096 public void addMapping(Class<? extends Annotation> componentType, ASTType type, InjectionMapping injectionMapping) { 097 getConfiguration(type, componentType).mappings.add(injectionMapping); 098 } 099 100 @Override 101 public void addCallThroughEvent(Class<? extends Annotation> componentType, ASTType type, Class<?> callThroughEventClass) { 102 getConfiguration(type, componentType).callThroughEvents.add(callThroughEventClass); 103 } 104 105 @Override 106 public void addListener(Class<? extends Annotation> componentType, ASTType type, ASTType listenerType, ASTType listenable, String listenerMethod) { 107 getConfiguration(type, componentType).listeners.put(listenerType, new ListenableMethod(listenable, listenerMethod)); 108 } 109 110 public List<EventMapping> getEvents(ASTType type, Class<? extends Annotation> annotation){ 111 return FluentIterable.from(findConfigurations(type, annotation)) 112 .transformAndConcat(new Function<Configuration, Iterable<EventMapping>>() { 113 public Iterable<EventMapping> apply(Configuration configuration) { 114 return configuration.events; 115 } 116 }).toList(); 117 } 118 119 public List<InjectionMapping> getMappings(ASTType type, Class<? extends Annotation> annotation) { 120 return FluentIterable.from(findConfigurations(type, annotation)) 121 .transformAndConcat(new Function<Configuration, Iterable<InjectionMapping>>() { 122 public Iterable<InjectionMapping> apply(Configuration configuration) { 123 return configuration.mappings; 124 } 125 }).toList(); 126 } 127 128 public Map<ASTType, ListenableMethod> getListeners(ASTType type, Class<? extends Annotation> annotation) { 129 Map<ASTType, ListenableMethod> matchedListeners = new HashMap<ASTType, ListenableMethod>(); 130 131 for (Configuration configuration : findConfigurations(type, annotation)) { 132 matchedListeners.putAll(configuration.listeners); 133 } 134 135 return matchedListeners; 136 } 137 138 public Set<Class<?>> getCallThroughClasses(ASTType type, Class<? extends Annotation> annotation) { 139 return FluentIterable.from(findConfigurations(type, annotation)) 140 .transformAndConcat(new Function<Configuration, Iterable<Class<?>>>() { 141 public Iterable<Class<?>> apply(Configuration configuration) { 142 return configuration.callThroughEvents; 143 } 144 }).toSet(); 145 } 146 147 public List<SuperCallMapping> getSuperCalls(ASTType type, Class<? extends Annotation> annotation){ 148 return FluentIterable.from(findConfigurations(type, annotation)) 149 .transformAndConcat(new Function<Configuration, Iterable<SuperCallMapping>>() { 150 public Iterable<SuperCallMapping> apply(Configuration configuration) { 151 return configuration.superCalls; 152 } 153 }).toList(); 154 } 155 156 public Registration getRegistration(ASTType type, Class<? extends Annotation> annotation){ 157 for(Configuration configuration : findConfigurations(type, annotation)){ 158 if(configuration.registraion != null){ 159 return configuration.registraion; 160 } 161 } 162 return null; 163 } 164}