Home | History | Annotate | Download | only in resources
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
      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.common.resources;
     18 
     19 import com.android.ide.common.rendering.api.ResourceValue;
     20 import com.android.ide.common.resources.configuration.FolderConfiguration;
     21 import com.android.resources.ResourceType;
     22 
     23 import java.util.ArrayList;
     24 import java.util.Collections;
     25 import java.util.Comparator;
     26 import java.util.List;
     27 
     28 /**
     29  * An android resource.
     30  *
     31  * This is a representation of the resource, not of its value(s). It gives access to all
     32  * the source files that generate this particular resource which then can be used to access
     33  * the actual value(s).
     34  *
     35  * @see ResourceFile#getResources(ResourceType, ResourceRepository)
     36  */
     37 public class ResourceItem implements Comparable<ResourceItem> {
     38 
     39     private final static Comparator<ResourceFile> sComparator = new Comparator<ResourceFile>() {
     40         @Override
     41         public int compare(ResourceFile file1, ResourceFile file2) {
     42             // get both FolderConfiguration and compare them
     43             FolderConfiguration fc1 = file1.getFolder().getConfiguration();
     44             FolderConfiguration fc2 = file2.getFolder().getConfiguration();
     45 
     46             return fc1.compareTo(fc2);
     47         }
     48     };
     49 
     50     private final String mName;
     51 
     52     /**
     53      * List of files generating this ResourceItem.
     54      */
     55     private final List<ResourceFile> mFiles = new ArrayList<ResourceFile>();
     56 
     57     /**
     58      * Constructs a new ResourceItem.
     59      * @param name the name of the resource as it appears in the XML and R.java files.
     60      */
     61     public ResourceItem(String name) {
     62         mName = name;
     63     }
     64 
     65     /**
     66      * Returns the name of the resource.
     67      */
     68     public final String getName() {
     69         return mName;
     70     }
     71 
     72     /**
     73      * Compares the {@link ResourceItem} to another.
     74      * @param other the ResourceItem to be compared to.
     75      */
     76     @Override
     77     public int compareTo(ResourceItem other) {
     78         return mName.compareTo(other.mName);
     79     }
     80 
     81     /**
     82      * Returns whether the resource is editable directly.
     83      * <p/>
     84      * This is typically the case for resources that don't have alternate versions, or resources
     85      * of type {@link ResourceType#ID} that aren't declared inline.
     86      */
     87     public boolean isEditableDirectly() {
     88         return hasAlternates() == false;
     89     }
     90 
     91     /**
     92      * Returns whether the ID resource has been declared inline inside another resource XML file.
     93      * If the resource type is not {@link ResourceType#ID}, this will always return {@code false}.
     94      */
     95     public boolean isDeclaredInline() {
     96         return false;
     97     }
     98 
     99     /**
    100      * Returns a {@link ResourceValue} for this item based on the given configuration.
    101      * If the ResourceItem has several source files, one will be selected based on the config.
    102      * @param type the type of the resource. This is necessary because ResourceItem doesn't embed
    103      *     its type, but ResourceValue does.
    104      * @param referenceConfig the config of the resource item.
    105      * @param isFramework whether the resource is a framework value. Same as the type.
    106      * @return a ResourceValue or null if none match the config.
    107      */
    108     public ResourceValue getResourceValue(ResourceType type, FolderConfiguration referenceConfig,
    109             boolean isFramework) {
    110         // look for the best match for the given configuration
    111         // the match has to be of type ResourceFile since that's what the input list contains
    112         ResourceFile match = (ResourceFile) referenceConfig.findMatchingConfigurable(mFiles);
    113 
    114         if (match != null) {
    115             // get the value of this configured resource.
    116             return match.getValue(type, mName);
    117         }
    118 
    119         return null;
    120     }
    121 
    122     /**
    123      * Adds a new source file.
    124      * @param file the source file.
    125      */
    126     protected void add(ResourceFile file) {
    127         mFiles.add(file);
    128     }
    129 
    130     /**
    131      * Removes a file from the list of source files.
    132      * @param file the file to remove
    133      */
    134     protected void removeFile(ResourceFile file) {
    135         mFiles.remove(file);
    136     }
    137 
    138     /**
    139      * Returns {@code true} if the item has no source file.
    140      * @return
    141      */
    142     protected boolean hasNoSourceFile() {
    143         return mFiles.size() == 0;
    144     }
    145 
    146     /**
    147      * Reset the item by emptying its source file list.
    148      */
    149     protected void reset() {
    150         mFiles.clear();
    151     }
    152 
    153     /**
    154      * Returns the sorted list of {@link ResourceItem} objects for this resource item.
    155      */
    156     public ResourceFile[] getSourceFileArray() {
    157         ArrayList<ResourceFile> list = new ArrayList<ResourceFile>();
    158         list.addAll(mFiles);
    159 
    160         Collections.sort(list, sComparator);
    161 
    162         return list.toArray(new ResourceFile[list.size()]);
    163     }
    164 
    165     /**
    166      * Returns the list of source file for this resource.
    167      */
    168     public List<ResourceFile> getSourceFileList() {
    169         return Collections.unmodifiableList(mFiles);
    170     }
    171 
    172     /**
    173      * Returns if the resource has at least one non-default version.
    174      *
    175      * @see ResourceFile#getConfiguration()
    176      * @see FolderConfiguration#isDefault()
    177      */
    178     public boolean hasAlternates() {
    179         for (ResourceFile file : mFiles) {
    180             if (file.getFolder().getConfiguration().isDefault() == false) {
    181                 return true;
    182             }
    183         }
    184 
    185         return false;
    186     }
    187 
    188     /**
    189      * Returns whether the resource has a default version, with no qualifier.
    190      *
    191      * @see ResourceFile#getConfiguration()
    192      * @see FolderConfiguration#isDefault()
    193      */
    194     public boolean hasDefault() {
    195         for (ResourceFile file : mFiles) {
    196             if (file.getFolder().getConfiguration().isDefault()) {
    197                 return true;
    198             }
    199         }
    200 
    201         // We only want to return false if there's no default and more than 0 items.
    202         return (mFiles.size() == 0);
    203     }
    204 
    205     /**
    206      * Returns the number of alternate versions for this resource.
    207      *
    208      * @see ResourceFile#getConfiguration()
    209      * @see FolderConfiguration#isDefault()
    210      */
    211     public int getAlternateCount() {
    212         int count = 0;
    213         for (ResourceFile file : mFiles) {
    214             if (file.getFolder().getConfiguration().isDefault() == false) {
    215                 count++;
    216             }
    217         }
    218 
    219         return count;
    220     }
    221 
    222     /**
    223      * Returns a formatted string usable in an XML to use for the {@link ResourceItem}.
    224      * @param system Whether this is a system resource or a project resource.
    225      * @return a string in the format @[type]/[name]
    226      */
    227     public String getXmlString(ResourceType type, boolean system) {
    228         if (type == ResourceType.ID && isDeclaredInline()) {
    229             return (system ? "@android:" : "@+") + type.getName() + "/" + mName; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
    230         }
    231 
    232         return (system ? "@android:" : "@") + type.getName() + "/" + mName; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
    233     }
    234 
    235     @Override
    236     public String toString() {
    237         return "ResourceItem [mName=" + mName + ", mFiles=" + mFiles + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
    238     }
    239 }
    240