1package org.robolectric.res; 2 3import java.util.regex.Matcher; 4import java.util.regex.Pattern; 5import org.robolectric.res.android.ConfigDescription; 6import 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 */ 11public 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 24 public static Qualifiers parse(String qualifiers) { 25 return parse(qualifiers, true); 26 } 27 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 } 34 35 return new Qualifiers(qualifiers, config); 36 } 37 38 protected Qualifiers(String qualifiers, ResTable_config config) { 39 this.qualifiers = qualifiers; 40 this.config = config; 41 } 42 43 public ResTable_config getConfig() { 44 return config; 45 } 46 47 @Override 48 public String toString() { 49 return qualifiers; 50 } 51 52 public static Qualifiers fromParentDir(FsFile parentDir) { 53 if (parentDir == null) { 54 return parse(""); 55 } else { 56 String parentDirName = parentDir.getName(); 57 Matcher matcher = DIR_QUALIFIER_PATTERN.matcher(parentDirName); 58 if (!matcher.find()) throw new IllegalStateException(parentDirName); 59 String qualifiers = matcher.group(1); 60 return parse(qualifiers != null ? qualifiers : ""); 61 } 62 } 63 64 /** 65 * @deprecated Use {@link android.os.Build.VERSION#SDK_INT} instead. 66 */ 67 @Deprecated 68 public static int getPlatformVersion(String qualifiers) { 69 Matcher m = VERSION_QUALIFIER_PATTERN.matcher(qualifiers); 70 if (m.find()) { 71 return Integer.parseInt(m.group(2)); 72 } 73 return -1; 74 } 75 76 /** 77 * @deprecated Use {@link android.content.res.Configuration#smallestScreenWidthDp} instead. 78 */ 79 @Deprecated 80 public static int getSmallestScreenWidth(String qualifiers) { 81 for (String qualifier : qualifiers.split("-")) { 82 Matcher matcher = SMALLEST_SCREEN_WIDTH_PATTERN.matcher(qualifier); 83 if (matcher.find()) { 84 return Integer.parseInt(matcher.group(1)); 85 } 86 } 87 88 return -1; 89 } 90 91 /** 92 * If the Config already has a version qualifier, do nothing. Otherwise, add a version 93 * qualifier for the target api level (which comes from the manifest or Config.sdk()). 94 * 95 * @deprecated Figure something else out. 96 */ 97 @Deprecated 98 public static String addPlatformVersion(String qualifiers, int apiLevel) { 99 int versionQualifierApiLevel = Qualifiers.getPlatformVersion(qualifiers); 100 if (versionQualifierApiLevel == -1) { 101 if (qualifiers.length() > 0) { 102 qualifiers += "-"; 103 } 104 qualifiers += "v" + apiLevel; 105 } 106 return qualifiers; 107 } 108 109 /** 110 * If the Config already has a `sw` qualifier, do nothing. Otherwise, add a `sw` 111 * qualifier for the given width. 112 * 113 * @deprecated Use {@link android.content.res.Configuration#smallestScreenWidthDp} instead. 114 */ 115 @Deprecated 116 public static String addSmallestScreenWidth(String qualifiers, int smallestScreenWidth) { 117 int qualifiersSmallestScreenWidth = Qualifiers.getSmallestScreenWidth(qualifiers); 118 if (qualifiersSmallestScreenWidth == -1) { 119 if (qualifiers.length() > 0) { 120 qualifiers += "-"; 121 } 122 qualifiers += "sw" + smallestScreenWidth + "dp"; 123 } 124 return qualifiers; 125 } 126 127 /** 128 * @deprecated Use {@link android.content.res.Configuration#screenWidthDp} instead. 129 */ 130 @Deprecated 131 public static int getScreenWidth(String qualifiers) { 132 for (String qualifier : qualifiers.split("-")) { 133 Matcher matcher = SCREEN_WIDTH_PATTERN.matcher(qualifier); 134 if (matcher.find()) { 135 return Integer.parseInt(matcher.group(1)); 136 } 137 } 138 139 return -1; 140 } 141 142 /** 143 * @deprecated Use {@link android.content.res.Configuration#screenWidthDp} instead. 144 */ 145 @Deprecated 146 public static String addScreenWidth(String qualifiers, int screenWidth) { 147 int qualifiersScreenWidth = Qualifiers.getScreenWidth(qualifiers); 148 if (qualifiersScreenWidth == -1) { 149 if (qualifiers.length() > 0) { 150 qualifiers += "-"; 151 } 152 qualifiers += "w" + screenWidth + "dp"; 153 } 154 return qualifiers; 155 } 156 157 /** 158 * @deprecated Use {@link android.content.res.Configuration#orientation} instead. 159 */ 160 @Deprecated 161 public static String getOrientation(String qualifiers) { 162 for (String qualifier : qualifiers.split("-")) { 163 Matcher matcher = ORIENTATION_QUALIFIER_PATTERN.matcher(qualifier); 164 if (matcher.find()) { 165 return matcher.group(1); 166 } 167 } 168 return null; 169 } 170} 171