blob: 9052672d36c06a9a3a9303f786e1b940a86ee223 [file] [log] [blame]
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Eclipse Public License, Version 1.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.eclipse.org/org/documents/epl-v10.php
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.ide.eclipse.adt.internal.resources.manager;
import com.android.ide.eclipse.adt.internal.resources.IResourceRepository;
import com.android.ide.eclipse.adt.internal.resources.ResourceItem;
import com.android.ide.eclipse.adt.internal.resources.ResourceType;
import com.android.ide.eclipse.adt.internal.resources.configurations.FolderConfiguration;
import com.android.ide.eclipse.adt.internal.resources.configurations.LanguageQualifier;
import com.android.ide.eclipse.adt.internal.resources.configurations.RegionQualifier;
import com.android.ide.eclipse.adt.internal.resources.configurations.ResourceQualifier;
import com.android.ide.eclipse.adt.internal.resources.manager.files.IAbstractFolder;
import com.android.layoutlib.api.IResourceValue;
import com.android.layoutlib.utils.ResourceValue;
import org.eclipse.core.resources.IFolder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
/**
* Represents the resources of a project. This is a file view of the resources, with handling
* for the alternate resource types. For a compiled view use CompiledResources.
*/
public class ProjectResources implements IResourceRepository {
private final HashMap<ResourceFolderType, List<ResourceFolder>> mFolderMap =
new HashMap<ResourceFolderType, List<ResourceFolder>>();
private final HashMap<ResourceType, List<ProjectResourceItem>> mResourceMap =
new HashMap<ResourceType, List<ProjectResourceItem>>();
/** Map of (name, id) for resources of type {@link ResourceType#ID} coming from R.java */
private Map<String, Map<String, Integer>> mResourceValueMap;
/** Map of (id, [name, resType]) for all resources coming from R.java */
private Map<Integer, String[]> mResIdValueToNameMap;
/** Map of (int[], name) for styleable resources coming from R.java */
private Map<IntArrayWrapper, String> mStyleableValueToNameMap;
/** Cached list of {@link IdResourceItem}. This is mix of IdResourceItem created by
* {@link MultiResourceFile} for ids coming from XML files under res/values and
* {@link IdResourceItem} created manually, from the list coming from R.java */
private final ArrayList<IdResourceItem> mIdResourceList = new ArrayList<IdResourceItem>();
private final boolean mIsFrameworkRepository;
private final IntArrayWrapper mWrapper = new IntArrayWrapper(null);
public ProjectResources(boolean isFrameworkRepository) {
mIsFrameworkRepository = isFrameworkRepository;
}
public boolean isSystemRepository() {
return mIsFrameworkRepository;
}
/**
* Adds a Folder Configuration to the project.
* @param type The resource type.
* @param config The resource configuration.
* @param folder The workspace folder object.
* @return the {@link ResourceFolder} object associated to this folder.
*/
protected ResourceFolder add(ResourceFolderType type, FolderConfiguration config,
IAbstractFolder folder) {
// get the list for the resource type
List<ResourceFolder> list = mFolderMap.get(type);
if (list == null) {
list = new ArrayList<ResourceFolder>();
ResourceFolder cf = new ResourceFolder(type, config, folder, mIsFrameworkRepository);
list.add(cf);
mFolderMap.put(type, list);
return cf;
}
// look for an already existing folder configuration.
for (ResourceFolder cFolder : list) {
if (cFolder.mConfiguration.equals(config)) {
// config already exist. Nothing to be done really, besides making sure
// the IFolder object is up to date.
cFolder.mFolder = folder;
return cFolder;
}
}
// If we arrive here, this means we didn't find a matching configuration.
// So we add one.
ResourceFolder cf = new ResourceFolder(type, config, folder, mIsFrameworkRepository);
list.add(cf);
return cf;
}
/**
* Removes a {@link ResourceFolder} associated with the specified {@link IAbstractFolder}.
* @param type The type of the folder
* @param folder the IFolder object.
*/
protected void removeFolder(ResourceFolderType type, IFolder folder) {
// get the list of folders for the resource type.
List<ResourceFolder> list = mFolderMap.get(type);
if (list != null) {
int count = list.size();
for (int i = 0 ; i < count ; i++) {
ResourceFolder resFolder = list.get(i);
if (resFolder.getFolder().getIFolder().equals(folder)) {
// we found the matching ResourceFolder. we need to remove it.
list.remove(i);
// we now need to invalidate this resource type.
// The easiest way is to touch one of the other folders of the same type.
if (list.size() > 0) {
list.get(0).touch();
} else {
// if the list is now empty, and we have a single ResouceType out of this
// ResourceFolderType, then we are done.
// However, if another ResourceFolderType can generate similar ResourceType
// than this, we need to update those ResourceTypes as well.
// For instance, if the last "drawable-*" folder is deleted, we need to
// refresh the ResourceItem associated with ResourceType.DRAWABLE.
// Those can be found in ResourceFolderType.DRAWABLE but also in
// ResourceFolderType.VALUES.
// If we don't find a single folder to touch, then it's fine, as the top
// level items (the list of generated resource types) is not cached
// (for now)
// get the lists of ResourceTypes generated by this ResourceFolderType
ResourceType[] resTypes = FolderTypeRelationship.getRelatedResourceTypes(
type);
// for each of those, make sure to find one folder to touch so that the
// list of ResourceItem associated with the type is rebuilt.
for (ResourceType resType : resTypes) {
// get the list of folder that can generate this type
ResourceFolderType[] folderTypes =
FolderTypeRelationship.getRelatedFolders(resType);
// we only need to touch one folder in any of those (since it's one
// folder per type, not per folder type).
for (ResourceFolderType folderType : folderTypes) {
List<ResourceFolder> resFolders = mFolderMap.get(folderType);
if (resFolders != null && resFolders.size() > 0) {
resFolders.get(0).touch();
break;
}
}
}
}
// we're done updating/touching, we can stop
break;
}
}
}
}
/**
* Returns a list of {@link ResourceFolder} for a specific {@link ResourceFolderType}.
* @param type The {@link ResourceFolderType}
*/
public List<ResourceFolder> getFolders(ResourceFolderType type) {
return mFolderMap.get(type);
}
/* (non-Javadoc)
* @see com.android.ide.eclipse.editors.resources.IResourceRepository#getAvailableResourceTypes()
*/
public ResourceType[] getAvailableResourceTypes() {
ArrayList<ResourceType> list = new ArrayList<ResourceType>();
// For each key, we check if there's a single ResourceType match.
// If not, we look for the actual content to give us the resource type.
for (ResourceFolderType folderType : mFolderMap.keySet()) {
ResourceType types[] = FolderTypeRelationship.getRelatedResourceTypes(folderType);
if (types.length == 1) {
// before we add it we check if it's not already present, since a ResourceType
// could be created from multiple folders, even for the folders that only create
// one type of resource (drawable for instance, can be created from drawable/ and
// values/)
if (list.indexOf(types[0]) == -1) {
list.add(types[0]);
}
} else {
// there isn't a single resource type out of this folder, so we look for all
// content.
List<ResourceFolder> folders = mFolderMap.get(folderType);
if (folders != null) {
for (ResourceFolder folder : folders) {
Collection<ResourceType> folderContent = folder.getResourceTypes();
// then we add them, but only if they aren't already in the list.
for (ResourceType folderResType : folderContent) {
if (list.indexOf(folderResType) == -1) {
list.add(folderResType);
}
}
}
}
}
}
// in case ResourceType.ID haven't been added yet because there's no id defined
// in XML, we check on the list of compiled id resources.
if (list.indexOf(ResourceType.ID) == -1 && mResourceValueMap != null) {
Map<String, Integer> map = mResourceValueMap.get(ResourceType.ID.getName());
if (map != null && map.size() > 0) {
list.add(ResourceType.ID);
}
}
// at this point the list is full of ResourceType defined in the files.
// We need to sort it.
Collections.sort(list);
return list.toArray(new ResourceType[list.size()]);
}
/* (non-Javadoc)
* @see com.android.ide.eclipse.editors.resources.IResourceRepository#getResources(com.android.ide.eclipse.common.resources.ResourceType)
*/
public ProjectResourceItem[] getResources(ResourceType type) {
checkAndUpdate(type);
if (type == ResourceType.ID) {
synchronized (mIdResourceList) {
return mIdResourceList.toArray(new ProjectResourceItem[mIdResourceList.size()]);
}
}
List<ProjectResourceItem> items = mResourceMap.get(type);
return items.toArray(new ProjectResourceItem[items.size()]);
}
/* (non-Javadoc)
* @see com.android.ide.eclipse.editors.resources.IResourceRepository#hasResources(com.android.ide.eclipse.common.resources.ResourceType)
*/
public boolean hasResources(ResourceType type) {
checkAndUpdate(type);
if (type == ResourceType.ID) {
synchronized (mIdResourceList) {
return mIdResourceList.size() > 0;
}
}
List<ProjectResourceItem> items = mResourceMap.get(type);
return (items != null && items.size() > 0);
}
/**
* Returns the {@link ResourceFolder} associated with a {@link IFolder}.
* @param folder The {@link IFolder} object.
* @return the {@link ResourceFolder} or null if it was not found.
*/
public ResourceFolder getResourceFolder(IFolder folder) {
for (List<ResourceFolder> list : mFolderMap.values()) {
for (ResourceFolder resFolder : list) {
if (resFolder.getFolder().getIFolder().equals(folder)) {
return resFolder;
}
}
}
return null;
}
/**
* Returns the {@link ResourceFile} matching the given name, {@link ResourceFolderType} and
* configuration.
* <p/>This only works with files generating one resource named after the file (for instance,
* layouts, bitmap based drawable, xml, anims).
* @return the matching file or <code>null</code> if no match was found.
*/
public ResourceFile getMatchingFile(String name, ResourceFolderType type,
FolderConfiguration config) {
// get the folders for the given type
List<ResourceFolder> folders = mFolderMap.get(type);
// look for folders containing a file with the given name.
ArrayList<ResourceFolder> matchingFolders = new ArrayList<ResourceFolder>();
// remove the folders that do not have a file with the given name, or if their config
// is incompatible.
for (int i = 0 ; i < folders.size(); i++) {
ResourceFolder folder = folders.get(i);
if (folder.hasFile(name) == true) {
matchingFolders.add(folder);
}
}
// from those, get the folder with a config matching the given reference configuration.
Resource match = findMatchingConfiguredResource(matchingFolders, config);
// do we have a matching folder?
if (match instanceof ResourceFolder) {
// get the ResourceFile from the filename
return ((ResourceFolder)match).getFile(name);
}
return null;
}
/**
* Returns the resources values matching a given {@link FolderConfiguration}.
* @param referenceConfig the configuration that each value must match.
*/
public Map<String, Map<String, IResourceValue>> getConfiguredResources(
FolderConfiguration referenceConfig) {
Map<String, Map<String, IResourceValue>> map =
new HashMap<String, Map<String, IResourceValue>>();
// special case for Id since there's a mix of compiled id (declared inline) and id declared
// in the XML files.
if (mIdResourceList.size() > 0) {
Map<String, IResourceValue> idMap = new HashMap<String, IResourceValue>();
String idType = ResourceType.ID.getName();
for (IdResourceItem id : mIdResourceList) {
// FIXME: cache the ResourceValue!
idMap.put(id.getName(), new ResourceValue(idType, id.getName(),
mIsFrameworkRepository));
}
map.put(ResourceType.ID.getName(), idMap);
}
Set<ResourceType> keys = mResourceMap.keySet();
for (ResourceType key : keys) {
// we don't process ID resources since we already did it above.
if (key != ResourceType.ID) {
map.put(key.getName(), getConfiguredResource(key, referenceConfig));
}
}
return map;
}
/**
* Loads all the resources. Essentially this forces to load the values from the
* {@link ResourceFile} objects to make sure they are up to date and loaded
* in {@link #mResourceMap}.
*/
public void loadAll() {
// gets all the resource types available.
ResourceType[] types = getAvailableResourceTypes();
// loop on them and load them
for (ResourceType type: types) {
checkAndUpdate(type);
}
}
/**
* Resolves a compiled resource id into the resource name and type
* @param id
* @return an array of 2 strings { name, type } or null if the id could not be resolved
*/
public String[] resolveResourceValue(int id) {
if (mResIdValueToNameMap != null) {
return mResIdValueToNameMap.get(id);
}
return null;
}
/**
* Resolves a compiled resource id of type int[] into the resource name.
*/
public String resolveResourceValue(int[] id) {
if (mStyleableValueToNameMap != null) {
mWrapper.set(id);
return mStyleableValueToNameMap.get(mWrapper);
}
return null;
}
/**
* Returns the value of a resource by its type and name.
*/
public Integer getResourceValue(String type, String name) {
if (mResourceValueMap != null) {
Map<String, Integer> map = mResourceValueMap.get(type);
if (map != null) {
return map.get(name);
}
}
return null;
}
/**
* Returns the sorted list of languages used in the resources.
*/
public SortedSet<String> getLanguages() {
SortedSet<String> set = new TreeSet<String>();
Collection<List<ResourceFolder>> folderList = mFolderMap.values();
for (List<ResourceFolder> folderSubList : folderList) {
for (ResourceFolder folder : folderSubList) {
FolderConfiguration config = folder.getConfiguration();
LanguageQualifier lang = config.getLanguageQualifier();
if (lang != null) {
set.add(lang.getStringValue());
}
}
}
return set;
}
/**
* Returns the sorted list of regions used in the resources with the given language.
* @param currentLanguage the current language the region must be associated with.
*/
public SortedSet<String> getRegions(String currentLanguage) {
SortedSet<String> set = new TreeSet<String>();
Collection<List<ResourceFolder>> folderList = mFolderMap.values();
for (List<ResourceFolder> folderSubList : folderList) {
for (ResourceFolder folder : folderSubList) {
FolderConfiguration config = folder.getConfiguration();
// get the language
LanguageQualifier lang = config.getLanguageQualifier();
if (lang != null && lang.getStringValue().equals(currentLanguage)) {
RegionQualifier region = config.getRegionQualifier();
if (region != null) {
set.add(region.getStringValue());
}
}
}
}
return set;
}
/**
* Returns a map of (resource name, resource value) for the given {@link ResourceType}.
* <p/>The values returned are taken from the resource files best matching a given
* {@link FolderConfiguration}.
* @param type the type of the resources.
* @param referenceConfig the configuration to best match.
*/
private Map<String, IResourceValue> getConfiguredResource(ResourceType type,
FolderConfiguration referenceConfig) {
// get the resource item for the given type
List<ProjectResourceItem> items = mResourceMap.get(type);
// create the map
HashMap<String, IResourceValue> map = new HashMap<String, IResourceValue>();
for (ProjectResourceItem item : items) {
// get the source files generating this resource
List<ResourceFile> list = item.getSourceFileList();
// look for the best match for the given configuration
Resource match = findMatchingConfiguredResource(list, referenceConfig);
if (match instanceof ResourceFile) {
ResourceFile matchResFile = (ResourceFile)match;
// get the value of this configured resource.
IResourceValue value = matchResFile.getValue(type, item.getName());
if (value != null) {
map.put(item.getName(), value);
}
}
}
return map;
}
/**
* Returns the best matching {@link Resource}.
* @param resources the list of {@link Resource} to choose from.
* @param referenceConfig the {@link FolderConfiguration} to match.
* @see http://d.android.com/guide/topics/resources/resources-i18n.html#best-match
*/
private Resource findMatchingConfiguredResource(List<? extends Resource> resources,
FolderConfiguration referenceConfig) {
//
// 1: eliminate resources that contradict the reference configuration
// 2: pick next qualifier type
// 3: check if any resources use this qualifier, if no, back to 2, else move on to 4.
// 4: eliminate resources that don't use this qualifier.
// 5: if more than one resource left, go back to 2.
//
// The precedence of the qualifiers is more important than the number of qualifiers that
// exactly match the device.
// 1: eliminate resources that contradict
ArrayList<Resource> matchingResources = new ArrayList<Resource>();
for (int i = 0 ; i < resources.size(); i++) {
Resource res = resources.get(i);
if (res.getConfiguration().isMatchFor(referenceConfig)) {
matchingResources.add(res);
}
}
// if there is only one match, just take it
if (matchingResources.size() == 1) {
return matchingResources.get(0);
} else if (matchingResources.size() == 0) {
return null;
}
// 2. Loop on the qualifiers, and eliminate matches
final int count = FolderConfiguration.getQualifierCount();
for (int q = 0 ; q < count ; q++) {
// look to see if one resource has this qualifier.
// At the same time also record the best match value for the qualifier (if applicable).
// The reference value, to find the best match.
// Note that this qualifier could be null. In which case any qualifier found in the
// possible match, will all be considered best match.
ResourceQualifier referenceQualifier = referenceConfig.getQualifier(q);
boolean found = false;
ResourceQualifier bestMatch = null; // this is to store the best match.
for (Resource res : matchingResources) {
ResourceQualifier qualifier = res.getConfiguration().getQualifier(q);
if (qualifier != null) {
// set the flag.
found = true;
// Now check for a best match. If the reference qualifier is null ,
// any qualifier is a "best" match (we don't need to record all of them.
// Instead the non compatible ones are removed below)
if (referenceQualifier != null) {
if (qualifier.isBetterMatchThan(bestMatch, referenceQualifier)) {
bestMatch = qualifier;
}
}
}
}
// 4. If a resources has a qualifier at the current index, remove all the resources that
// do not have one, or whose qualifier value does not equal the best match found above
// unless there's no reference qualifier, in which case they are all considered
// "best" match.
if (found) {
for (int i = 0 ; i < matchingResources.size(); ) {
Resource res = matchingResources.get(i);
ResourceQualifier qualifier = res.getConfiguration().getQualifier(q);
if (qualifier == null) {
// this resources has no qualifier of this type: rejected.
matchingResources.remove(res);
} else if (referenceQualifier != null && bestMatch != null &&
bestMatch.equals(qualifier) == false) {
// there's a reference qualifier and there is a better match for it than
// this resource, so we reject it.
matchingResources.remove(res);
} else {
// looks like we keep this resource, move on to the next one.
i++;
}
}
// at this point we may have run out of matching resources before going
// through all the qualifiers.
if (matchingResources.size() < 2) {
break;
}
}
}
// Because we accept resources whose configuration have qualifiers where the reference
// configuration doesn't, we can end up with more than one match. In this case, we just
// take the first one.
if (matchingResources.size() == 0) {
return null;
}
return matchingResources.get(1);
}
/**
* Checks if the list of {@link ResourceItem}s for the specified {@link ResourceType} needs
* to be updated.
* @param type the Resource Type.
*/
private void checkAndUpdate(ResourceType type) {
// get the list of folder that can output this type
ResourceFolderType[] folderTypes = FolderTypeRelationship.getRelatedFolders(type);
for (ResourceFolderType folderType : folderTypes) {
List<ResourceFolder> folders = mFolderMap.get(folderType);
if (folders != null) {
for (ResourceFolder folder : folders) {
if (folder.isTouched()) {
// if this folder is touched we need to update all the types that can
// be generated from a file in this folder.
// This will include 'type' obviously.
ResourceType[] resTypes = FolderTypeRelationship.getRelatedResourceTypes(
folderType);
for (ResourceType resType : resTypes) {
update(resType);
}
return;
}
}
}
}
}
/**
* Updates the list of {@link ResourceItem} objects associated with a {@link ResourceType}.
* This will reset the touch status of all the folders that can generate this resource type.
* @param type the Resource Type.
*/
private void update(ResourceType type) {
// get the cache list, and lets make a backup
List<ProjectResourceItem> items = mResourceMap.get(type);
List<ProjectResourceItem> backup = new ArrayList<ProjectResourceItem>();
if (items == null) {
items = new ArrayList<ProjectResourceItem>();
mResourceMap.put(type, items);
} else {
// backup the list
backup.addAll(items);
// we reset the list itself.
items.clear();
}
// get the list of folder that can output this type
ResourceFolderType[] folderTypes = FolderTypeRelationship.getRelatedFolders(type);
for (ResourceFolderType folderType : folderTypes) {
List<ResourceFolder> folders = mFolderMap.get(folderType);
if (folders != null) {
for (ResourceFolder folder : folders) {
items.addAll(folder.getResources(type, this));
folder.resetTouch();
}
}
}
// now items contains the new list. We "merge" it with the backup list.
// Basically, we need to keep the old instances of ResourceItem (where applicable),
// but replace them by the content of the new items.
// This will let the resource explorer keep the expanded state of the nodes whose data
// is a ResourceItem object.
if (backup.size() > 0) {
// this is not going to change as we're only replacing instances.
int count = items.size();
for (int i = 0 ; i < count;) {
// get the "new" item
ProjectResourceItem item = items.get(i);
// look for a similar item in the old list.
ProjectResourceItem foundOldItem = null;
for (ProjectResourceItem oldItem : backup) {
if (oldItem.getName().equals(item.getName())) {
foundOldItem = oldItem;
break;
}
}
if (foundOldItem != null) {
// erase the data of the old item with the data from the new one.
foundOldItem.replaceWith(item);
// remove the old and new item from their respective lists
items.remove(i);
backup.remove(foundOldItem);
// add the old item to the new list
items.add(foundOldItem);
} else {
// this is a new item, we skip to the next object
i++;
}
}
}
// if this is the ResourceType.ID, we create the actual list, from this list and
// the compiled resource list.
if (type == ResourceType.ID) {
mergeIdResources();
} else {
// else this is the list that will actually be displayed, so we sort it.
Collections.sort(items);
}
}
/**
* Looks up an existing {@link ProjectResourceItem} by {@link ResourceType} and name.
* @param type the Resource Type.
* @param name the Resource name.
* @return the existing ResourceItem or null if no match was found.
*/
protected ProjectResourceItem findResourceItem(ResourceType type, String name) {
List<ProjectResourceItem> list = mResourceMap.get(type);
for (ProjectResourceItem item : list) {
if (name.equals(item.getName())) {
return item;
}
}
return null;
}
/**
* Sets compiled resource information.
* @param resIdValueToNameMap a map of compiled resource id to resource name.
* The map is acquired by the {@link ProjectResources} object.
* @param styleableValueMap
* @param resourceValueMap a map of (name, id) for resources of type {@link ResourceType#ID}.
* The list is acquired by the {@link ProjectResources} object.
*/
void setCompiledResources(Map<Integer, String[]> resIdValueToNameMap,
Map<IntArrayWrapper, String> styleableValueMap,
Map<String, Map<String, Integer>> resourceValueMap) {
mResourceValueMap = resourceValueMap;
mResIdValueToNameMap = resIdValueToNameMap;
mStyleableValueToNameMap = styleableValueMap;
mergeIdResources();
}
/**
* Merges the list of ID resource coming from R.java and the list of ID resources
* coming from XML declaration into the cached list {@link #mIdResourceList}.
*/
void mergeIdResources() {
// get the list of IDs coming from XML declaration. Those ids are present in
// mCompiledIdResources already, so we'll need to use those instead of creating
// new IdResourceItem
List<ProjectResourceItem> xmlIdResources = mResourceMap.get(ResourceType.ID);
synchronized (mIdResourceList) {
// copy the currently cached items.
ArrayList<IdResourceItem> oldItems = new ArrayList<IdResourceItem>();
oldItems.addAll(mIdResourceList);
// empty the current list
mIdResourceList.clear();
// get the list of compile id resources.
Map<String, Integer> idMap = null;
if (mResourceValueMap != null) {
idMap = mResourceValueMap.get(ResourceType.ID.getName());
}
if (idMap == null) {
if (xmlIdResources != null) {
for (ProjectResourceItem resourceItem : xmlIdResources) {
// check the actual class just for safety.
if (resourceItem instanceof IdResourceItem) {
mIdResourceList.add((IdResourceItem)resourceItem);
}
}
}
} else {
// loop on the full list of id, and look for a match in the old list,
// in the list coming from XML (in case a new XML item was created.)
Set<String> idSet = idMap.keySet();
idLoop: for (String idResource : idSet) {
// first look in the XML list in case an id went from inline to XML declared.
if (xmlIdResources != null) {
for (ProjectResourceItem resourceItem : xmlIdResources) {
if (resourceItem instanceof IdResourceItem &&
resourceItem.getName().equals(idResource)) {
mIdResourceList.add((IdResourceItem)resourceItem);
continue idLoop;
}
}
}
// if we haven't found it, look in the old items.
int count = oldItems.size();
for (int i = 0 ; i < count ; i++) {
IdResourceItem resourceItem = oldItems.get(i);
if (resourceItem.getName().equals(idResource)) {
oldItems.remove(i);
mIdResourceList.add(resourceItem);
continue idLoop;
}
}
// if we haven't found it, it looks like it's a new id that was
// declared inline.
mIdResourceList.add(new IdResourceItem(idResource,
true /* isDeclaredInline */));
}
}
// now we sort the list
Collections.sort(mIdResourceList);
}
}
}