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     }
34 
35     return new Qualifiers(qualifiers, config);
36   }
37 
Qualifiers(String qualifiers, ResTable_config config)38   protected Qualifiers(String qualifiers, ResTable_config config) {
39     this.qualifiers = qualifiers;
40     this.config = config;
41   }
42 
getConfig()43   public ResTable_config getConfig() {
44     return config;
45   }
46 
47   @Override
toString()48   public String toString() {
49     return qualifiers;
50   }
51 
fromParentDir(FsFile parentDir)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
getPlatformVersion(String qualifiers)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
getSmallestScreenWidth(String qualifiers)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
addPlatformVersion(String qualifiers, int apiLevel)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
addSmallestScreenWidth(String qualifiers, int smallestScreenWidth)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
getScreenWidth(String qualifiers)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
addScreenWidth(String qualifiers, int screenWidth)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
getOrientation(String qualifiers)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