1 package org.robolectric.res; 2 3 import com.google.common.base.Strings; 4 import java.util.LinkedHashMap; 5 import java.util.List; 6 import java.util.Map; 7 import java.util.Objects; 8 import java.util.regex.Pattern; 9 10 public class StyleData implements Style { 11 private final String packageName; 12 private final String name; 13 private final String parent; 14 private final Map<ResName, AttributeResource> items = new LinkedHashMap<>(); 15 StyleData(String packageName, String name, String parent, List<AttributeResource> attributeResources)16 public StyleData(String packageName, String name, String parent, List<AttributeResource> attributeResources) { 17 this.packageName = packageName; 18 this.name = name; 19 this.parent = parent; 20 21 for (AttributeResource attributeResource : attributeResources) { 22 add(attributeResource.resName, attributeResource); 23 } 24 } 25 getName()26 public String getName() { 27 return name; 28 } 29 getParent()30 public String getParent() { 31 return parent; 32 } 33 add(ResName attrName, AttributeResource attribute)34 private void add(ResName attrName, AttributeResource attribute) { 35 attrName.mustBe("attr"); 36 items.put(attrName, attribute); 37 } 38 getAttrValue(ResName resName)39 @Override public AttributeResource getAttrValue(ResName resName) { 40 AttributeResource attributeResource = items.get(resName); 41 42 // This hack allows us to look up attributes from downstream dependencies, see comment in 43 // org.robolectric.shadows.ShadowThemeTest.obtainTypedArrayFromDependencyLibrary() 44 // for an explanation. TODO(jongerrish): Make Robolectric use a more realistic resource merging 45 // scheme. 46 if (attributeResource == null && !"android".equals(resName.packageName) && !"android".equals(packageName)) { 47 attributeResource = items.get(resName.withPackageName(packageName)); 48 if (attributeResource != null && !"android".equals(attributeResource.contextPackageName)) { 49 attributeResource = new AttributeResource(resName, attributeResource.value, resName.packageName); 50 } 51 } 52 53 return attributeResource; 54 } 55 grep(Pattern pattern)56 public boolean grep(Pattern pattern) { 57 for (ResName resName : items.keySet()) { 58 if (pattern.matcher(resName.getFullyQualifiedName()).find()) { 59 return true; 60 } 61 } 62 return false; 63 } 64 visit(Visitor visitor)65 public void visit(Visitor visitor) { 66 for (AttributeResource attributeResource : items.values()) { 67 visitor.visit(attributeResource); 68 } 69 } 70 71 public interface Visitor { visit(AttributeResource attributeResource)72 void visit(AttributeResource attributeResource); 73 } 74 75 @Override equals(Object obj)76 public boolean equals(Object obj) { 77 if (!(obj instanceof StyleData)) { 78 return false; 79 } 80 StyleData other = (StyleData) obj; 81 82 return Objects.equals(packageName, other.packageName) 83 && Objects.equals(name, other.name) 84 && Objects.equals(parent, other.parent) 85 && items.size() == other.items.size(); 86 } 87 88 @Override hashCode()89 public int hashCode() { 90 int hashCode = 0; 91 hashCode = 31 * hashCode + Strings.nullToEmpty(packageName).hashCode(); 92 hashCode = 31 * hashCode + Strings.nullToEmpty(name).hashCode(); 93 hashCode = 31 * hashCode + Strings.nullToEmpty(parent).hashCode(); 94 hashCode = 31 * hashCode + items.size(); 95 return hashCode; 96 } 97 toString()98 @Override public String toString() { 99 return "Style " + packageName + ":" + name; 100 } 101 getPackageName()102 public String getPackageName() { 103 return packageName; 104 } 105 } 106