package cideplus.ui.configuration;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import cideplus.FeaturerPlugin;
import cideplus.model.ASTNodeReference;
import cideplus.model.CompilationUnitFeaturesModel;
import cideplus.model.Feature;
import cideplus.model.FeaturesUtil;
import cideplus.model.exceptions.FeatureNotFoundException;
import cideplus.ui.editor.FeaturerCompilationUnitEditor;
import cideplus.ui.presentation.FeaturesMarker;
/**
* Class utilit�ria para trabalhar com a configura��o das features junto a Interface Gr�fica
* @author rogel
*
*/
public class FeaturesConfigurationUtil {
public static final String FEATURES_FILE = "features.feat";
private static Map<IProject, IFeaturesManager> projectCache = new HashMap<IProject, IFeaturesManager>();
public static IFeaturesManager getFeaturesManager(final IProject project){
IFeaturesManager featuresManager;
if((featuresManager = projectCache.get(project)) == null){
if (FeaturerPlugin.DEBUG_MANAGER_CACHE)
System.out.println("projectCache MISS");
featuresManager = new IFeaturesManager() {
Map<ICompilationUnit, ICompilationUnitFeaturesManager> compUnitCache = new HashMap<ICompilationUnit, ICompilationUnitFeaturesManager>();
@Override
public void saveFeatures(Set<Feature> features) throws CoreException {
FeaturesConfigurationUtil.saveFeatures(project, features);
}
@Override
public Set<Feature> getFeatures() throws CoreException, IOException {
return FeaturesConfigurationUtil.getFeatures(project);
}
@Override
public IProject getProject() {
return project;
}
@Override
public ICompilationUnitFeaturesManager getManagerForFile(final IFile file) throws IOException, FeatureNotFoundException, CoreException {
ICompilationUnit compilationUnit = (ICompilationUnit) JavaCore.create(file);
return getManagerForFile(compilationUnit);
}
@Override
public ICompilationUnitFeaturesManager getManagerForFile(final ICompilationUnit compilationUnit) throws IOException, CoreException, FeatureNotFoundException {
ICompilationUnitFeaturesManager compilationUnitFeaturesManager;
if((compilationUnitFeaturesManager = compUnitCache.get(compilationUnit)) == null){
if (FeaturerPlugin.DEBUG_MANAGER_CACHE)
System.out.println("compUnitCache MISS\n");
IPath path = compilationUnit.getPath().removeFileExtension().addFileExtension("feat");
final IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
final CompilationUnitFeaturesModel model;
if(file.exists()){
model = FeaturesUtil.loadFeaturesForCompilationUnit(getFeatures(), file.getContents(true));
} else {
model = new CompilationUnitFeaturesModel();
}
// compilationUnitFeaturesManager = new CompilationUnitFeaturesManager(model, compilationUnit);
compilationUnitFeaturesManager = new ICompilationUnitFeaturesManager() {
@Override
public Set<ASTNodeReference> getNodeReferences() {
return model.getNodeReferences();
}
private Set<Feature> getASTFeatures(ASTNode astNode) {
if(astNode == null){
return new HashSet<Feature>();
}
return model.getFeatures(getNodeReferenceFromAST(astNode), true);
}
@Override
public void setFeature(ASTNode astNode, Feature feature) {
if(astNode == null)
throw new IllegalArgumentException("AST node cannot be null to set feature");
getASTFeatures(astNode).add(feature);
/* Um marker associado com cada feature. */
try {
FeaturesMarker.createMarker(astNode, feature.getId());
} catch (CoreException e) {
System.out.println("Could not create marker for feature " + feature.getName());
e.printStackTrace();
}
}
@Override
public boolean hasFeature(ASTNode astNode, Feature feature) {
return getASTFeatures(astNode).contains(feature);
}
@Override
public Set<Feature> getFeatures(ASTNode astNode) {
return getASTFeatures(astNode);
}
@Override
public Set<Feature> getFeatures(ASTNodeReference reference){
return model.getFeatures(reference);
}
@Override
public void removeFeature(ASTNode node, Feature feature) {
getASTFeatures(node).remove(feature);
try {
IMarker marker = FeaturesMarker.getCorrespondingMarker(node, feature.getId());
if (marker != null)
marker.delete();
} catch (CoreException e) {
e.printStackTrace();
}
}
@Override
public synchronized void commitChanges() throws CoreException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
FeaturesUtil.saveFeaturesForCompilationUnit(out, model);
ByteArrayInputStream source = new ByteArrayInputStream(out.toByteArray());
if(file.exists()){
file.setContents(source, true, false, null);
} else {
file.create(source, true, null);
}
}
@Override
public ICompilationUnit getCompilationUnit() {
return compilationUnit;
}
};
compUnitCache.put(compilationUnit, compilationUnitFeaturesManager);
}
else {
if (FeaturerPlugin.DEBUG_MANAGER_CACHE)
System.out.println("compUnitCache HIT\n");
}
return compilationUnitFeaturesManager;
}
};
//o project feature manager nao possuirá cache... apenas o compilation unit
//projectCache.put(project, featuresManager);
}
else {
if (FeaturerPlugin.DEBUG_MANAGER_CACHE) System.out.println("projectCache HIT");
}
return featuresManager;
}
public static Set<Feature> getFeatures(IProject project) throws CoreException, IOException {
IFile featuresFile = project.getFile(FEATURES_FILE);
Set<Feature> features;
if(featuresFile.exists()){
features = FeaturesUtil.readFeatures(featuresFile.getContents(true));
} else {
features = new TreeSet<Feature>();
}
return features;
}
// TODO: Não iterar nas features para buscar o id.
public static Feature getFeature(IProject project, int featureId) throws CoreException, IOException {
if (project != null) {
Set<Feature> features = getFeatures(project);
for (Feature feature : features) {
if (feature.getId() == featureId) {
return feature;
}
}
// TODO: Verificar o impacto de lançar uma exception aqui
// ao invés de retornar null
// throw new FeatureNotFoundException(featureId);
}
else {
System.out.println("PluginUtils.getFeature(): project is NULL!");
}
return null;
}
private static void saveFeatures(IProject project, Set<Feature> features) throws CoreException {
IFile featuresFile = project.getFile(FEATURES_FILE);
ByteArrayOutputStream out = new ByteArrayOutputStream();
FeaturesUtil.saveFeatures(out, features);
if(featuresFile.exists()){
featuresFile.setContents(new ByteArrayInputStream(out.toByteArray()), true, false, null);
} else {
featuresFile.create(new ByteArrayInputStream(out.toByteArray()), true, null);
}
}
private static ASTNodeReference getNodeReferenceFromAST(ASTNode astNode) {
return new ASTNodeReference(astNode);
}
public static RGB getRGB(Feature feature){
return new RGB(feature.getRgb().getRed(), feature.getRgb().getGreen(), feature.getRgb().getBlue());
}
public static RGB getCombinedRGB(Collection<Feature> featureList) {
RGB rgb = new RGB(0,0,0);
int amountRed = 0;
int amountGreen = 0;
int amountBlue = 0;
if (featureList.size() > 0) {
for (Feature feature : featureList) {
if(feature.getRgb().getRed() > 0){
amountRed+=1;
}
if(feature.getRgb().getGreen() > 0){
amountGreen += 1;
}
if(feature.getRgb().getBlue() > 0){
amountBlue +=1;
}
rgb.red += feature.getRgb().getRed();
rgb.green += feature.getRgb().getGreen();
rgb.blue += feature.getRgb().getBlue();
}
if(amountRed > 0){
rgb.red /= amountRed;
}
if(amountGreen > 0){
rgb.green /= amountGreen;
}
if(amountBlue > 0){
rgb.blue /= amountBlue;
}
} else {
rgb = new RGB(255,255,255);
}
return rgb;
}
public static void clean() {
projectCache = new HashMap<IProject, IFeaturesManager>();
}
public static void updateEditors(Display display, final ASTNode compilationUnit) {
display.asyncExec(new Runnable() {
@Override
public void run() {
doUpdateEditors(compilationUnit);
}
});
}
private static void doUpdateEditors(ASTNode compilationUnit) {
//atualizar os editores
IWorkbenchWindow[] workbenchWindows = PlatformUI.getWorkbench().getWorkbenchWindows();
for (IWorkbenchWindow iWorkbenchWindow : workbenchWindows) {
IEditorReference[] editorReferences = iWorkbenchWindow.getActivePage().getEditorReferences();
for (IEditorReference iEditorReference : editorReferences) {
String editorName = iEditorReference.getName();
if(compilationUnit != null){
String compilationUnitName = ((CompilationUnit) compilationUnit).getJavaElement().getElementName();
if(editorName.equals(compilationUnitName)){
refresh(iEditorReference);
}
} else {
//se o compilation unit é null, atualizar todos os editores
refresh(iEditorReference);
}
}
}
}
private static void refresh(IEditorReference iEditorReference) {
IEditorPart editor = iEditorReference.getEditor(false);
if(editor instanceof FeaturerCompilationUnitEditor){
((FeaturerCompilationUnitEditor) editor).getViewer().invalidateTextPresentation();
// FeaturerCompilationUnitEditor fcue = (FeaturerCompilationUnitEditor) editor;
// fcue.getColorPresentation().refreshFeatures();
// ISourceViewer viewer = fcue.getViewer();
// viewer.invalidateTextPresentation();
}
}
}