/*******************************************************************************
* Copyright (c) 2008, 2009 Spring IDE Developers
* 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:
* Spring IDE Developers - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.core.java;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.JavaCore;
import org.springframework.core.Ordered;
import org.springframework.ide.eclipse.core.SpringCore;
import org.springframework.ide.eclipse.core.internal.model.validation.ValidatorDefinition;
import org.springframework.ide.eclipse.core.internal.project.SpringProjectContributionManager.ResourceDeltaVisitor;
import org.springframework.ide.eclipse.core.internal.project.SpringProjectContributionManager.ResourceTreeVisitor;
import org.springframework.ide.eclipse.core.project.IProjectContributionEventListener;
import org.springframework.ide.eclipse.core.project.IProjectContributor;
import org.springframework.ide.eclipse.core.project.IProjectContributorState;
import org.springframework.ide.eclipse.core.project.ProjectBuilderDefinition;
import org.springframework.ide.eclipse.core.project.ProjectContributionEventListenerAdapter;
import org.springframework.util.ClassUtils;
/**
* {@link IProjectContributionEventListener} implementation that manages the lifecycle of the {@link TypeStructureCache}.
* @author Christian Dupuis
* @since 2.2.0
* @see #updateTypeStructures(int,IProject,IResourceDelta)
*/
public class TypeStructureStateRegisteringEventListener extends ProjectContributionEventListenerAdapter implements Ordered {
/**
* {@inheritDoc}
*/
public void start(int kind, IResourceDelta delta, List<ProjectBuilderDefinition> builderDefinitions,
List<ValidatorDefinition> validatorDefinitions, IProjectContributorState state, IProject project) {
state.hold(new TypeStructureState());
}
/**
* {@inheritDoc}
*/
public void finish(int kind, IResourceDelta delta, List<ProjectBuilderDefinition> builderDefinitions,
List<ValidatorDefinition> validatorDefinitions, IProjectContributorState state, IProject project) {
try {
// Update type structures at the end of each build
updateTypeStructures(kind, project, delta);
}
catch (CoreException e) {
}
}
/**
* Updates the type structures for a given project.s
*/
private void updateTypeStructures(int kind, IProject project, IResourceDelta delta) throws CoreException {
// Record type structures
if (delta == null || kind == IncrementalProjectBuilder.FULL_BUILD
|| kind == IncrementalProjectBuilder.CLEAN_BUILD) {
// 1. full build (does not matter if state (1a) or not (1b))
recoredFullTypeStructures(project);
}
else {
// 2. incremental build and no state
if (!SpringCore.getTypeStructureCache().hasRecordedTypeStructures(project)) {
recoredFullTypeStructures(project);
}
// 3. incremental build and state
else {
JavaResourceRecordingProjectContributor contributor = new JavaResourceRecordingProjectContributor();
ResourceDeltaVisitor visitor = new ResourceDeltaVisitor(contributor, kind);
delta.accept(visitor);
SpringCore.getTypeStructureCache().recordTypeStructures(project,
visitor.getResources().toArray(new IResource[visitor.getResources().size()]));
}
}
}
/**
* Records a complete snapshot of the type structure of all java class files in the given project.
*/
private void recoredFullTypeStructures(IProject project) throws CoreException {
// remove pre-existing state as we are doing a clean build
SpringCore.getTypeStructureCache().clearStateForProject(project);
// collect all java class files
JavaResourceRecordingProjectContributor contributor = new JavaResourceRecordingProjectContributor();
ResourceTreeVisitor visitor = new ResourceTreeVisitor(contributor);
project.accept(visitor);
// record type strcutures for all collected class files
SpringCore.getTypeStructureCache().recordTypeStructures(project,
visitor.getResources().toArray(new IResource[visitor.getResources().size()]));
}
/**
* Passes through any java class file.
*/
private class JavaResourceRecordingProjectContributor implements IProjectContributor {
public void cleanup(IResource resource, IProgressMonitor monitor) throws CoreException {
// nothing to do
}
public Set<IResource> getAffectedResources(IResource resource, int kind, int deltaKind) throws CoreException {
if (resource.getName().endsWith(ClassUtils.CLASS_FILE_SUFFIX) && JavaCore.create(resource) != null) {
Set<IResource> resources = new HashSet<IResource>();
resources.add(resource);
return resources;
}
return Collections.emptySet();
}
}
/**
* {@inheritDoc}
*/
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
}