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