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