All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.android.ide.common.resources.MultiResourceFile Maven / Gradle / Ivy

There is a newer version: 25.3.0
Show newest version
/*
 * 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}.
 * 

* This is typically an XML file inside res/values. */ public final class MultiResourceFile extends ResourceFile implements IValueResourceRepository { private static final SAXParserFactory sParserFactory = SAXParserFactory.newInstance(); private final Map> mResourceItems = new EnumMap>(ResourceType.class); private Collection 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> oldResourceItems = new EnumMap>(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 getResourceTypes() { return mResourceTypeList; } @Override public boolean hasResources(ResourceType type) { Map list = mResourceItems.get(type); return (list != null && !list.isEmpty()); } private void updateResourceItems(ScanningContext context) { ResourceRepository repository = getRepository(); // remove this file from all existing ResourceItem. repository.removeFile(mResourceTypeList, this); for (ResourceType type : mResourceTypeList) { Map list = mResourceItems.get(type); if (list != null) { Collection 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 list = mResourceItems.get(resType); // if the list does not exist, create it. if (list == null) { list = new HashMap(); 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 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 list = mResourceItems.get(type); if (list != null) { return list.get(name); } return null; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy