package net.sourceforge.c4jplugin.internal.core;
import java.util.Collection;
import java.util.HashSet;
import net.sourceforge.c4jplugin.internal.decorators.C4JDecorator;
import net.sourceforge.c4jplugin.internal.nature.C4JProjectNature;
import net.sourceforge.c4jplugin.internal.util.ContractReferenceUtil;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.ui.IDecoratorManager;
import org.eclipse.ui.PlatformUI;
public class ResourceChangeListener implements IResourceChangeListener {
private IDecoratorManager decoratorManager = PlatformUI.getWorkbench().getDecoratorManager();
private ResourceDeltaVisitor deltaVisitor = new ResourceDeltaVisitor();
public void resourceChanged(IResourceChangeEvent event) {
C4JDecorator decorator = (C4JDecorator)decoratorManager.getBaseLabelProvider(C4JDecorator.ID);
IResourceDelta delta = event.getDelta();
try {
delta.accept(deltaVisitor);
Collection<IResource> visitedResources = deltaVisitor.getVisitedResources();
Collection<IResource> visitedContracts = deltaVisitor.getVisitedContracts();
for (IResource visitedResource : visitedResources) {
ContractReferenceUtil.deleteMarkers(visitedResource);
ContractReferenceUtil.createContractedClassMarkers(visitedResource);
}
for (IResource visitedContract : visitedContracts) {
ContractReferenceUtil.deleteMarkers(visitedContract);
ContractReferenceUtil.createContractMarkers(visitedContract);
}
if (decorator != null) {
decorator.refresh(visitedResources);
decorator.refresh(visitedContracts);
}
deltaVisitor.clear();
} catch (CoreException e2) { }
}
private class ResourceDeltaVisitor implements IResourceDeltaVisitor {
private HashSet<IResource> visitedResources = new HashSet<IResource>();
private HashSet<IResource> allContracts = new HashSet<IResource>();
public Collection<IResource> getVisitedResources() {
return visitedResources;
}
public Collection<IResource> getVisitedContracts() {
return allContracts;
}
public void clear() {
visitedResources.clear();
allContracts.clear();
}
public boolean visit(IResourceDelta delta) throws CoreException {
IResource resource = delta.getResource();
IProject project = resource.getProject();
if (project == null) return true;
if (!project.isNatureEnabled(C4JProjectNature.NATURE_ID)) return false;
if (resource instanceof IFile && resource.getName().endsWith(".java")) {
if (delta.getKind() == IResourceDelta.REMOVED) {
if (ContractReferenceModel.isContract(resource, true)) {
handleRemovedContract(resource);
}
else {
Boolean contracted = ContractReferenceModel.isContracted(resource, true);
if (contracted != null && contracted == true) {
handleRemovedContractedClass(resource);
}
}
}
// resource changes or additions
else {
// check if the resource is a contract
if (ContractReferenceModel.isContract(resource)) {
handleChangedContract(resource);
}
else {
handleChangedResource(resource);
}
}
}
return true;
}
synchronized private void handleRemovedContract(IResource contract) {
Collection<IResource> changedResources = ContractReferenceModel.removeContract(contract);
visitedResources.addAll(changedResources);
}
synchronized private void handleRemovedContractedClass(IResource resource) {
Collection<IResource> changedContracts = ContractReferenceModel.removeContractedClass(resource);
for (IResource changedContract : changedContracts) {
Collection<IResource> contractedClasses = ContractReferenceModel.getContractedClasses(changedContract);
for (IResource contractedClass : contractedClasses) {
ContractReferenceModel.clearResource(contractedClass);
ContractReferenceUtil.checkResourceForContracts(contractedClass);
}
visitedResources.addAll(contractedClasses);
}
allContracts.addAll(changedContracts);
}
synchronized private void handleChangedContract(IResource contract) {
Collection<IResource> contractedClasses = ContractReferenceModel.getContractedClasses(contract);
ContractReferenceModel.clearResource(contract);
for (IResource contractedClass : contractedClasses) {
ContractReferenceModel.clearResource(contractedClass);
ContractReferenceUtil.checkResourceForContracts(contractedClass);
}
allContracts.add(contract);
visitedResources.addAll(contractedClasses);
}
synchronized private void handleChangedResource(IResource resource) throws CoreException {
Collection<IResource> oldContracts = ContractReferenceModel.getContractReferences(resource);
ContractReferenceModel.clearResource(resource);
Collection<IResource> contracts = ContractReferenceUtil.checkResourceForContracts(resource);
visitedResources.add(resource);
// check if the contracts have changed
boolean bChanged = true;
if (oldContracts.size() == contracts.size()) {
if (contracts.containsAll(oldContracts)) bChanged = false;
}
if (bChanged) {
// yes, check all subtypes
visitedResources.addAll(ContractReferenceUtil.checkAllSubtypes(resource, true));
}
allContracts.addAll(oldContracts);
allContracts.addAll(contracts);
}
}
}