/*
* Copyright 2009-2017 the original author or authors.
*
* 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 org.codehaus.groovy.eclipse.dsl;
import org.codehaus.groovy.eclipse.GroovyLogManager;
import org.codehaus.groovy.eclipse.TraceCategory;
import org.codehaus.groovy.eclipse.dsl.inferencing.suggestions.SuggestionsLoader;
import org.codehaus.groovy.eclipse.dsl.inferencing.suggestions.writer.SuggestionsFileProperties;
import org.codehaus.groovy.eclipse.dsl.script.DSLDScriptExecutor;
import org.codehaus.jdt.groovy.model.GroovyNature;
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.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.JavaCore;
/**
* Handles updates and changes of DSLD files
* Things that need to get handled:
*
* Project deletion or close: flush the context
* Project creation, or groovy nature added: refresh DSLDs for project
* DSLD script added: update that script from context
* DSLD script deleted: remove that script from context
* DSLD script changed: first remove and then re-add to context
*
* @author andrew
* @created Nov 25, 2010
*/
public class DSLDResourceListener implements IResourceChangeListener {
private class DSLDChangeResourceDeltaVisitor implements IResourceDeltaVisitor {
private final int eventType;
private DSLDChangeResourceDeltaVisitor(int eventType) {
this.eventType = eventType;
}
public boolean visit(IResourceDelta delta) throws CoreException {
IResource deltaResource = delta.getResource();
if (deltaResource.isDerived()) {
// fail fast
return false;
}
if (deltaResource.getType() == IResource.PROJECT) {
IProject project = (IProject) deltaResource;
// two possibilities handled here:
// project being closed/deleted/groovy nature removed
// project being opened.
if ((eventType == IResourceChangeEvent.PRE_DELETE && delta.getKind() == IResourceDelta.REMOVED)
|| eventType == IResourceChangeEvent.PRE_CLOSE ||
// just in case nature has been removed for this project
!GroovyNature.hasGroovyNature(project)) {
// no longer managing state for this project
if (GroovyLogManager.manager.hasLoggers()) {
GroovyLogManager.manager.log(TraceCategory.DSL, "Deleting DSL context for: " + project.getName());
}
contextStoreManager.clearDSLDStore(project);
return false;
} else if (!contextStoreManager.hasDSLDStoreFor(project) && GroovyNature.hasGroovyNature(project)) {
// could be that this project has just been opened
GroovyDSLCoreActivator.getDefault().getContextStoreManager().initialize(project, false);
return false;
}
// not opening or closing the project, just check to see if we
// still care about it
if (!GroovyNature.hasGroovyNature(project)) {
return false;
}
} else if (deltaResource.getType() == IResource.FILE) {
// at this point, we know that we are in a groovy project
IFile file = (IFile) deltaResource;
if (isDSLDFile(file) || isXDSL(file)) {
IProject project = file.getProject();
DSLDStore store = contextStoreManager.getDSLDStore(project);
Assert.isNotNull(store, "Context store should not be null");
if (GroovyLogManager.manager.hasLoggers()) {
GroovyLogManager.manager.log(TraceCategory.DSL, "Processing " + file.getName());
}
// this file has been changed or deleted. Either way, must
// start by purging
// if this file diden't exist in the past, then this is a
// no-op
store.purgeIdentifier(file);
if (file.isAccessible() && eventType == IResourceChangeEvent.POST_CHANGE) {
// also refresh the file
if (isDSLDFile(file)) {
DSLDScriptExecutor executor = new DSLDScriptExecutor(JavaCore.create(project));
executor.executeScript(file);
} else if (isXDSL(file)) {
// At this point the suggestions should already be in the manager. only contribution groups
// and point cuts need to be created
new SuggestionsLoader(file).addSuggestionsContributionGroup();
}
}
}
}
// we know that we are in a groovy project
// so keep on trudging through the delta
return true;
}
}
private static final DSLDStoreManager contextStoreManager = GroovyDSLCoreActivator.getDefault().getContextStoreManager();
public void resourceChanged(IResourceChangeEvent event) {
switch (event.getType()) {
case IResourceChangeEvent.PRE_DELETE:
case IResourceChangeEvent.PRE_CLOSE:
case IResourceChangeEvent.POST_CHANGE:
try {
if (event.getDelta() != null) {
event.getDelta().accept(new DSLDChangeResourceDeltaVisitor(event.getType()));
}
} catch (CoreException e) {
GroovyDSLCoreActivator.logException(e);
}
}
}
/**
* @param file
* @return
*/
public boolean isDSLDFile(IFile file) {
String fileExtension = file.getFileExtension();
return fileExtension != null && fileExtension.equals("dsld");
}
public boolean isXDSL(IFile file) {
String fileExtension = file.getFileExtension();
return fileExtension != null && fileExtension.equals(SuggestionsFileProperties.FILE_TYPE);
}
}