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