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