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.repository;
017
018import com.google.common.collect.ImmutableMap;
019import com.google.common.collect.ImmutableSet;
020import com.sun.codemodel.JExpr;
021import org.androidtransfuse.adapter.ASTStringType;
022import org.androidtransfuse.adapter.ASTType;
023import org.androidtransfuse.analysis.module.ModuleRepository;
024import org.androidtransfuse.gen.variableBuilder.InjectionBindingBuilder;
025import org.androidtransfuse.util.AndroidLiterals;
026
027import javax.inject.Inject;
028import javax.inject.Provider;
029import javax.inject.Singleton;
030import java.lang.annotation.Annotation;
031import java.util.*;
032
033/**
034 * @author John Ericksen
035 */
036public class InjectionNodeBuilderRepositoryFactory implements ModuleRepository {
037
038    public static final java.lang.String POWER_SERVICE = "power";
039    public static final java.lang.String WINDOW_SERVICE = "window";
040    public static final java.lang.String LAYOUT_INFLATER_SERVICE = "layout_inflater";
041    public static final java.lang.String ACCOUNT_SERVICE = "account";
042    public static final java.lang.String ACTIVITY_SERVICE = "activity";
043    public static final java.lang.String ALARM_SERVICE = "alarm";
044    public static final java.lang.String NOTIFICATION_SERVICE = "notification";
045    public static final java.lang.String ACCESSIBILITY_SERVICE = "accessibility";
046    public static final java.lang.String KEYGUARD_SERVICE = "keyguard";
047    public static final java.lang.String LOCATION_SERVICE = "location";
048    public static final java.lang.String SEARCH_SERVICE = "search";
049    public static final java.lang.String SENSOR_SERVICE = "sensor";
050    public static final java.lang.String STORAGE_SERVICE = "storage";
051    public static final java.lang.String WALLPAPER_SERVICE = "wallpaper";
052    public static final java.lang.String VIBRATOR_SERVICE = "vibrator";
053    public static final java.lang.String CONNECTIVITY_SERVICE = "connectivity";
054    public static final java.lang.String WIFI_SERVICE = "wifi";
055    public static final java.lang.String WIFI_P2P_SERVICE = "wifip2p";
056    public static final java.lang.String NSD_SERVICE = "servicediscovery";
057    public static final java.lang.String AUDIO_SERVICE = "audio";
058    public static final java.lang.String MEDIA_ROUTER_SERVICE = "media_router";
059    public static final java.lang.String TELEPHONY_SERVICE = "phone";
060    public static final java.lang.String CLIPBOARD_SERVICE = "clipboard";
061    public static final java.lang.String INPUT_METHOD_SERVICE = "input_method";
062    public static final java.lang.String TEXT_SERVICES_MANAGER_SERVICE = "textservices";
063    public static final java.lang.String DROPBOX_SERVICE = "dropbox";
064    public static final java.lang.String DEVICE_POLICY_SERVICE = "device_policy";
065    public static final java.lang.String UI_MODE_SERVICE = "uimode";
066    public static final java.lang.String DOWNLOAD_SERVICE = "download";
067    public static final java.lang.String NFC_SERVICE = "nfc";
068    public static final java.lang.String USB_SERVICE = "usb";
069    public static final java.lang.String INPUT_SERVICE = "input";
070
071    private static final ImmutableMap<String, ASTType> SYSTEM_SERVICES;
072
073    static{
074        ImmutableMap.Builder<String, ASTType> systemServiceBuilder = ImmutableMap.builder();
075        //mapping to class by string to avoid differences in Android platform compilation problems.
076        systemServiceBuilder.put(ACCESSIBILITY_SERVICE, new ASTStringType("android.view.accessibility.AccessibilityManager"));
077        systemServiceBuilder.put(ACCOUNT_SERVICE, new ASTStringType("android.accounts.AccountManager"));
078        systemServiceBuilder.put(ACTIVITY_SERVICE, new ASTStringType("android.app.ActivityManager"));
079        systemServiceBuilder.put(ALARM_SERVICE, new ASTStringType("android.app.AlarmManager"));
080        systemServiceBuilder.put(AUDIO_SERVICE, new ASTStringType("android.media.AudioManager"));
081        systemServiceBuilder.put(CLIPBOARD_SERVICE, new ASTStringType("android.text.ClipboardManager"));
082        systemServiceBuilder.put(CONNECTIVITY_SERVICE, new ASTStringType("android.net.ConnectivityManager"));
083        systemServiceBuilder.put(DEVICE_POLICY_SERVICE, new ASTStringType("android.app.admin.DevicePolicyManager"));
084        systemServiceBuilder.put(DOWNLOAD_SERVICE, new ASTStringType("android.app.DownloadManager"));
085        systemServiceBuilder.put(DROPBOX_SERVICE, new ASTStringType("android.os.DropBoxManager"));
086        systemServiceBuilder.put(INPUT_METHOD_SERVICE, new ASTStringType("android.view.inputmethod.InputMethodManager"));
087        systemServiceBuilder.put(INPUT_SERVICE, new ASTStringType("android.hardware.input.InputManager"));
088        systemServiceBuilder.put(KEYGUARD_SERVICE, new ASTStringType("android.app.KeyguardManager"));
089        systemServiceBuilder.put(LAYOUT_INFLATER_SERVICE, new ASTStringType("android.view.LayoutInflater"));
090        systemServiceBuilder.put(LOCATION_SERVICE, new ASTStringType("android.location.LocationManager"));
091        systemServiceBuilder.put(MEDIA_ROUTER_SERVICE, new ASTStringType("android.media.MediaRouter"));
092        systemServiceBuilder.put(NFC_SERVICE, new ASTStringType("android.nfc.NfcManager"));
093        systemServiceBuilder.put(NSD_SERVICE, new ASTStringType("android.net.nsd.NsdManager"));
094        systemServiceBuilder.put(NOTIFICATION_SERVICE, new ASTStringType("android.app.NotificationManager"));
095        systemServiceBuilder.put(POWER_SERVICE, new ASTStringType("android.os.PowerManager"));
096        systemServiceBuilder.put(SEARCH_SERVICE, new ASTStringType("android.app.SearchManager"));
097        systemServiceBuilder.put(SENSOR_SERVICE, new ASTStringType("android.hardware.SensorManager"));
098        systemServiceBuilder.put(STORAGE_SERVICE, new ASTStringType("android.os.storage.StorageManager"));
099        systemServiceBuilder.put(TELEPHONY_SERVICE, new ASTStringType("android.telephony.TelephonyManager"));
100        systemServiceBuilder.put(TEXT_SERVICES_MANAGER_SERVICE, new ASTStringType("android.view.textservice.TextServicesManager"));
101        systemServiceBuilder.put(UI_MODE_SERVICE, new ASTStringType("android.app.UiModeManager"));
102        systemServiceBuilder.put(USB_SERVICE, new ASTStringType("android.hardware.usb.UsbManager"));
103        systemServiceBuilder.put(VIBRATOR_SERVICE, new ASTStringType("android.os.Vibrator"));
104        systemServiceBuilder.put(WALLPAPER_SERVICE, new ASTStringType("android.service.wallpaper.WallpaperService"));
105        systemServiceBuilder.put(WIFI_P2P_SERVICE, new ASTStringType("android.net.wifi.p2p.WifiP2pManager"));
106        systemServiceBuilder.put(WIFI_SERVICE, new ASTStringType("android.net.wifi.WifiManager"));
107        systemServiceBuilder.put(WINDOW_SERVICE, new ASTStringType("android.view.WindowManager"));
108
109        SYSTEM_SERVICES = systemServiceBuilder.build();
110    }
111
112    @Singleton
113    public static final class InjectionNodeRepository{
114
115        private final Set<ASTType> installedComponents = new HashSet<ASTType>();
116        private final InjectionNodeBuilderRepository moduleRepository;
117
118        @Inject
119        public InjectionNodeRepository(InjectionNodeBuilderRepository moduleRepository){
120            this.moduleRepository = moduleRepository;
121        }
122    }
123
124    private final InjectionNodeRepository repository;
125    private final InjectionBindingBuilder injectionBindingBuilder;
126    private final Provider<InjectionNodeBuilderRepository> injectionNodeBuilderRepositoryProvider;
127    private final ScopeAspectFactoryRepositoryProvider scopeAspectFactoryRepositoryProvider;
128
129    @Inject
130    public InjectionNodeBuilderRepositoryFactory(InjectionBindingBuilder injectionBindingBuilder,
131                                                 Provider<InjectionNodeBuilderRepository> injectionNodeBuilderRepositoryProvider,
132                                                 ScopeAspectFactoryRepositoryProvider scopeAspectFactoryRepositoryProvider,
133                                                 InjectionNodeRepository repository) {
134        this.injectionBindingBuilder = injectionBindingBuilder;
135        this.injectionNodeBuilderRepositoryProvider = injectionNodeBuilderRepositoryProvider;
136        this.scopeAspectFactoryRepositoryProvider = scopeAspectFactoryRepositoryProvider;
137        this.repository = repository;
138    }
139
140    public InjectionNodeBuilderRepository buildApplicationInjections() {
141        InjectionNodeBuilderRepository builderRepository = injectionNodeBuilderRepositoryProvider.get();
142        //resources
143        builderRepository.putType(AndroidLiterals.RESOURCES, injectionBindingBuilder.dependency(AndroidLiterals.APPLICATION).invoke(AndroidLiterals.RESOURCES, "getResources").build());
144
145        //menu inflater
146        builderRepository.putType(AndroidLiterals.MENU_INFLATER, injectionBindingBuilder.dependency(AndroidLiterals.ACTIVITY).invoke(AndroidLiterals.MENU_INFLATER, "getMenuInflater").build());
147
148        //system services
149        for (Map.Entry<String, ASTType> systemServiceEntry : SYSTEM_SERVICES.entrySet()) {
150            builderRepository.putType(systemServiceEntry.getValue(),
151                    injectionBindingBuilder.dependency(AndroidLiterals.CONTEXT).invoke(new ASTStringType("java.lang.Object"), "getSystemService").arg(JExpr.lit(systemServiceEntry.getKey())).build());
152        }
153
154        builderRepository.putType(AndroidLiterals.SHARED_PREFERENCES,
155                injectionBindingBuilder.staticInvoke(AndroidLiterals.PREFERENCE_MANAGER, AndroidLiterals.SHARED_PREFERENCES, "getDefaultSharedPreferences").dependencyArg(AndroidLiterals.CONTEXT).build());
156
157
158        return builderRepository;
159    }
160
161    public InjectionNodeBuilderRepository buildModuleConfiguration() {
162        InjectionNodeBuilderRepository builderRepository = injectionNodeBuilderRepositoryProvider.get();
163        builderRepository.addRepository(this.repository.moduleRepository);
164        builderRepository.addRepository(scopeAspectFactoryRepositoryProvider.get());
165        builderRepository.addRepository(injectionNodeBuilderRepositoryProvider.get());
166
167        return builderRepository;
168    }
169
170    @Override
171    public Collection<ASTType> getInstalledAnnotatedWith(Class<? extends Annotation> annotation) {
172        ImmutableSet.Builder<ASTType> installedBuilder = ImmutableSet.builder();
173
174        for (ASTType installedComponent : repository.installedComponents) {
175            if(installedComponent.isAnnotated(annotation)){
176                installedBuilder.add(installedComponent);
177            }
178        }
179
180        return installedBuilder.build();
181    }
182
183    @Override
184    public void addInstalledComponents(ASTType[] astType) {
185        repository.installedComponents.addAll(Arrays.asList(astType));
186    }
187
188    @Override
189    public void addModuleRepository(InjectionNodeBuilderRepository repository) {
190        this.repository.moduleRepository.addRepository(repository);
191    }
192}