/**
* Copyright (c) 2015 Codetrails GmbH.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Marcel Bruch - initial API and implementation.
* Johannes Dorn - Refactoring
*/
package org.eclipse.recommenders.internal.types.rcp;
import static org.eclipse.jdt.core.IJavaElement.*;
import static org.eclipse.jdt.core.IJavaElementDelta.*;
import java.io.IOException;
import java.util.Set;
import javax.inject.Inject;
import org.eclipse.jdt.core.ElementChangedEvent;
import org.eclipse.jdt.core.IElementChangedListener;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaElementDelta;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.recommenders.internal.types.rcp.l10n.LogMessages;
import org.eclipse.recommenders.utils.Logs;
import org.eclipse.recommenders.utils.names.ITypeName;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchListener;
import org.eclipse.ui.PlatformUI;
public class TypesIndexService implements ITypesIndexService, IElementChangedListener {
private final IIndexProvider indexProvider;
@Inject
public TypesIndexService(IIndexProvider indexProvider) {
this.indexProvider = indexProvider;
JavaCore.addElementChangedListener(this, ElementChangedEvent.POST_CHANGE);
PlatformUI.getWorkbench().addWorkbenchListener(new ShutdownListener());
};
@Override
public void elementChanged(ElementChangedEvent event) {
IJavaElementDelta delta = event.getDelta();
process(delta);
}
private void process(IJavaElementDelta delta) {
IJavaElement element = delta.getElement();
IJavaProject project = element.getJavaProject();
boolean resolvedClasspathChanged = (delta.getFlags() & IJavaElementDelta.F_RESOLVED_CLASSPATH_CHANGED) != 0;
if (element instanceof IJavaProject && resolvedClasspathChanged) {
rebuildIndex(element.getJavaProject());
return;
}
if (isChildAffectedByChange(delta)) {
for (IJavaElementDelta child : delta.getAffectedChildren()) {
process(child);
}
return;
}
switch (delta.getKind()) {
case IJavaElementDelta.ADDED:
processElementAdded(element, project);
break;
case CHANGED:
processElementChanged(delta, element, project);
break;
case REMOVED:
processElementRemoved(element, project);
break;
}
}
private boolean isChildAffectedByChange(IJavaElementDelta delta) {
return (delta.getFlags() & IJavaElementDelta.F_CHILDREN) != 0;
}
private void processElementAdded(IJavaElement element, IJavaProject project) {
switch (element.getElementType()) {
case JAVA_PROJECT:
case PACKAGE_FRAGMENT_ROOT:
rebuildIndex(project);
break;
}
}
private void processElementChanged(IJavaElementDelta delta, IJavaElement element, IJavaProject project) {
if (PACKAGE_FRAGMENT_ROOT == element.getElementType()) {
boolean removed = (delta.getFlags() & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) != 0;
boolean content = (delta.getFlags() & IJavaElementDelta.F_ARCHIVE_CONTENT_CHANGED) != 0;
if (removed || content) {
rebuildIndex(project);
}
}
}
private void processElementRemoved(IJavaElement element, IJavaProject project) {
switch (element.getElementType()) {
case PACKAGE_FRAGMENT_ROOT:
rebuildIndex(project);
break;
case JAVA_PROJECT:
removeProjectIndex(project);
break;
}
}
private void rebuildIndex(IJavaProject project) {
IProjectTypesIndex index = indexProvider.findIndex(project).orNull();
if (index == null) {
return;
}
index.suggestRebuild();
}
private void removeProjectIndex(IJavaProject project) {
indexProvider.deleteIndex(project);
}
@Override
public Set<String> subtypes(ITypeName expected, IJavaProject project) {
IProjectTypesIndex index = indexProvider.findOrCreateIndex(project);
return index.subtypes(expected);
}
private final class ShutdownListener implements IWorkbenchListener {
@Override
public boolean preShutdown(IWorkbench workbench, boolean forced) {
return true;
}
@Override
public void postShutdown(IWorkbench workbench) {
try {
indexProvider.close();
} catch (IOException e) {
Logs.log(LogMessages.ERROR_CLOSING_PROJECT_TYPES_INDEXES, e);
}
}
}
}