• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Eclipse Public License, Version 1.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.eclipse.org/org/documents/epl-v10.php
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.ide.eclipse.adt.internal.resources.configurations;
18 
19 import com.android.ide.eclipse.adt.internal.resources.manager.ResourceFolderType;
20 import com.android.ide.eclipse.adt.internal.sdk.Sdk;
21 import com.android.sdklib.IAndroidTarget;
22 
23 import org.eclipse.core.resources.IProject;
24 
25 
26 /**
27  * Represents the configuration for Resource Folders. All the properties have a default
28  * value which means that the property is not set.
29  */
30 public final class FolderConfiguration implements Comparable<FolderConfiguration> {
31     public final static String QUALIFIER_SEP = "-"; //$NON-NLS-1$
32 
33     private final ResourceQualifier[] mQualifiers = new ResourceQualifier[INDEX_COUNT];
34 
35     private final static int INDEX_COUNTRY_CODE       = 0;
36     private final static int INDEX_NETWORK_CODE       = 1;
37     private final static int INDEX_LANGUAGE           = 2;
38     private final static int INDEX_REGION             = 3;
39     private final static int INDEX_SCREEN_SIZE        = 4;
40     private final static int INDEX_SCREEN_RATIO       = 5;
41     private final static int INDEX_SCREEN_ORIENTATION = 6;
42     private final static int INDEX_PIXEL_DENSITY      = 7;
43     private final static int INDEX_TOUCH_TYPE         = 8;
44     private final static int INDEX_KEYBOARD_STATE     = 9;
45     private final static int INDEX_TEXT_INPUT_METHOD  = 10;
46     private final static int INDEX_NAVIGATION_METHOD  = 11;
47     private final static int INDEX_SCREEN_DIMENSION   = 12;
48     private final static int INDEX_VERSION            = 13;
49     private final static int INDEX_COUNT              = 14;
50 
51     /**
52      * Returns the number of {@link ResourceQualifier} that make up a Folder configuration.
53      */
getQualifierCount()54     public static int getQualifierCount() {
55         return INDEX_COUNT;
56     }
57 
58     /**
59      * Sets the config from the qualifiers of a given <var>config</var>.
60      * @param config
61      */
set(FolderConfiguration config)62     public void set(FolderConfiguration config) {
63         if (config != null) {
64             for (int i = 0 ; i < INDEX_COUNT ; i++) {
65                 mQualifiers[i] = config.mQualifiers[i];
66             }
67         }
68     }
69 
70     /**
71      * Removes the qualifiers from the receiver if they are present (and valid)
72      * in the given configuration.
73      */
substract(FolderConfiguration config)74     public void substract(FolderConfiguration config) {
75         for (int i = 0 ; i < INDEX_COUNT ; i++) {
76             if (config.mQualifiers[i] != null && config.mQualifiers[i].isValid()) {
77                 mQualifiers[i] = null;
78             }
79         }
80     }
81 
82     /**
83      * Returns the first invalid qualifier, or <code>null<code> if they are all valid (or if none
84      * exists).
85      */
getInvalidQualifier()86     public ResourceQualifier getInvalidQualifier() {
87         for (int i = 0 ; i < INDEX_COUNT ; i++) {
88             if (mQualifiers[i] != null && mQualifiers[i].isValid() == false) {
89                 return mQualifiers[i];
90             }
91         }
92 
93         // all allocated qualifiers are valid, we return null.
94         return null;
95     }
96 
97     /**
98      * Returns whether the Region qualifier is valid. Region qualifier can only be present if a
99      * Language qualifier is present as well.
100      * @return true if the Region qualifier is valid.
101      */
checkRegion()102     public boolean checkRegion() {
103         if (mQualifiers[INDEX_LANGUAGE] == null && mQualifiers[INDEX_REGION] != null) {
104             return false;
105         }
106 
107         return true;
108     }
109 
110     /**
111      * Adds a qualifier to the {@link FolderConfiguration}
112      * @param qualifier the {@link ResourceQualifier} to add.
113      */
addQualifier(ResourceQualifier qualifier)114     public void addQualifier(ResourceQualifier qualifier) {
115         if (qualifier instanceof CountryCodeQualifier) {
116             mQualifiers[INDEX_COUNTRY_CODE] = qualifier;
117         } else if (qualifier instanceof NetworkCodeQualifier) {
118             mQualifiers[INDEX_NETWORK_CODE] = qualifier;
119         } else if (qualifier instanceof LanguageQualifier) {
120             mQualifiers[INDEX_LANGUAGE] = qualifier;
121         } else if (qualifier instanceof RegionQualifier) {
122             mQualifiers[INDEX_REGION] = qualifier;
123         } else if (qualifier instanceof ScreenSizeQualifier) {
124             mQualifiers[INDEX_SCREEN_SIZE] = qualifier;
125         } else if (qualifier instanceof ScreenRatioQualifier) {
126             mQualifiers[INDEX_SCREEN_RATIO] = qualifier;
127         } else if (qualifier instanceof ScreenOrientationQualifier) {
128             mQualifiers[INDEX_SCREEN_ORIENTATION] = qualifier;
129         } else if (qualifier instanceof PixelDensityQualifier) {
130             mQualifiers[INDEX_PIXEL_DENSITY] = qualifier;
131         } else if (qualifier instanceof TouchScreenQualifier) {
132             mQualifiers[INDEX_TOUCH_TYPE] = qualifier;
133         } else if (qualifier instanceof KeyboardStateQualifier) {
134             mQualifiers[INDEX_KEYBOARD_STATE] = qualifier;
135         } else if (qualifier instanceof TextInputMethodQualifier) {
136             mQualifiers[INDEX_TEXT_INPUT_METHOD] = qualifier;
137         } else if (qualifier instanceof NavigationMethodQualifier) {
138             mQualifiers[INDEX_NAVIGATION_METHOD] = qualifier;
139         } else if (qualifier instanceof ScreenDimensionQualifier) {
140             mQualifiers[INDEX_SCREEN_DIMENSION] = qualifier;
141         } else if (qualifier instanceof VersionQualifier) {
142             mQualifiers[INDEX_VERSION] = qualifier;
143         }
144     }
145 
146     /**
147      * Removes a given qualifier from the {@link FolderConfiguration}.
148      * @param qualifier the {@link ResourceQualifier} to remove.
149      */
removeQualifier(ResourceQualifier qualifier)150     public void removeQualifier(ResourceQualifier qualifier) {
151         for (int i = 0 ; i < INDEX_COUNT ; i++) {
152             if (mQualifiers[i] == qualifier) {
153                 mQualifiers[i] = null;
154                 return;
155             }
156         }
157     }
158 
159     /**
160      * Returns a qualifier by its index. The total number of qualifiers can be accessed by
161      * {@link #getQualifierCount()}.
162      * @param index the index of the qualifier to return.
163      * @return the qualifier or null if there are none at the index.
164      */
getQualifier(int index)165     public ResourceQualifier getQualifier(int index) {
166         return mQualifiers[index];
167     }
168 
setCountryCodeQualifier(CountryCodeQualifier qualifier)169     public void setCountryCodeQualifier(CountryCodeQualifier qualifier) {
170         mQualifiers[INDEX_COUNTRY_CODE] = qualifier;
171     }
172 
getCountryCodeQualifier()173     public CountryCodeQualifier getCountryCodeQualifier() {
174         return (CountryCodeQualifier)mQualifiers[INDEX_COUNTRY_CODE];
175     }
176 
setNetworkCodeQualifier(NetworkCodeQualifier qualifier)177     public void setNetworkCodeQualifier(NetworkCodeQualifier qualifier) {
178         mQualifiers[INDEX_NETWORK_CODE] = qualifier;
179     }
180 
getNetworkCodeQualifier()181     public NetworkCodeQualifier getNetworkCodeQualifier() {
182         return (NetworkCodeQualifier)mQualifiers[INDEX_NETWORK_CODE];
183     }
184 
setLanguageQualifier(LanguageQualifier qualifier)185     public void setLanguageQualifier(LanguageQualifier qualifier) {
186         mQualifiers[INDEX_LANGUAGE] = qualifier;
187     }
188 
getLanguageQualifier()189     public LanguageQualifier getLanguageQualifier() {
190         return (LanguageQualifier)mQualifiers[INDEX_LANGUAGE];
191     }
192 
setRegionQualifier(RegionQualifier qualifier)193     public void setRegionQualifier(RegionQualifier qualifier) {
194         mQualifiers[INDEX_REGION] = qualifier;
195     }
196 
getRegionQualifier()197     public RegionQualifier getRegionQualifier() {
198         return (RegionQualifier)mQualifiers[INDEX_REGION];
199     }
200 
setScreenSizeQualifier(ScreenSizeQualifier qualifier)201     public void setScreenSizeQualifier(ScreenSizeQualifier qualifier) {
202         mQualifiers[INDEX_SCREEN_SIZE] = qualifier;
203     }
204 
getScreenSizeQualifier()205     public ScreenSizeQualifier getScreenSizeQualifier() {
206         return (ScreenSizeQualifier)mQualifiers[INDEX_SCREEN_SIZE];
207     }
208 
setScreenRatioQualifier(ScreenRatioQualifier qualifier)209     public void setScreenRatioQualifier(ScreenRatioQualifier qualifier) {
210         mQualifiers[INDEX_SCREEN_RATIO] = qualifier;
211     }
212 
getScreenRatioQualifier()213     public ScreenRatioQualifier getScreenRatioQualifier() {
214         return (ScreenRatioQualifier)mQualifiers[INDEX_SCREEN_RATIO];
215     }
216 
setScreenOrientationQualifier(ScreenOrientationQualifier qualifier)217     public void setScreenOrientationQualifier(ScreenOrientationQualifier qualifier) {
218         mQualifiers[INDEX_SCREEN_ORIENTATION] = qualifier;
219     }
220 
getScreenOrientationQualifier()221     public ScreenOrientationQualifier getScreenOrientationQualifier() {
222         return (ScreenOrientationQualifier)mQualifiers[INDEX_SCREEN_ORIENTATION];
223     }
224 
setPixelDensityQualifier(PixelDensityQualifier qualifier)225     public void setPixelDensityQualifier(PixelDensityQualifier qualifier) {
226         mQualifiers[INDEX_PIXEL_DENSITY] = qualifier;
227     }
228 
getPixelDensityQualifier()229     public PixelDensityQualifier getPixelDensityQualifier() {
230         return (PixelDensityQualifier)mQualifiers[INDEX_PIXEL_DENSITY];
231     }
232 
setTouchTypeQualifier(TouchScreenQualifier qualifier)233     public void setTouchTypeQualifier(TouchScreenQualifier qualifier) {
234         mQualifiers[INDEX_TOUCH_TYPE] = qualifier;
235     }
236 
getTouchTypeQualifier()237     public TouchScreenQualifier getTouchTypeQualifier() {
238         return (TouchScreenQualifier)mQualifiers[INDEX_TOUCH_TYPE];
239     }
240 
setKeyboardStateQualifier(KeyboardStateQualifier qualifier)241     public void setKeyboardStateQualifier(KeyboardStateQualifier qualifier) {
242         mQualifiers[INDEX_KEYBOARD_STATE] = qualifier;
243     }
244 
getKeyboardStateQualifier()245     public KeyboardStateQualifier getKeyboardStateQualifier() {
246         return (KeyboardStateQualifier)mQualifiers[INDEX_KEYBOARD_STATE];
247     }
248 
setTextInputMethodQualifier(TextInputMethodQualifier qualifier)249     public void setTextInputMethodQualifier(TextInputMethodQualifier qualifier) {
250         mQualifiers[INDEX_TEXT_INPUT_METHOD] = qualifier;
251     }
252 
getTextInputMethodQualifier()253     public TextInputMethodQualifier getTextInputMethodQualifier() {
254         return (TextInputMethodQualifier)mQualifiers[INDEX_TEXT_INPUT_METHOD];
255     }
256 
setNavigationMethodQualifier(NavigationMethodQualifier qualifier)257     public void setNavigationMethodQualifier(NavigationMethodQualifier qualifier) {
258         mQualifiers[INDEX_NAVIGATION_METHOD] = qualifier;
259     }
260 
getNavigationMethodQualifier()261     public NavigationMethodQualifier getNavigationMethodQualifier() {
262         return (NavigationMethodQualifier)mQualifiers[INDEX_NAVIGATION_METHOD];
263     }
264 
setScreenDimensionQualifier(ScreenDimensionQualifier qualifier)265     public void setScreenDimensionQualifier(ScreenDimensionQualifier qualifier) {
266         mQualifiers[INDEX_SCREEN_DIMENSION] = qualifier;
267     }
268 
getScreenDimensionQualifier()269     public ScreenDimensionQualifier getScreenDimensionQualifier() {
270         return (ScreenDimensionQualifier)mQualifiers[INDEX_SCREEN_DIMENSION];
271     }
272 
setVersionQualifier(VersionQualifier qualifier)273     public void setVersionQualifier(VersionQualifier qualifier) {
274         mQualifiers[INDEX_VERSION] = qualifier;
275     }
276 
getVersionQualifier()277     public VersionQualifier getVersionQualifier() {
278         return (VersionQualifier)mQualifiers[INDEX_VERSION];
279     }
280 
281     /**
282      * Returns whether an object is equals to the receiver.
283      */
284     @Override
equals(Object obj)285     public boolean equals(Object obj) {
286         if (obj == this) {
287             return true;
288         }
289 
290         if (obj instanceof FolderConfiguration) {
291             FolderConfiguration fc = (FolderConfiguration)obj;
292             for (int i = 0 ; i < INDEX_COUNT ; i++) {
293                 ResourceQualifier qualifier = mQualifiers[i];
294                 ResourceQualifier fcQualifier = fc.mQualifiers[i];
295                 if (qualifier != null) {
296                     if (qualifier.equals(fcQualifier) == false) {
297                         return false;
298                     }
299                 } else if (fcQualifier != null) {
300                     return false;
301                 }
302             }
303 
304             return true;
305         }
306 
307         return false;
308     }
309 
310     @Override
hashCode()311     public int hashCode() {
312         return toString().hashCode();
313     }
314 
315     /**
316      * Returns whether the Configuration has only default values.
317      */
isDefault()318     public boolean isDefault() {
319         for (ResourceQualifier irq : mQualifiers) {
320             if (irq != null) {
321                 return false;
322             }
323         }
324 
325         return true;
326     }
327 
328     /**
329      * Returns the name of a folder with the configuration.
330      */
getFolderName(ResourceFolderType folder, IAndroidTarget target)331     public String getFolderName(ResourceFolderType folder, IAndroidTarget target) {
332         StringBuilder result = new StringBuilder(folder.getName());
333 
334         for (ResourceQualifier qualifier : mQualifiers) {
335             if (qualifier != null) {
336                 String segment = qualifier.getFolderSegment(target);
337                 if (segment != null && segment.length() > 0) {
338                     result.append(QUALIFIER_SEP);
339                     result.append(segment);
340                 }
341             }
342         }
343 
344         return result.toString();
345     }
346 
347     /**
348      * Returns the name of a folder with the configuration.
349      */
getFolderName(ResourceFolderType folder, IProject project)350     public String getFolderName(ResourceFolderType folder, IProject project) {
351         IAndroidTarget target = null;
352         if (project != null) {
353             Sdk currentSdk = Sdk.getCurrent();
354             if (currentSdk != null) {
355                 target = currentSdk.getTarget(project);
356             }
357         }
358 
359         return getFolderName(folder, target);
360     }
361 
362     /**
363      * Returns {@link #toDisplayString()}.
364      */
365     @Override
toString()366     public String toString() {
367         return toDisplayString();
368     }
369 
370     /**
371      * Returns a string valid for display purpose.
372      */
toDisplayString()373     public String toDisplayString() {
374         if (isDefault()) {
375             return "default";
376         }
377 
378         StringBuilder result = null;
379         int index = 0;
380         ResourceQualifier qualifier = null;
381 
382         // pre- language/region qualifiers
383         while (index < INDEX_LANGUAGE) {
384             qualifier = mQualifiers[index++];
385             if (qualifier != null) {
386                 if (result == null) {
387                     result = new StringBuilder();
388                 } else {
389                     result.append(", "); //$NON-NLS-1$
390                 }
391                 result.append(qualifier.getStringValue());
392 
393             }
394         }
395 
396         // process the language/region qualifier in a custom way, if there are both non null.
397         if (mQualifiers[INDEX_LANGUAGE] != null && mQualifiers[INDEX_REGION] != null) {
398             String language = mQualifiers[INDEX_LANGUAGE].getStringValue();
399             String region = mQualifiers[INDEX_REGION].getStringValue();
400 
401             if (result == null) {
402                 result = new StringBuilder();
403             } else {
404                 result.append(", "); //$NON-NLS-1$
405             }
406             result.append(String.format("%s_%s", language, region)); //$NON-NLS-1$
407 
408             index += 2;
409         }
410 
411         // post language/region qualifiers.
412         while (index < INDEX_COUNT) {
413             qualifier = mQualifiers[index++];
414             if (qualifier != null) {
415                 if (result == null) {
416                     result = new StringBuilder();
417                 } else {
418                     result.append(", "); //$NON-NLS-1$
419                 }
420                 result.append(qualifier.getStringValue());
421 
422             }
423         }
424 
425         return result == null ? null : result.toString();
426     }
427 
compareTo(FolderConfiguration folderConfig)428     public int compareTo(FolderConfiguration folderConfig) {
429         // default are always at the top.
430         if (isDefault()) {
431             if (folderConfig.isDefault()) {
432                 return 0;
433             }
434             return -1;
435         }
436 
437         // now we compare the qualifiers
438         for (int i = 0 ; i < INDEX_COUNT; i++) {
439             ResourceQualifier qualifier1 = mQualifiers[i];
440             ResourceQualifier qualifier2 = folderConfig.mQualifiers[i];
441 
442             if (qualifier1 == null) {
443                 if (qualifier2 == null) {
444                     continue;
445                 } else {
446                     return -1;
447                 }
448             } else {
449                 if (qualifier2 == null) {
450                     return 1;
451                 } else {
452                     int result = qualifier1.compareTo(qualifier2);
453 
454                     if (result == 0) {
455                         continue;
456                     }
457 
458                     return result;
459                 }
460             }
461         }
462 
463         // if we arrive here, all the qualifier matches
464         return 0;
465     }
466 
467     /**
468      * Returns whether the configuration is a match for the given reference config.
469      * <p/>A match means that, for each qualifier of this config
470      * <ul>
471      * <li>The reference config has no value set
472      * <li>or, the qualifier of the reference config is a match. Depending on the qualifier type
473      * this does not mean the same exact value.</li>
474      * </ul>
475      * @param referenceConfig The reference configuration to test against.
476      * @return true if the configuration matches.
477      */
isMatchFor(FolderConfiguration referenceConfig)478     public boolean isMatchFor(FolderConfiguration referenceConfig) {
479         for (int i = 0 ; i < INDEX_COUNT ; i++) {
480             ResourceQualifier testQualifier = mQualifiers[i];
481             ResourceQualifier referenceQualifier = referenceConfig.mQualifiers[i];
482 
483             // it's only a non match if both qualifiers are non-null, and they don't match.
484             if (testQualifier != null && referenceQualifier != null &&
485                         testQualifier.isMatchFor(referenceQualifier) == false) {
486                 return false;
487             }
488         }
489         return true;
490     }
491 
492     /**
493      * Returns the index of the first non null {@link ResourceQualifier} starting at index
494      * <var>startIndex</var>
495      * @param startIndex
496      * @return -1 if no qualifier was found.
497      */
getHighestPriorityQualifier(int startIndex)498     public int getHighestPriorityQualifier(int startIndex) {
499         for (int i = startIndex ; i < INDEX_COUNT ; i++) {
500             if (mQualifiers[i] != null) {
501                 return i;
502             }
503         }
504 
505         return -1;
506     }
507 
508     /**
509      * Create default qualifiers.
510      */
createDefault()511     public void createDefault() {
512         mQualifiers[INDEX_COUNTRY_CODE] = new CountryCodeQualifier();
513         mQualifiers[INDEX_NETWORK_CODE] = new NetworkCodeQualifier();
514         mQualifiers[INDEX_LANGUAGE] = new LanguageQualifier();
515         mQualifiers[INDEX_REGION] = new RegionQualifier();
516         mQualifiers[INDEX_SCREEN_SIZE] = new ScreenSizeQualifier();
517         mQualifiers[INDEX_SCREEN_RATIO] = new ScreenRatioQualifier();
518         mQualifiers[INDEX_SCREEN_ORIENTATION] = new ScreenOrientationQualifier();
519         mQualifiers[INDEX_PIXEL_DENSITY] = new PixelDensityQualifier();
520         mQualifiers[INDEX_TOUCH_TYPE] = new TouchScreenQualifier();
521         mQualifiers[INDEX_KEYBOARD_STATE] = new KeyboardStateQualifier();
522         mQualifiers[INDEX_TEXT_INPUT_METHOD] = new TextInputMethodQualifier();
523         mQualifiers[INDEX_NAVIGATION_METHOD] = new NavigationMethodQualifier();
524         mQualifiers[INDEX_SCREEN_DIMENSION] = new ScreenDimensionQualifier();
525         mQualifiers[INDEX_VERSION] = new VersionQualifier();
526     }
527 
528     /**
529      * Returns an array of all the non null qualifiers.
530      */
getQualifiers()531     public ResourceQualifier[] getQualifiers() {
532         int count = 0;
533         for (int i = 0 ; i < INDEX_COUNT ; i++) {
534             if (mQualifiers[i] != null) {
535                 count++;
536             }
537         }
538 
539         ResourceQualifier[] array = new ResourceQualifier[count];
540         int index = 0;
541         for (int i = 0 ; i < INDEX_COUNT ; i++) {
542             if (mQualifiers[i] != null) {
543                 array[index++] = mQualifiers[i];
544             }
545         }
546 
547         return array;
548     }
549 }
550