Home | History | Annotate | Download | only in res
      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 public class ResName {
      9   public static final String ID_TYPE = "id";
     10 
     11   private static final Pattern FQN_PATTERN = Pattern.compile("^([^:]*):([^/]+)/(.+)$");
     12   private static final int NAMESPACE = 1;
     13   private static final int TYPE = 2;
     14   private static final int NAME = 3;
     15 
     16   public final @Nonnull String packageName;
     17   public final @Nonnull String type;
     18   public final @Nonnull String name;
     19 
     20   public final int hashCode;
     21 
     22   public ResName(@Nonnull String packageName, @Nonnull String type, @Nonnull String name) {
     23     this.packageName = packageName;
     24     this.type = type.trim();
     25     this.name = name.trim();
     26 
     27     hashCode = computeHashCode();
     28   }
     29 
     30   public ResName(@Nonnull String fullyQualifiedName) {
     31     Matcher matcher = FQN_PATTERN.matcher(fullyQualifiedName.trim());
     32     if (!matcher.find()) {
     33       throw new IllegalStateException("\"" + fullyQualifiedName + "\" is not fully qualified");
     34     }
     35     packageName = matcher.group(NAMESPACE);
     36     type = matcher.group(TYPE).trim();
     37     name = matcher.group(NAME).trim();
     38 
     39     hashCode = computeHashCode();
     40     if (packageName.equals("xmlns")) throw new IllegalStateException("\"" + fullyQualifiedName + "\" unexpected");
     41   }
     42 
     43   /**
     44    * @return null if the resource could not be qualified.
     45    */
     46   public static String qualifyResourceName(@Nonnull String possiblyQualifiedResourceName, String defaultPackageName, String defaultType) {
     47     ResName resName = qualifyResName(possiblyQualifiedResourceName, defaultPackageName, defaultType);
     48     return resName != null ? resName.getFullyQualifiedName() : null;
     49   }
     50 
     51   public static ResName qualifyResName(@Nonnull String possiblyQualifiedResourceName, ResName defaults) {
     52     return qualifyResName(possiblyQualifiedResourceName, defaults.packageName, defaults.type);
     53   }
     54 
     55   public static ResName qualifyResName(@Nonnull String possiblyQualifiedResourceName, String defaultPackageName, String defaultType) {
     56     int indexOfColon = possiblyQualifiedResourceName.indexOf(':');
     57     int indexOfSlash = possiblyQualifiedResourceName.indexOf('/');
     58     String type = null;
     59     String packageName = null;
     60     String name = possiblyQualifiedResourceName;
     61     if (indexOfColon > indexOfSlash) {
     62       if (indexOfSlash > 0) {
     63         type = possiblyQualifiedResourceName.substring(0, indexOfSlash);
     64       }
     65       packageName = possiblyQualifiedResourceName.substring(indexOfSlash + 1, indexOfColon);
     66       name =  possiblyQualifiedResourceName.substring(indexOfColon + 1);
     67     } else if (indexOfSlash > indexOfColon) {
     68       if (indexOfColon > 0) {
     69         packageName = possiblyQualifiedResourceName.substring(0, indexOfColon);
     70       }
     71       type = possiblyQualifiedResourceName.substring(indexOfColon + 1, indexOfSlash);
     72       name = possiblyQualifiedResourceName.substring(indexOfSlash + 1);
     73     }
     74 
     75     if ((type == null && defaultType == null) || (packageName == null && defaultPackageName == null)) {
     76       return null;
     77     }
     78 
     79     if (packageName == null) {
     80       packageName = defaultPackageName;
     81     } else if ("*android".equals(packageName)) {
     82       packageName = "android";
     83     }
     84 
     85     return new ResName(
     86         packageName,
     87         type == null ? defaultType : type,
     88         name);
     89   }
     90 
     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 
    109   public static ResName qualifyFromFilePath(@Nonnull final String packageName, @Nonnull final String filePath) {
    110     final FileFsFile filePathFile = new FileFsFile(new File(filePath));
    111     final String type = filePathFile.getParent().getName().split("-", 0)[0];
    112     final String name = filePathFile.getBaseName();
    113 
    114     return new ResName(packageName, type, name);
    115   }
    116 
    117   @Override
    118   public boolean equals(Object o) {
    119     if (this == o) return true;
    120     if (o == null || getClass() != o.getClass()) 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
    134   public int hashCode() {
    135     return hashCode;
    136   }
    137 
    138   @Override
    139   public String toString() {
    140     return "ResName{" + getFullyQualifiedName() + "}";
    141   }
    142 
    143   public String getFullyQualifiedName() {
    144     return packageName + ":" + type + "/" + name;
    145   }
    146 
    147   public String getNamespaceUri() {
    148     return "http://schemas.android.com/apk/res/" + packageName;
    149   }
    150 
    151   public ResName withPackageName(String packageName) {
    152     if (packageName.equals(this.packageName)) return this;
    153     return new ResName(packageName, type, name);
    154   }
    155 
    156   public void mustBe(String expectedType) {
    157     if (!type.equals(expectedType)) {
    158       throw new RuntimeException("expected " + getFullyQualifiedName() + " to be a " + expectedType + ", is a " + type);
    159     }
    160   }
    161 
    162   private int computeHashCode() {
    163     int result = packageName.hashCode();
    164     result = 31 * result + type.hashCode();
    165     result = 31 * result + name.hashCode();
    166     return result;
    167   }
    168 }
    169