/* * Copyright 2009 Michael Burton * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions * and limitations under the License. */ package roboguice.inject; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.Set; import com.google.inject.Guice; import com.google.inject.MembersInjector; import com.google.inject.TypeLiteral; import com.google.inject.HierarchyTraversalFilter; import com.google.inject.spi.TypeEncounter; import com.google.inject.spi.TypeListener; import android.app.Application; import android.content.res.ColorStateList; import android.content.res.Resources; import android.graphics.Movie; import android.graphics.drawable.Drawable; import android.view.animation.Animation; import android.view.animation.AnimationUtils; /** * Resource listener. * * @author Mike Burton */ public class ResourceListener implements TypeListener { protected Application application; private HierarchyTraversalFilter filter; public ResourceListener(Application application) { this.application = application; } public <I> void hear(TypeLiteral<I> typeLiteral, TypeEncounter<I> typeEncounter) { if (filter == null) { filter = Guice.createHierarchyTraversalFilter(); } else { filter.reset(); } Class<?> c = typeLiteral.getRawType(); while (isWorthScanning(c)) { Set<Field> allFields = null; allFields = filter.getAllFields(InjectResource.class.getName(), c); if (allFields != null) { for (Field field : allFields) { if (field.isAnnotationPresent(InjectResource.class) && !Modifier.isStatic(field.getModifiers())) typeEncounter.register(new ResourceMembersInjector<I>(field, application, field.getAnnotation(InjectResource.class))); } c = c.getSuperclass(); } } } private boolean isWorthScanning(Class<?> c) { return filter.isWorthScanningForFields(InjectResource.class.getName(), c); } protected static class ResourceMembersInjector<T> implements MembersInjector<T> { protected Field field; protected Application application; protected InjectResource annotation; public ResourceMembersInjector(Field field, Application application, InjectResource annotation) { this.field = field; this.application = application; this.annotation = annotation; } public void injectMembers(T instance) { Object value = null; try { final Resources resources = application.getResources(); final int id = getId(resources, annotation); final Class<?> t = field.getType(); if (String.class.isAssignableFrom(t)) { value = resources.getString(id); } else if (boolean.class.isAssignableFrom(t) || Boolean.class.isAssignableFrom(t)) { value = resources.getBoolean(id); } else if (ColorStateList.class.isAssignableFrom(t)) { value = resources.getColorStateList(id); } else if (int.class.isAssignableFrom(t) || Integer.class.isAssignableFrom(t)) { value = resources.getInteger(id); } else if (Drawable.class.isAssignableFrom(t)) { value = resources.getDrawable(id); } else if (String[].class.isAssignableFrom(t)) { value = resources.getStringArray(id); } else if (int[].class.isAssignableFrom(t) || Integer[].class.isAssignableFrom(t)) { value = resources.getIntArray(id); } else if (Animation.class.isAssignableFrom(t)) { value = AnimationUtils.loadAnimation(application, id); } else if (Movie.class.isAssignableFrom(t)) { value = resources.getMovie(id); } if (value == null && Nullable.notNullable(field)) { throw new NullPointerException(String.format("Can't inject null value into %s.%s when field is not @Nullable", field.getDeclaringClass(), field.getName())); } field.setAccessible(true); field.set(instance, value); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (IllegalArgumentException f) { throw new IllegalArgumentException(String.format("Can't assign %s value %s to %s field %s", value != null ? value.getClass() : "(null)", value, field.getType(), field.getName())); } } protected int getId(Resources resources, InjectResource annotation) { int id = annotation.value(); return id >= 0 ? id : resources.getIdentifier(annotation.name(), null, application.getPackageName()); } } }