aboutsummaryrefslogtreecommitdiff
path: root/resources/src/main/java/org/robolectric/res/ResName.java
blob: 42ce2b5c1238c8943fc94bb6f3b7f1c66d07235f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
package org.robolectric.res;

import java.io.File;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Nonnull;

public class ResName {
  public static final String ID_TYPE = "id";

  private static final Pattern FQN_PATTERN = Pattern.compile("^([^:]*):([^/]+)/(.+)$");
  private static final int NAMESPACE = 1;
  private static final int TYPE = 2;
  private static final int NAME = 3;

  public final @Nonnull String packageName;
  public final @Nonnull String type;
  public final @Nonnull String name;

  public final int hashCode;

  public ResName(@Nonnull String packageName, @Nonnull String type, @Nonnull String name) {
    this.packageName = packageName;
    this.type = type.trim();
    this.name = name.indexOf('.') != -1 ? name.replace('.', '_').trim() : name.trim();

    hashCode = computeHashCode();
  }

  public ResName(@Nonnull String fullyQualifiedName) {
    Matcher matcher = FQN_PATTERN.matcher(fullyQualifiedName.trim());
    if (!matcher.find()) {
      throw new IllegalStateException("\"" + fullyQualifiedName + "\" is not fully qualified");
    }
    packageName = matcher.group(NAMESPACE);
    type = matcher.group(TYPE).trim();
    String nameStr = matcher.group(NAME);
    name = nameStr.indexOf('.') != -1 ? nameStr.replace('.', '_') : nameStr;

    hashCode = computeHashCode();
    if (packageName.equals("xmlns")) throw new IllegalStateException("\"" + fullyQualifiedName + "\" unexpected");
  }

  /**
   * @return null if the resource could not be qualified.
   */
  public static String qualifyResourceName(@Nonnull String possiblyQualifiedResourceName, String defaultPackageName, String defaultType) {
    ResName resName = qualifyResName(possiblyQualifiedResourceName, defaultPackageName, defaultType);
    return resName != null ? resName.getFullyQualifiedName() : null;
  }

  public static ResName qualifyResName(@Nonnull String possiblyQualifiedResourceName, ResName defaults) {
    return qualifyResName(possiblyQualifiedResourceName, defaults.packageName, defaults.type);
  }

  public static ResName qualifyResName(@Nonnull String possiblyQualifiedResourceName, String defaultPackageName, String defaultType) {
    int indexOfColon = possiblyQualifiedResourceName.indexOf(':');
    int indexOfSlash = possiblyQualifiedResourceName.indexOf('/');
    String type = null;
    String packageName = null;
    String name = possiblyQualifiedResourceName;
    if (indexOfColon > indexOfSlash) {
      if (indexOfSlash > 0) {
        type = possiblyQualifiedResourceName.substring(0, indexOfSlash);
      }
      packageName = possiblyQualifiedResourceName.substring(indexOfSlash + 1, indexOfColon);
      name =  possiblyQualifiedResourceName.substring(indexOfColon + 1);
    } else if (indexOfSlash > indexOfColon) {
      if (indexOfColon > 0) {
        packageName = possiblyQualifiedResourceName.substring(0, indexOfColon);
      }
      type = possiblyQualifiedResourceName.substring(indexOfColon + 1, indexOfSlash);
      name = possiblyQualifiedResourceName.substring(indexOfSlash + 1);
    }

    if ((type == null && defaultType == null) || (packageName == null && defaultPackageName == null)) {
      return null;
    }

    if (packageName == null) {
      packageName = defaultPackageName;
    } else if ("*android".equals(packageName)) {
      packageName = "android";
    }

    return new ResName(
        packageName,
        type == null ? defaultType : type,
        name);
  }

  public static String qualifyResName(String possiblyQualifiedResourceName, String contextPackageName) {
    if (possiblyQualifiedResourceName == null) {
      return null;
    }

    if (AttributeResource.isNull(possiblyQualifiedResourceName)) {
      return null;
    }

    // Was not able to fully qualify the resource name
    String fullyQualifiedResourceName = qualifyResourceName(possiblyQualifiedResourceName, contextPackageName, null);
    if (fullyQualifiedResourceName == null) {
      return null;
    }

    return fullyQualifiedResourceName.replaceAll("[@+]", "");
  }

  public static ResName qualifyFromFilePath(@Nonnull final String packageName, @Nonnull final String filePath) {
    final FileFsFile filePathFile = new FileFsFile(new File(filePath));
    final String type = filePathFile.getParent().getName().split("-")[0];
    final String name = filePathFile.getBaseName();

    return new ResName(packageName, type, name);
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    ResName resName = (ResName) o;

    if (hashCode() != resName.hashCode()) return false;

    if (!packageName.equals(resName.packageName)) return false;
    if (!type.equals(resName.type)) return false;
    if (!name.equals(resName.name)) return false;

    return true;
  }

  @Override
  public int hashCode() {
    return hashCode;
  }

  @Override
  public String toString() {
    return "ResName{" + getFullyQualifiedName() + "}";
  }

  public String getFullyQualifiedName() {
    return packageName + ":" + type + "/" + name;
  }

  public String getNamespaceUri() {
    return "http://schemas.android.com/apk/res/" + packageName;
  }

  public ResName withPackageName(String packageName) {
    if (packageName.equals(this.packageName)) return this;
    return new ResName(packageName, type, name);
  }

  public void mustBe(String expectedType) {
    if (!type.equals(expectedType)) {
      throw new RuntimeException("expected " + getFullyQualifiedName() + " to be a " + expectedType + ", is a " + type);
    }
  }

  private int computeHashCode() {
    int result = packageName.hashCode();
    result = 31 * result + type.hashCode();
    result = 31 * result + name.hashCode();
    return result;
  }
}