1 package org.robolectric.res; 2 3 import java.io.InputStream; 4 import java.util.LinkedHashMap; 5 import java.util.Map; 6 import java.util.TreeSet; 7 import javax.annotation.Nonnull; 8 import org.robolectric.res.android.ResTable_config; 9 import org.robolectric.res.builder.XmlBlock; 10 11 public class RoutingResourceTable implements ResourceTable { 12 private static final PackageResourceTable EMPTY_RESOURCE_TABLE = new ResourceTableFactory().newResourceTable(""); 13 private final Map<String, PackageResourceTable> resourceTables; 14 15 public RoutingResourceTable(PackageResourceTable... resourceTables) { 16 this.resourceTables = new LinkedHashMap<>(); 17 18 for (PackageResourceTable resourceTable : resourceTables) { 19 this.resourceTables.put(resourceTable.getPackageName(), resourceTable); 20 } 21 } 22 23 @Override public InputStream getRawValue(int resId, ResTable_config config) { 24 ResName resName = getResName(resId); 25 return resName != null ? getRawValue(resName, config) : null; 26 } 27 28 @Override public TypedResource getValue(@Nonnull ResName resName, ResTable_config config) { 29 return pickFor(resName).getValue(resName, config); 30 } 31 32 @Override public TypedResource getValue(int resId, ResTable_config config) { 33 ResName resName = pickFor(resId).getResName(resId); 34 return resName != null ? getValue(resName, config) : null; 35 } 36 37 @Override public XmlBlock getXml(ResName resName, ResTable_config config) { 38 return pickFor(resName).getXml(resName, config); 39 } 40 41 @Override public InputStream getRawValue(ResName resName, ResTable_config config) { 42 return pickFor(resName).getRawValue(resName, config); 43 } 44 45 @Override 46 public Integer getResourceId(ResName resName) { 47 return pickFor(resName).getResourceId(resName); 48 } 49 50 @Override 51 public ResName getResName(int resourceId) { 52 return pickFor(resourceId).getResName(resourceId); 53 } 54 55 @Override 56 public void receive(Visitor visitor) { 57 for (PackageResourceTable resourceTable : resourceTables.values()) { 58 resourceTable.receive(visitor); 59 } 60 } 61 62 @Override 63 public String getPackageName() { 64 return resourceTables.keySet().iterator().next(); 65 } 66 67 private PackageResourceTable pickFor(int resId) { 68 for (PackageResourceTable resourceTable : resourceTables.values()) { 69 if (resourceTable.getPackageIdentifier() == ResourceIds.getPackageIdentifier(resId)) { 70 return resourceTable; 71 } 72 } 73 return EMPTY_RESOURCE_TABLE; 74 } 75 76 private PackageResourceTable pickFor(ResName resName) { 77 if (resName == null) return EMPTY_RESOURCE_TABLE; 78 return pickFor(resName.packageName); 79 } 80 81 private PackageResourceTable pickFor(String namespace) { 82 if (namespace.equals("android.internal")) { 83 return EMPTY_RESOURCE_TABLE; 84 } 85 PackageResourceTable resourceTable = resourceTables.get(namespace); 86 if (resourceTable == null) { 87 resourceTable = whichProvidesFor(namespace); 88 return (resourceTable != null) ? resourceTable : EMPTY_RESOURCE_TABLE; 89 } 90 return resourceTable; 91 } 92 93 private PackageResourceTable whichProvidesFor(String namespace) { 94 for (PackageResourceTable resourceTable : resourceTables.values()) { 95 if (resourceTable.getPackageName().equals(namespace)) { 96 return resourceTable; 97 } 98 } 99 return null; 100 } 101 102 @Override 103 public String toString() { 104 return new TreeSet<>(resourceTables.keySet()).toString(); 105 } 106 } 107