/*
* Copyright 2011 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.inferencing.suggestions;
import java.io.ByteArrayInputStream;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.codehaus.groovy.eclipse.dsl.GroovyDSLCoreActivator;
import org.codehaus.groovy.eclipse.dsl.inferencing.suggestions.writer.SuggestionsFile;
import org.codehaus.groovy.eclipse.dsl.inferencing.suggestions.writer.SuggestionsTransform;
import org.codehaus.jdt.groovy.model.GroovyNature;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
/**
*
* @author Nieraj Singh
* @created 2011-05-09
*/
public class InferencingSuggestionsManager {
private Map<IProject, ProjectSuggestions> perProjectSuggestions;
private static InferencingSuggestionsManager manager;
private IProject lastModifiedProject;
private InferencingSuggestionsManager() {
// Singleton
}
public static InferencingSuggestionsManager getInstance() {
if (manager == null) {
manager = new InferencingSuggestionsManager();
}
return manager;
}
/**
* For now support per project commits
*
* @return true if changes for given project are successfully committed.
* False otherwise
*/
public boolean commitChanges(IProject project) {
// don't commit if the project is not accessible
if (!isValidProject(project)) {
return false;
}
// Keep track of the last project that was modified
lastModifiedProject = project;
ProjectSuggestions suggestions = getSuggestions(project);
SuggestionsTransform transform = new SuggestionsTransform(suggestions);
String result = transform.transform();
if (result != null) {
SuggestionsFile suggestionsFile = new SuggestionsFile(project);
IFile file = suggestionsFile.createFile();
writeToFile(file, result);
return true;
}
return false;
}
/**
* Restores the suggestions for an accessible project back in the
* suggestions model.
* If the project is not accessible, it removes all the suggestions from the
* model, as the model
* should reflect whether the suggestions in the file can be read or not.
*
* @param project
* @return true if suggestions are restored or if project is not accessible,
* suggestions in memory are cleared. False if no restoration took
* place
*/
public boolean restoreSuggestions(IProject project) {
// For now restore from XML
if (isValidProject(project)) {
SuggestionsFile suggestionFile = new SuggestionsFile(project);
IFile file = suggestionFile.getFile();
if (file != null && file.exists()) {
return new SuggestionsLoader(file).loadExistingSuggestions();
}
}
// If restoring was not possible, remove suggestions from model
ProjectSuggestions suggestions = getSuggestions(project);
if (suggestions != null) {
suggestions.removeAll();
return true;
}
return false;
}
public boolean isValidProject(IProject project) {
return project != null && project.isAccessible() && GroovyNature.hasGroovyNature(project);
}
/**
*
* FIXNS: Hook to a resource change listener in the future.
*
* @return gets the last project that had suggestion commits. It may be null
* including if the last modified project is no longer accessible.
*/
public IProject getlastModifiedProject() {
if (isValidProject(lastModifiedProject)) {
return lastModifiedProject;
}
// Otherwise, clear the last modified project
return lastModifiedProject = null;
}
protected void writeToFile(IFile file, String value) {
if (file != null) {
try {
// For now replace all the contents
file.setContents(new ByteArrayInputStream(value.getBytes()), true, true, new NullProgressMonitor());
} catch (CoreException e) {
GroovyDSLCoreActivator.logException(e);
}
}
}
/**
* Not null, unless it is not an accessible Groovy project. may be empty.
* Original copy.
*
* @param project
* @return Non-null suggestions for any accessible Groovy project. Null
* otherwise
*/
public ProjectSuggestions getSuggestions(IProject project) {
// Only Groovy Projects have suggestions
if (!isValidProject(project)) {
return null;
}
if (perProjectSuggestions == null) {
perProjectSuggestions = new HashMap<IProject, ProjectSuggestions>();
}
ProjectSuggestions projectSuggestions = perProjectSuggestions.get(project);
if (projectSuggestions == null) {
projectSuggestions = new ProjectSuggestions(project);
perProjectSuggestions.put(project, projectSuggestions);
}
return projectSuggestions;
}
public class ProjectSuggestions {
private Map<String, GroovySuggestionDeclaringType> suggestions;
private IProject project;
protected ProjectSuggestions(IProject project) {
suggestions = new HashMap<String, GroovySuggestionDeclaringType>();
this.project = project;
}
/**
*
* @return a new, clean project suggestion, registered in the
* suggestions manager, for the project associated with the
* current project selection. All
* current suggestions will be deleted.
*/
public ProjectSuggestions registerNewProjectSuggestion() {
suggestions.clear();
ProjectSuggestions cleanProjectSuggestions = new ProjectSuggestions(project);
perProjectSuggestions.put(project, cleanProjectSuggestions);
return cleanProjectSuggestions;
}
/**
* May be null if no suggestions have ever been added to the specified
* declaring
* type before. Declaring types cannot exist
* by them selves without at least one suggestion
*
* @param declaringTypeName
* @return
*/
public GroovySuggestionDeclaringType getExactDeclaringType(String declaringTypeName) {
return suggestions.get(declaringTypeName);
}
/**
* Creates a declaring type or returns an existing one.
*
* @param declaringTypeName
* @return
*/
public IGroovySuggestion addSuggestion(SuggestionDescriptor descriptor) {
String declaringTypeName = descriptor.getDeclaringTypeName();
GroovySuggestionDeclaringType declaringType = suggestions.get(declaringTypeName);
if (declaringType == null) {
declaringType = new GroovySuggestionDeclaringType(declaringTypeName);
}
IGroovySuggestion createdSuggestion = declaringType.createSuggestion(descriptor);
// Don't add a new declaring type unless a suggestion was
// successfully created
if (createdSuggestion != null && !suggestions.containsKey(declaringType.getName())) {
suggestions.put(declaringTypeName, declaringType);
}
return createdSuggestion;
}
public void removeDeclaringType(GroovySuggestionDeclaringType declaringType) {
suggestions.remove(declaringType.getName());
}
/**
* Removes all declaring types from the suggestions model for this
* project
*/
public void removeAll() {
suggestions.clear();
}
/**
*
* @return all the declaring types. Never null, but may be empty
*/
public Collection<GroovySuggestionDeclaringType> getDeclaringTypes() {
return suggestions.values();
}
}
}