diff options
author | Siva Velusamy <vsiva@google.com> | 2012-09-18 14:51:46 -0700 |
---|---|---|
committer | Siva Velusamy <vsiva@google.com> | 2012-09-18 15:09:33 -0700 |
commit | 6837aad30d6c51783ca1dc784ca6bdcc8a3d9f2d (patch) | |
tree | 90af15ddcc9f0bbc3151a0978b3e637f77fdd54a /sdk_common/src/com/android/ide/common/resources/MultiResourceFile.java | |
parent | 6184f12fa097e1c5bddfe50700b3b0740c736a5a (diff) | |
download | sdk-6837aad30d6c51783ca1dc784ca6bdcc8a3d9f2d.zip sdk-6837aad30d6c51783ca1dc784ca6bdcc8a3d9f2d.tar.gz sdk-6837aad30d6c51783ca1dc784ca6bdcc8a3d9f2d.tar.bz2 |
Rename ide_common to sdk_common
Change-Id: I1b39ee439a532f3f6758be35b569948e2e906665
Diffstat (limited to 'sdk_common/src/com/android/ide/common/resources/MultiResourceFile.java')
-rw-r--r-- | sdk_common/src/com/android/ide/common/resources/MultiResourceFile.java | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/sdk_common/src/com/android/ide/common/resources/MultiResourceFile.java b/sdk_common/src/com/android/ide/common/resources/MultiResourceFile.java new file mode 100644 index 0000000..c9a8bc7 --- /dev/null +++ b/sdk_common/src/com/android/ide/common/resources/MultiResourceFile.java @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 + * + * 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.common.resources; + +import com.android.ide.common.rendering.api.ResourceValue; +import com.android.ide.common.resources.ValueResourceParser.IValueResourceRepository; +import com.android.io.IAbstractFile; +import com.android.io.StreamException; +import com.android.resources.ResourceType; + +import org.xml.sax.SAXException; + +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.Map; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +/** + * Represents a resource file able to declare multiple resources, which could be of + * different {@link ResourceType}. + * <p/> + * This is typically an XML file inside res/values. + */ +public final class MultiResourceFile extends ResourceFile implements IValueResourceRepository { + + private final static SAXParserFactory sParserFactory = SAXParserFactory.newInstance(); + + private final Map<ResourceType, Map<String, ResourceValue>> mResourceItems = + new EnumMap<ResourceType, Map<String, ResourceValue>>(ResourceType.class); + + private Collection<ResourceType> mResourceTypeList = null; + + public MultiResourceFile(IAbstractFile file, ResourceFolder folder) { + super(file, folder); + } + + // Boolean flag to track whether a named element has been added or removed, thus requiring + // a new ID table to be generated + private boolean mNeedIdRefresh; + + @Override + protected void load(ScanningContext context) { + // need to parse the file and find the content. + parseFile(); + + // create new ResourceItems for the new content. + mResourceTypeList = Collections.unmodifiableCollection(mResourceItems.keySet()); + + // We need an ID generation step + mNeedIdRefresh = true; + + // create/update the resource items. + updateResourceItems(context); + } + + @Override + protected void update(ScanningContext context) { + // Reset the ID generation flag + mNeedIdRefresh = false; + + // Copy the previous version of our list of ResourceItems and types + Map<ResourceType, Map<String, ResourceValue>> oldResourceItems + = new EnumMap<ResourceType, Map<String, ResourceValue>>(mResourceItems); + + // reset current content. + mResourceItems.clear(); + + // need to parse the file and find the content. + parseFile(); + + // create new ResourceItems for the new content. + mResourceTypeList = Collections.unmodifiableCollection(mResourceItems.keySet()); + + // Check to see if any names have changed. If so, mark the flag so updateResourceItems + // can notify the ResourceRepository that an ID refresh is needed + if (oldResourceItems.keySet().equals(mResourceItems.keySet())) { + for (ResourceType type : mResourceTypeList) { + // We just need to check the names of the items. + // If there are new or removed names then we'll have to regenerate IDs + if (mResourceItems.get(type).keySet() + .equals(oldResourceItems.get(type).keySet()) == false) { + mNeedIdRefresh = true; + } + } + } else { + // If our type list is different, obviously the names will be different + mNeedIdRefresh = true; + } + // create/update the resource items. + updateResourceItems(context); + } + + @Override + protected void dispose(ScanningContext context) { + ResourceRepository repository = getRepository(); + + // only remove this file from all existing ResourceItem. + repository.removeFile(mResourceTypeList, this); + + // We'll need an ID refresh because we deleted items + context.requestFullAapt(); + + // don't need to touch the content, it'll get reclaimed as this objects disappear. + // In the mean time other objects may need to access it. + } + + @Override + public Collection<ResourceType> getResourceTypes() { + return mResourceTypeList; + } + + @Override + public boolean hasResources(ResourceType type) { + Map<String, ResourceValue> list = mResourceItems.get(type); + return (list != null && list.size() > 0); + } + + private void updateResourceItems(ScanningContext context) { + ResourceRepository repository = getRepository(); + + // remove this file from all existing ResourceItem. + repository.removeFile(mResourceTypeList, this); + + for (ResourceType type : mResourceTypeList) { + Map<String, ResourceValue> list = mResourceItems.get(type); + + if (list != null) { + Collection<ResourceValue> values = list.values(); + for (ResourceValue res : values) { + ResourceItem item = repository.getResourceItem(type, res.getName()); + + // add this file to the list of files generating this resource item. + item.add(this); + } + } + } + + // If we need an ID refresh, ask the repository for that now + if (mNeedIdRefresh) { + context.requestFullAapt(); + } + } + + /** + * Parses the file and creates a list of {@link ResourceType}. + */ + private void parseFile() { + try { + SAXParser parser = sParserFactory.newSAXParser(); + parser.parse(getFile().getContents(), new ValueResourceParser(this, isFramework())); + } catch (ParserConfigurationException e) { + } catch (SAXException e) { + } catch (IOException e) { + } catch (StreamException e) { + } + } + + /** + * Adds a resource item to the list + * @param value The value of the resource. + */ + @Override + public void addResourceValue(ResourceValue value) { + ResourceType resType = value.getResourceType(); + + Map<String, ResourceValue> list = mResourceItems.get(resType); + + // if the list does not exist, create it. + if (list == null) { + list = new HashMap<String, ResourceValue>(); + mResourceItems.put(resType, list); + } else { + // look for a possible value already existing. + ResourceValue oldValue = list.get(value.getName()); + + if (oldValue != null) { + oldValue.replaceWith(value); + return; + } + } + + // empty list or no match found? add the given resource + list.put(value.getName(), value); + } + + @Override + public boolean hasResourceValue(ResourceType type, String name) { + Map<String, ResourceValue> map = mResourceItems.get(type); + return map != null && map.containsKey(name); + } + + @Override + public ResourceValue getValue(ResourceType type, String name) { + // get the list for the given type + Map<String, ResourceValue> list = mResourceItems.get(type); + + if (list != null) { + return list.get(name); + } + + return null; + } +} |