| /* |
| * Copyright 2000-2014 JetBrains s.r.o. |
| * |
| * 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.intellij.util.descriptors.impl; |
| |
| import com.intellij.openapi.Disposable; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.openapi.util.Disposer; |
| import com.intellij.openapi.util.MultiValuesMap; |
| import com.intellij.openapi.util.SimpleModificationTracker; |
| import com.intellij.openapi.vfs.*; |
| import com.intellij.util.EventDispatcher; |
| import com.intellij.util.descriptors.*; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import java.util.Collection; |
| import java.util.HashSet; |
| import java.util.Map; |
| import java.util.Set; |
| |
| /** |
| * @author nik |
| */ |
| public class ConfigFileContainerImpl extends SimpleModificationTracker implements ConfigFileContainer { |
| private final Project myProject; |
| private final EventDispatcher<ConfigFileListener> myDispatcher = EventDispatcher.create(ConfigFileListener.class); |
| private final MultiValuesMap<ConfigFileMetaData, ConfigFile> myConfigFiles = new MultiValuesMap<ConfigFileMetaData, ConfigFile>(); |
| private ConfigFile[] myCachedConfigFiles; |
| private final ConfigFileMetaDataProvider myMetaDataProvider; |
| private final ConfigFileInfoSetImpl myConfiguration; |
| |
| public ConfigFileContainerImpl(final Project project, final ConfigFileMetaDataProvider descriptorMetaDataProvider, |
| final ConfigFileInfoSetImpl configuration) { |
| myConfiguration = configuration; |
| myMetaDataProvider = descriptorMetaDataProvider; |
| myProject = project; |
| VirtualFileManager.getInstance().addVirtualFileListener(new VirtualFileAdapter() { |
| @Override |
| public void propertyChanged(@NotNull final VirtualFilePropertyEvent event) { |
| fileChanged(event.getFile()); |
| } |
| |
| @Override |
| public void fileMoved(@NotNull final VirtualFileMoveEvent event) { |
| fileChanged(event.getFile()); |
| } |
| }, this); |
| myConfiguration.setContainer(this); |
| } |
| |
| private void fileChanged(final VirtualFile file) { |
| for (ConfigFile descriptor : myConfigFiles.values()) { |
| final VirtualFile virtualFile = descriptor.getVirtualFile(); |
| if (virtualFile != null && VfsUtilCore.isAncestor(file, virtualFile, false)) { |
| myConfiguration.updateConfigFile(descriptor); |
| fireDescriptorChanged(descriptor); |
| } |
| } |
| } |
| |
| @Override |
| @Nullable |
| public ConfigFile getConfigFile(ConfigFileMetaData metaData) { |
| final Collection<ConfigFile> descriptors = myConfigFiles.get(metaData); |
| if (descriptors == null || descriptors.isEmpty()) { |
| return null; |
| } |
| return descriptors.iterator().next(); |
| } |
| |
| @Override |
| public ConfigFile[] getConfigFiles() { |
| if (myCachedConfigFiles == null) { |
| final Collection<ConfigFile> descriptors = myConfigFiles.values(); |
| myCachedConfigFiles = descriptors.toArray(new ConfigFile[descriptors.size()]); |
| } |
| return myCachedConfigFiles; |
| } |
| |
| @Override |
| public Project getProject() { |
| return myProject; |
| } |
| |
| @Override |
| public void addListener(final ConfigFileListener listener, final Disposable parentDisposable) { |
| myDispatcher.addListener(listener, parentDisposable); |
| } |
| |
| public void fireDescriptorChanged(final ConfigFile descriptor) { |
| incModificationCount(); |
| myDispatcher.getMulticaster().configFileChanged(descriptor); |
| } |
| |
| |
| @Override |
| public ConfigFileInfoSet getConfiguration() { |
| return myConfiguration; |
| } |
| |
| @Override |
| public void dispose() { |
| } |
| |
| @Override |
| public void addListener(final ConfigFileListener listener) { |
| myDispatcher.addListener(listener); |
| } |
| |
| @Override |
| public void removeListener(final ConfigFileListener listener) { |
| myDispatcher.removeListener(listener); |
| } |
| |
| public ConfigFileMetaDataProvider getMetaDataProvider() { |
| return myMetaDataProvider; |
| } |
| |
| public void updateDescriptors(final MultiValuesMap<ConfigFileMetaData, ConfigFileInfo> descriptorsMap) { |
| Set<ConfigFile> toDelete = new HashSet<ConfigFile>(myConfigFiles.values()); |
| Set<ConfigFile> added = new HashSet<ConfigFile>(); |
| |
| for (Map.Entry<ConfigFileMetaData, Collection<ConfigFileInfo>> entry : descriptorsMap.entrySet()) { |
| ConfigFileMetaData metaData = entry.getKey(); |
| Set<ConfigFileInfo> newDescriptors = new HashSet<ConfigFileInfo>(entry.getValue()); |
| final Collection<ConfigFile> oldDescriptors = myConfigFiles.get(metaData); |
| if (oldDescriptors != null) { |
| for (ConfigFile descriptor : oldDescriptors) { |
| if (newDescriptors.contains(descriptor.getInfo())) { |
| newDescriptors.remove(descriptor.getInfo()); |
| toDelete.remove(descriptor); |
| } |
| } |
| } |
| for (ConfigFileInfo configuration : newDescriptors) { |
| final ConfigFileImpl configFile = new ConfigFileImpl(this, configuration); |
| Disposer.register(this, configFile); |
| myConfigFiles.put(metaData, configFile); |
| added.add(configFile); |
| } |
| } |
| |
| for (ConfigFile descriptor : toDelete) { |
| myConfigFiles.remove(descriptor.getMetaData(), descriptor); |
| Disposer.dispose(descriptor); |
| } |
| |
| myCachedConfigFiles = null; |
| for (ConfigFile configFile : added) { |
| incModificationCount(); |
| myDispatcher.getMulticaster().configFileAdded(configFile); |
| } |
| for (ConfigFile configFile : toDelete) { |
| incModificationCount(); |
| myDispatcher.getMulticaster().configFileRemoved(configFile); |
| } |
| } |
| } |