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