/* * Copyright (C) 2013 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.tools.idea.rendering; import com.android.annotations.NonNull; import com.android.ide.common.res2.ResourceFile; import com.android.ide.common.res2.ResourceItem; import com.android.ide.common.resources.configuration.FolderConfiguration; import com.android.resources.ResourceFolderType; import com.google.common.base.Splitter; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Iterators; import com.google.common.collect.Multimap; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; import java.io.File; import java.util.Collection; import java.util.Iterator; import java.util.List; class PsiResourceFile extends ResourceFile implements Iterable<ResourceItem> { private static final File DUMMY_FILE = new File(""); private PsiFile myFile; private String myName; private ResourceFolderType myFolderType; private FolderConfiguration myFolderConfiguration; private Multimap<String, ResourceItem> myDuplicates; public PsiResourceFile(@NonNull PsiFile file, @NonNull ResourceItem item, @NonNull String qualifiers, @NonNull ResourceFolderType folderType, @NonNull FolderConfiguration folderConfiguration) { super(DUMMY_FILE, item, qualifiers); myFile = file; myName = file.getName(); myFolderType = folderType; myFolderConfiguration = folderConfiguration; } public PsiResourceFile(@NonNull PsiFile file, @NonNull List<ResourceItem> items, @NonNull String qualifiers, @NonNull ResourceFolderType folderType, @NonNull FolderConfiguration folderConfiguration) { super(DUMMY_FILE, items, qualifiers); myFile = file; myName = file.getName(); myFolderType = folderType; myFolderConfiguration = folderConfiguration; } @NonNull public PsiFile getPsiFile() { return myFile; } @NonNull @Override public File getFile() { if (mFile == null || mFile == DUMMY_FILE) { VirtualFile virtualFile = myFile.getVirtualFile(); if (virtualFile != null) { mFile = VfsUtilCore.virtualToIoFile(virtualFile); } else { mFile = super.getFile(); } } return mFile; } public String getName() { return myName; } ResourceFolderType getFolderType() { return myFolderType; } FolderConfiguration getFolderConfiguration() { return myFolderConfiguration; } public void setPsiFile(@NonNull PsiFile psiFile, String qualifiers) { mFile = null; myFile = psiFile; setQualifiers(qualifiers); myFolderConfiguration = FolderConfiguration.getConfigFromQualifiers(Splitter.on('-').split(qualifiers)); myFolderType = ResourceHelper.getFolderType(psiFile); } @Override public void addItems(@NonNull Iterable<ResourceItem> items) { for (ResourceItem item : items) { addItem(item); } } @Override public void removeItems(@NonNull Iterable<ResourceItem> items) { for (ResourceItem item : items) { removeItem(item); } } @Override public void addItem(@NonNull ResourceItem item) { item.setSource(this); String key = item.getKey(); ResourceItem prev = mItems.get(key); if (prev != null) { // There are duplicates. We need to track these separately since the normal data file // only contains a single key position. if (myDuplicates == null) { myDuplicates = ArrayListMultimap.create(); } myDuplicates.put(key, prev); } mItems.put(key, item); } @Override public void removeItem(ResourceItem item) { String key = item.getKey(); if (myDuplicates != null) { Collection<ResourceItem> prev = myDuplicates.get(key); if (prev != null && prev.contains(item)) { myDuplicates.remove(key, item); if (myDuplicates.isEmpty()) { myDuplicates = null; } item.setSource(null); return; } } mItems.remove(key); item.setSource(null); // If we removed an item and we have duplicates in the wings, shift one of those into the prime position if (myDuplicates != null) { Collection<ResourceItem> prev = myDuplicates.get(key); if (prev != null && !prev.isEmpty()) { ResourceItem first = prev.iterator().next(); myDuplicates.remove(key, first); mItems.put(key, first); if (myDuplicates.isEmpty()) { myDuplicates = null; } } } } @Override public void replace(@NonNull ResourceItem oldItem, @NonNull ResourceItem newItem) { removeItem(oldItem); addItem(newItem); } @Override public Iterator<ResourceItem> iterator() { if (myDuplicates == null) { return mItems.values().iterator(); } return Iterators.concat(mItems.values().iterator(), myDuplicates.values().iterator()); } }