1 package org.robolectric.res; 2 3 import java.util.regex.Matcher; 4 import java.util.regex.Pattern; 5 import org.robolectric.res.android.ConfigDescription; 6 import org.robolectric.res.android.ResTable_config; 7 8 /** 9 * Android qualifers as defined by https://developer.android.com/guide/topics/resources/providing-resources.html 10 */ 11 public class Qualifiers { 12 private static final Pattern DIR_QUALIFIER_PATTERN = Pattern.compile("^[^-]+(?:-(.*))?$"); 13 14 // Matches a version qualifier like "v14". Parentheses capture the numeric 15 // part for easy retrieval with Matcher.group(2). 16 private static final Pattern SCREEN_WIDTH_PATTERN = Pattern.compile("^w([0-9]+)dp"); 17 private static final Pattern SMALLEST_SCREEN_WIDTH_PATTERN = Pattern.compile("^sw([0-9]+)dp"); 18 private static final Pattern VERSION_QUALIFIER_PATTERN = Pattern.compile("(v)([0-9]+)$"); 19 private static final Pattern ORIENTATION_QUALIFIER_PATTERN = Pattern.compile("(land|port)"); 20 21 private final String qualifiers; 22 private final ResTable_config config; 23 parse(String qualifiers)24 public static Qualifiers parse(String qualifiers) { 25 return parse(qualifiers, true); 26 } 27 parse(String qualifiers, boolean applyVersionForCompat)28 public static Qualifiers parse(String qualifiers, boolean applyVersionForCompat) { 29 final ResTable_config config = new ResTable_config(); 30 if (!qualifiers.isEmpty() 31 && !ConfigDescription.parse(qualifiers, config, applyVersionForCompat)) { 32 throw new IllegalArgumentException("failed to parse qualifiers '" + qualifiers + "'." 33 + " See https://developer.android.com/guide/topics/resources/providing-resources.html#QualifierRules for expected format."); 34 } 35 36 return new Qualifiers(qualifiers, config); 37 } 38 Qualifiers(String qualifiers, ResTable_config config)39 protected Qualifiers(String qualifiers, ResTable_config config) { 40 this.qualifiers = qualifiers; 41 this.config = config; 42 } 43 getConfig()44 public ResTable_config getConfig() { 45 return config; 46 } 47 48 @Override toString()49 public String toString() { 50 return qualifiers; 51 } 52 fromParentDir(FsFile parentDir)53 public static Qualifiers fromParentDir(FsFile parentDir) { 54 if (parentDir == null) { 55 return parse(""); 56 } else { 57 String parentDirName = parentDir.getName(); 58 Matcher matcher = DIR_QUALIFIER_PATTERN.matcher(parentDirName); 59 if (!matcher.find()) throw new IllegalStateException(parentDirName); 60 String qualifiers = matcher.group(1); 61 return parse(qualifiers != null ? qualifiers : ""); 62 } 63 } 64 65 /** 66 * @deprecated Use {@link android.os.Build.VERSION#SDK_INT} instead. 67 */ 68 @Deprecated getPlatformVersion(String qualifiers)69 public static int getPlatformVersion(String qualifiers) { 70 Matcher m = VERSION_QUALIFIER_PATTERN.matcher(qualifiers); 71 if (m.find()) { 72 return Integer.parseInt(m.group(2)); 73 } 74 return -1; 75 } 76 77 /** 78 * @deprecated Use {@link android.content.res.Configuration#smallestScreenWidthDp} instead. 79 */ 80 @Deprecated getSmallestScreenWidth(String qualifiers)81 public static int getSmallestScreenWidth(String qualifiers) { 82 for (String qualifier : qualifiers.split("-", 0)) { 83 Matcher matcher = SMALLEST_SCREEN_WIDTH_PATTERN.matcher(qualifier); 84 if (matcher.find()) { 85 return Integer.parseInt(matcher.group(1)); 86 } 87 } 88 89 return -1; 90 } 91 92 /** 93 * If the Config already has a version qualifier, do nothing. Otherwise, add a version 94 * qualifier for the target api level (which comes from the manifest or Config.sdk()). 95 * 96 * @deprecated Figure something else out. 97 */ 98 @Deprecated addPlatformVersion(String qualifiers, int apiLevel)99 public static String addPlatformVersion(String qualifiers, int apiLevel) { 100 int versionQualifierApiLevel = Qualifiers.getPlatformVersion(qualifiers); 101 if (versionQualifierApiLevel == -1) { 102 if (qualifiers.length() > 0) { 103 qualifiers += "-"; 104 } 105 qualifiers += "v" + apiLevel; 106 } 107 return qualifiers; 108 } 109 110 /** 111 * If the Config already has a `sw` qualifier, do nothing. Otherwise, add a `sw` 112 * qualifier for the given width. 113 * 114 * @deprecated Use {@link android.content.res.Configuration#smallestScreenWidthDp} instead. 115 */ 116 @Deprecated addSmallestScreenWidth(String qualifiers, int smallestScreenWidth)117 public static String addSmallestScreenWidth(String qualifiers, int smallestScreenWidth) { 118 int qualifiersSmallestScreenWidth = Qualifiers.getSmallestScreenWidth(qualifiers); 119 if (qualifiersSmallestScreenWidth == -1) { 120 if (qualifiers.length() > 0) { 121 qualifiers += "-"; 122 } 123 qualifiers += "sw" + smallestScreenWidth + "dp"; 124 } 125 return qualifiers; 126 } 127 128 /** 129 * @deprecated Use {@link android.content.res.Configuration#screenWidthDp} instead. 130 */ 131 @Deprecated getScreenWidth(String qualifiers)132 public static int getScreenWidth(String qualifiers) { 133 for (String qualifier : qualifiers.split("-", 0)) { 134 Matcher matcher = SCREEN_WIDTH_PATTERN.matcher(qualifier); 135 if (matcher.find()) { 136 return Integer.parseInt(matcher.group(1)); 137 } 138 } 139 140 return -1; 141 } 142 143 /** 144 * @deprecated Use {@link android.content.res.Configuration#screenWidthDp} instead. 145 */ 146 @Deprecated addScreenWidth(String qualifiers, int screenWidth)147 public static String addScreenWidth(String qualifiers, int screenWidth) { 148 int qualifiersScreenWidth = Qualifiers.getScreenWidth(qualifiers); 149 if (qualifiersScreenWidth == -1) { 150 if (qualifiers.length() > 0) { 151 qualifiers += "-"; 152 } 153 qualifiers += "w" + screenWidth + "dp"; 154 } 155 return qualifiers; 156 } 157 158 /** 159 * @deprecated Use {@link android.content.res.Configuration#orientation} instead. 160 */ 161 @Deprecated getOrientation(String qualifiers)162 public static String getOrientation(String qualifiers) { 163 for (String qualifier : qualifiers.split("-", 0)) { 164 Matcher matcher = ORIENTATION_QUALIFIER_PATTERN.matcher(qualifier); 165 if (matcher.find()) { 166 return matcher.group(1); 167 } 168 } 169 return null; 170 } 171 } 172