• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.robolectric.res;
2 
3 import java.io.File;
4 import java.util.regex.Matcher;
5 import java.util.regex.Pattern;
6 import javax.annotation.Nonnull;
7 
8 @SuppressWarnings("NewApi")
9 public class ResName {
10   public static final String ID_TYPE = "id";
11 
12   private static final Pattern FQN_PATTERN = Pattern.compile("^([^:]*):([^/]+)/(.+)$");
13   private static final int NAMESPACE = 1;
14   private static final int TYPE = 2;
15   private static final int NAME = 3;
16 
17   public final @Nonnull String packageName;
18   public final @Nonnull String type;
19   public final @Nonnull String name;
20 
21   public final int hashCode;
22 
ResName(@onnull String packageName, @Nonnull String type, @Nonnull String name)23   public ResName(@Nonnull String packageName, @Nonnull String type, @Nonnull String name) {
24     this.packageName = packageName;
25     this.type = type.trim();
26     this.name = name.trim();
27 
28     hashCode = computeHashCode();
29   }
30 
ResName(@onnull String fullyQualifiedName)31   public ResName(@Nonnull String fullyQualifiedName) {
32     Matcher matcher = FQN_PATTERN.matcher(fullyQualifiedName.trim());
33     if (!matcher.find()) {
34       throw new IllegalStateException("\"" + fullyQualifiedName + "\" is not fully qualified");
35     }
36     packageName = matcher.group(NAMESPACE);
37     type = matcher.group(TYPE).trim();
38     name = matcher.group(NAME).trim();
39 
40     hashCode = computeHashCode();
41     if (packageName.equals("xmlns"))
42       throw new IllegalStateException("\"" + fullyQualifiedName + "\" unexpected");
43   }
44 
45   /** Returns the fully qualified resource name if null if the resource could not be qualified. */
qualifyResourceName( @onnull String possiblyQualifiedResourceName, String defaultPackageName, String defaultType)46   public static String qualifyResourceName(
47       @Nonnull String possiblyQualifiedResourceName,
48       String defaultPackageName,
49       String defaultType) {
50     ResName resName = qualifyResName(possiblyQualifiedResourceName, defaultPackageName, defaultType);
51     return resName != null ? resName.getFullyQualifiedName() : null;
52   }
53 
qualifyResName(@onnull String possiblyQualifiedResourceName, ResName defaults)54   public static ResName qualifyResName(@Nonnull String possiblyQualifiedResourceName, ResName defaults) {
55     return qualifyResName(possiblyQualifiedResourceName, defaults.packageName, defaults.type);
56   }
57 
qualifyResName(@onnull String possiblyQualifiedResourceName, String defaultPackageName, String defaultType)58   public static ResName qualifyResName(@Nonnull String possiblyQualifiedResourceName, String defaultPackageName, String defaultType) {
59     int indexOfColon = possiblyQualifiedResourceName.indexOf(':');
60     int indexOfSlash = possiblyQualifiedResourceName.indexOf('/');
61     String type = null;
62     String packageName = null;
63     String name = possiblyQualifiedResourceName;
64     if (indexOfColon > indexOfSlash) {
65       if (indexOfSlash > 0) {
66         type = possiblyQualifiedResourceName.substring(0, indexOfSlash);
67       }
68       packageName = possiblyQualifiedResourceName.substring(indexOfSlash + 1, indexOfColon);
69       name =  possiblyQualifiedResourceName.substring(indexOfColon + 1);
70     } else if (indexOfSlash > indexOfColon) {
71       if (indexOfColon > 0) {
72         packageName = possiblyQualifiedResourceName.substring(0, indexOfColon);
73       }
74       type = possiblyQualifiedResourceName.substring(indexOfColon + 1, indexOfSlash);
75       name = possiblyQualifiedResourceName.substring(indexOfSlash + 1);
76     }
77 
78     if ((type == null && defaultType == null) || (packageName == null && defaultPackageName == null)) {
79       return null;
80     }
81 
82     if (packageName == null) {
83       packageName = defaultPackageName;
84     } else if ("*android".equals(packageName)) {
85       packageName = "android";
86     }
87 
88     return new ResName(packageName, type == null ? defaultType : type, name);
89   }
90 
qualifyResName(String possiblyQualifiedResourceName, String contextPackageName)91   public static String qualifyResName(String possiblyQualifiedResourceName, String contextPackageName) {
92     if (possiblyQualifiedResourceName == null) {
93       return null;
94     }
95 
96     if (AttributeResource.isNull(possiblyQualifiedResourceName)) {
97       return null;
98     }
99 
100     // Was not able to fully qualify the resource name
101     String fullyQualifiedResourceName = qualifyResourceName(possiblyQualifiedResourceName, contextPackageName, null);
102     if (fullyQualifiedResourceName == null) {
103       return null;
104     }
105 
106     return fullyQualifiedResourceName.replaceAll("[@+]", "");
107   }
108 
qualifyFromFilePath(@onnull final String packageName, @Nonnull final String filePath)109   public static ResName qualifyFromFilePath(@Nonnull final String packageName, @Nonnull final String filePath) {
110     final File file = new File(filePath);
111     final String type = file.getParentFile().getName().split("-", 0)[0];
112     final String name = Fs.baseNameFor(file.toPath());
113 
114     return new ResName(packageName, type, name);
115   }
116 
117   @Override
equals(Object o)118   public boolean equals(Object o) {
119     if (this == o) return true;
120     if (!(o instanceof ResName)) return false;
121 
122     ResName resName = (ResName) o;
123 
124     if (hashCode() != resName.hashCode()) return false;
125 
126     if (!packageName.equals(resName.packageName)) return false;
127     if (!type.equals(resName.type)) return false;
128     if (!name.equals(resName.name)) return false;
129 
130     return true;
131   }
132 
133   @Override
hashCode()134   public int hashCode() {
135     return hashCode;
136   }
137 
138   @Override
toString()139   public String toString() {
140     return "ResName{" + getFullyQualifiedName() + "}";
141   }
142 
getFullyQualifiedName()143   public String getFullyQualifiedName() {
144     return packageName + ":" + type + "/" + name;
145   }
146 
getNamespaceUri()147   public String getNamespaceUri() {
148     return "http://schemas.android.com/apk/res/" + packageName;
149   }
150 
withPackageName(String packageName)151   public ResName withPackageName(String packageName) {
152     if (packageName.equals(this.packageName)) return this;
153     return new ResName(packageName, type, name);
154   }
155 
mustBe(String expectedType)156   public void mustBe(String expectedType) {
157     if (!type.equals(expectedType)) {
158       throw new RuntimeException(
159           "expected " + getFullyQualifiedName() + " to be a " + expectedType + ", is a " + type);
160     }
161   }
162 
computeHashCode()163   private int computeHashCode() {
164     int result = packageName.hashCode();
165     result = 31 * result + type.hashCode();
166     result = 31 * result + name.hashCode();
167     return result;
168   }
169 }
170