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 RoutingResourceTable(PackageResourceTable... resourceTables)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 getRawValue(int resId, ResTable_config config)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 getValue(@onnull ResName resName, ResTable_config config)28 @Override public TypedResource getValue(@Nonnull ResName resName, ResTable_config config) { 29 return pickFor(resName).getValue(resName, config); 30 } 31 getValue(int resId, ResTable_config config)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 getXml(ResName resName, ResTable_config config)37 @Override public XmlBlock getXml(ResName resName, ResTable_config config) { 38 return pickFor(resName).getXml(resName, config); 39 } 40 getRawValue(ResName resName, ResTable_config config)41 @Override public InputStream getRawValue(ResName resName, ResTable_config config) { 42 return pickFor(resName).getRawValue(resName, config); 43 } 44 45 @Override getResourceId(ResName resName)46 public Integer getResourceId(ResName resName) { 47 return pickFor(resName).getResourceId(resName); 48 } 49 50 @Override getResName(int resourceId)51 public ResName getResName(int resourceId) { 52 return pickFor(resourceId).getResName(resourceId); 53 } 54 55 @Override receive(Visitor visitor)56 public void receive(Visitor visitor) { 57 for (PackageResourceTable resourceTable : resourceTables.values()) { 58 resourceTable.receive(visitor); 59 } 60 } 61 62 @Override getPackageName()63 public String getPackageName() { 64 return resourceTables.keySet().iterator().next(); 65 } 66 pickFor(int resId)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 pickFor(ResName resName)76 private PackageResourceTable pickFor(ResName resName) { 77 if (resName == null) return EMPTY_RESOURCE_TABLE; 78 return pickFor(resName.packageName); 79 } 80 pickFor(String namespace)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 whichProvidesFor(String namespace)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 toString()103 public String toString() { 104 return new TreeSet<>(resourceTables.keySet()).toString(); 105 } 106 } 107