package jetbrains.mps.watching;
/*Generated by MPS */
import com.intellij.openapi.components.ApplicationComponent;
import jetbrains.mps.library.AdditionalLibrariesManager;
import jetbrains.mps.classloading.ClassLoaderManager;
import jetbrains.mps.classloading.MPSClassesListener;
import java.util.Map;
import jetbrains.mps.library.Library;
import com.intellij.openapi.vfs.LocalFileSystem;
import java.util.HashMap;
import jetbrains.mps.ide.platform.watching.WatchedRoots;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.project.ProjectManagerAdapter;
import jetbrains.mps.ide.MPSCoreComponents;
import org.jetbrains.annotations.NotNull;
import com.intellij.openapi.project.Project;
import jetbrains.mps.project.ProjectLibraryManager;
import java.util.Set;
import java.util.HashSet;
import java.util.List;
import java.util.Collection;
import java.util.ArrayList;
/**
* This should probably be gone.
* It listens for library changes, class reloads and refreshes library watched paths.
*/
public class WatchedRootsUpdater implements ApplicationComponent {
private final AdditionalLibrariesManager myLibraryManager;
private final ClassLoaderManager myClassLoaderManager;
private MPSClassesListener myClassesListener;
private final Map<Library, LocalFileSystem.WatchRequest> myLibrariesRequests = new HashMap<Library, LocalFileSystem.WatchRequest>();
private final Map<Library, LocalFileSystem.WatchRequest> myProjectLibrariesRequests = new HashMap<Library, LocalFileSystem.WatchRequest>();
private final LocalFileSystem myLocalFileSystem;
private final WatchedRoots myWatchedRootsBase;
private final ProjectManager myProjectManager;
private ProjectManagerAdapter myProjectManagerListener;
public WatchedRootsUpdater(LocalFileSystem lfs, WatchedRoots watchedRoots, MPSCoreComponents coreComponents, AdditionalLibrariesManager libraryManager, ProjectManager projectManager) {
myLibraryManager = libraryManager;
myProjectManager = projectManager;
myClassLoaderManager = coreComponents.getClassLoaderManager();
myLocalFileSystem = lfs;
myWatchedRootsBase = watchedRoots;
}
@NotNull
@Override
public String getComponentName() {
return "Watched Roots Updater";
}
@Override
public void initComponent() {
processLibrariesChange();
myProjectManagerListener = new ProjectManagerAdapter() {
@Override
public void projectOpened(Project project) {
processLibrariesChange(project.getComponent(ProjectLibraryManager.class).getUILibraries(), myProjectLibrariesRequests);
}
@Override
public void projectClosing(Project project) {
processLibrariesChange(project.getComponent(ProjectLibraryManager.class).getUILibraries(), myProjectLibrariesRequests);
}
};
myProjectManager.addProjectManagerListener(myProjectManagerListener);
}
private void processLibrariesChange() {
processLibrariesChange(myLibraryManager.getUILibraries(), myLibrariesRequests);
processProjectLibrariesChange();
}
private void processProjectLibrariesChange() {
Set<Library> libs = new HashSet<Library>();
for (Project p : myProjectManager.getOpenProjects()) {
libs.addAll(p.getComponent(ProjectLibraryManager.class).getUILibraries());
}
processLibrariesChange(libs, myProjectLibrariesRequests);
}
private void processLibrariesChange(Set<Library> currentLibraries, Map<Library, LocalFileSystem.WatchRequest> libraryToRequest) {
List<Library> toRemove = librarySubtract(libraryToRequest.keySet(), currentLibraries);
List<Library> toAdd = librarySubtract(currentLibraries, libraryToRequest.keySet());
removeLibraryWatch(toRemove, libraryToRequest);
addLibraryWatch(toAdd, libraryToRequest);
}
private void addLibraryWatch(List<Library> toAdd, Map<Library, LocalFileSystem.WatchRequest> librariesRequests) {
for (Library l : toAdd) {
LocalFileSystem.WatchRequest watchRequest = myLocalFileSystem.addRootToWatch(l.getPath(), true);
librariesRequests.put(l, watchRequest);
}
}
private void removeLibraryWatch(List<Library> toRemove, Map<Library, LocalFileSystem.WatchRequest> librariesRequests) {
for (Library l : toRemove) {
final LocalFileSystem.WatchRequest watchRequest = librariesRequests.get(l);
if (watchRequest != null) {
myLocalFileSystem.removeWatchedRoot(watchRequest);
}
librariesRequests.remove(l);
}
}
private List<Library> librarySubtract(Collection<Library> from, Collection<Library> what) {
List<Library> result = new ArrayList<Library>();
for (Library pattern : from) {
boolean found = false;
for (Library possibleMatching : what) {
if (pattern.getPath().equals(possibleMatching.getPath())) {
found = true;
break;
}
}
if (!(found)) {
result.add(pattern);
}
}
return result;
}
@Override
public void disposeComponent() {
myClassLoaderManager.removeClassesHandler(myClassesListener);
myProjectManager.removeProjectManagerListener(myProjectManagerListener);
}
}