blob: 59b1b9601d900bd5c5706515026c6f7b0a12adcb [file] [log] [blame]
/*
* 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);
}
}
}