blob: 619c47029b63484c63ca8305622c1b667605fbef [file] [log] [blame]
/**
* Copyright (c) 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* IBM - Initial API and implementation
*/
package org.eclipse.emf.common.ui;
import java.util.Collections;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.emf.common.util.BasicDiagnostic;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.common.util.URI;
/**
* Provides methods to simplify the work with {@link IMarker}s. The main goal is to
* simplify the creation of markers using the information described in
* {@link Diagnostic}s.
*
* @since 2.2.0
*/
public class MarkerHelper
{
/**
* Returns the {@link Diagnostic#getSource() source} value used for {@link #getMarkerDiagnostics(Object, IFile) creating diagnostics} from markers.
* @since 2.9
*/
public String getDiagnosticSource()
{
return "org.eclipse.emf.common.ui.markers";
}
protected String getMarkerID()
{
return "org.eclipse.core.resources.problemmarker";
}
protected IFile getFile(Object datum)
{
if (datum instanceof IFileEditorInput)
{
return ((IFileEditorInput)datum).getFile();
}
else if (datum instanceof IFile)
{
return (IFile)datum;
}
else if (datum instanceof Diagnostic)
{
return getFile((Diagnostic)datum);
}
return null;
}
protected IFile getFile(Diagnostic diagnostic)
{
List<?> data = diagnostic.getData();
if (data != null)
{
for (Object datum : data)
{
IFile result = getFile(datum);
if (result != null)
{
return result;
}
}
}
return null;
}
protected IFile getFile(URI uri)
{
return uri.isPlatformResource() && uri.segmentCount() > 2 ?
ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(uri.toPlatformString(true))) :
null;
}
/**
* <p>Creates a marker based on the information available in the specified
* diagnostic. The marker's id is defined by {@link #getMarkerID()}.</p>
* <p>The default implementation looks in the diagnostic's data array for
* objects that would allow an IFile to be computed</p>
* @param diagnostic
* @throws CoreException
*/
public void createMarkers(final Diagnostic diagnostic) throws CoreException
{
ResourcesPlugin.getWorkspace().run
(new IWorkspaceRunnable()
{
public void run(IProgressMonitor monitor) throws CoreException
{
if (diagnostic.getChildren().isEmpty())
{
createMarkers(getFile(diagnostic), diagnostic, null);
}
else if (diagnostic.getMessage() == null)
{
for (Diagnostic childDiagnostic : diagnostic.getChildren())
{
createMarkers(childDiagnostic);
}
}
else
{
for (Diagnostic childDiagnostic : diagnostic.getChildren())
{
createMarkers(getFile(childDiagnostic), childDiagnostic, diagnostic);
}
}
}
},
null);
}
protected void createMarkers(IResource resource, Diagnostic diagnostic, Diagnostic parentDiagnostic) throws CoreException
{
if (resource != null && resource.exists())
{
IMarker marker = resource.createMarker(getMarkerID());
int severity = diagnostic.getSeverity();
if (severity < Diagnostic.WARNING)
{
marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_INFO);
}
else if (severity < Diagnostic.ERROR)
{
marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_WARNING);
}
else
{
marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
}
String message = composeMessage(diagnostic, parentDiagnostic);
if (message != null)
{
marker.setAttribute(IMarker.MESSAGE, message);
}
adjustMarker(marker, diagnostic, parentDiagnostic);
}
}
/**
* Clients should override this method to update the marker associated with the diagnostic.
* @param marker the marker to be updated.
* @param diagnostic the diagnostic associated with the marker.
* @param parentDiagnostic the parent of the diagnostic, if any.
* @throws CoreException
*/
protected void adjustMarker(IMarker marker, Diagnostic diagnostic, Diagnostic parentDiagnostic) throws CoreException
{
// Subclasses may override
}
/**
* Returns the message that will be used with the marker associated with the given diagnostic.
* @param diagnostic the diagnostic.
* @param parentDiagnostic the parent of the diagnostic, if any.
* @return the message that will be used with the marker associated with the given diagnostic.
*/
protected String composeMessage(Diagnostic diagnostic, Diagnostic parentDiagnostic)
{
return diagnostic.getMessage();
}
/**
* Returns whether the a maker with id equals to the return of {@link #getMarkerID()}
* is available in the IResource computed from the specified object.
* @param object
* @return boolean
*/
public boolean hasMarkers(Object object)
{
return hasMarkers(object, false, IResource.DEPTH_ZERO);
}
public boolean hasMarkers(Object object, boolean includeSubtypes, int depth)
{
return hasMarkers(getFile(object), includeSubtypes, depth);
}
protected boolean hasMarkers(IResource resource, boolean includeSubtypes, int depth)
{
if (resource != null && resource.exists())
{
try
{
IMarker[] markers = resource.findMarkers(getMarkerID(), includeSubtypes, depth);
return markers.length > 0;
}
catch (CoreException e)
{
// Ignore
}
}
return false;
}
/**
* Deletes a maker with id equals to the return of {@link #getMarkerID()}
* from the IResource computed from the specified object.
* @param object
*/
public void deleteMarkers(Object object)
{
deleteMarkers(object, false, IResource.DEPTH_ZERO);
}
public void deleteMarkers(Object object, boolean includeSubtypes, int depth)
{
deleteMarkers(getFile(object), includeSubtypes, depth);
}
protected void deleteMarkers(final IResource resource, final boolean includeSubtypes, final int depth)
{
if (resource != null && resource.exists())
{
try
{
resource.getWorkspace().run
(new IWorkspaceRunnable()
{
public void run(IProgressMonitor monitor) throws CoreException
{
resource.deleteMarkers(getMarkerID(), includeSubtypes, depth);
}
},
null);
}
catch (CoreException e)
{
CommonUIPlugin.INSTANCE.log(e);
}
}
}
public IEditorInput getEditorInput(Object object)
{
IFile file = getFile(object);
if (file != null)
{
return new FileEditorInput(file);
}
else
{
return null;
}
}
/**
* @since 2.3
*/
public List<?> getTargetObjects(Object object, IMarker marker)
{
return getTargetObjects(object, marker, true);
}
/**
* @since 2.11
*/
public List<?> getTargetObjects(Object object, IMarker marker, boolean wrap)
{
return Collections.EMPTY_LIST;
}
/**
* Converts markers in the file to diagnostics.
* @since 2.9
*/
public Diagnostic getMarkerDiagnostics(Object object, IFile file)
{
return getMarkerDiagnostics(object, file, true);
}
/**
* @since 2.11
*/
public Diagnostic getMarkerDiagnostics(Object object, IFile file, boolean wrap)
{
BasicDiagnostic diagnostic = new BasicDiagnostic(null, 0, getDiagnosticSource(), new Object[] { object });
try
{
for (IMarker marker : file.findMarkers(null, true, IResource.DEPTH_ZERO))
{
String message = marker.getAttribute(IMarker.MESSAGE, "");
int severity = marker.getAttribute(IMarker.SEVERITY, Diagnostic.INFO);
String sourceID = marker.getAttribute(IMarker.SOURCE_ID, "");
diagnostic.add
(new BasicDiagnostic
(severity == IMarker.SEVERITY_ERROR ?
Diagnostic.ERROR :
severity == IMarker.SEVERITY_WARNING ?
Diagnostic.WARNING :
Diagnostic.INFO,
sourceID,
0,
message,
null));
}
for (Diagnostic instrincDiagnostic : getIntrinsicDiagnostics(object, wrap))
{
diagnostic.add(instrincDiagnostic);
}
}
catch (CoreException exception)
{
CommonUIPlugin.INSTANCE.log(exception);
}
return diagnostic;
}
/**
* Returns any additional diagnostics associated in some way with the given object.
* <p>
* The method has a typo so please avoid calling this method and rather the fixed spelling of {@link #getIntrinsicDiagnostics(Object, boolean)}.
* Use this method only in a derived class to specialize the behavior.
* </p>
*
* @since 2.13
*/
public List<? extends Diagnostic> getInstrinciDiagnostics(Object object, boolean wrap)
{
return Collections.emptyList();
}
/**
* Returns any additional diagnostics associated in some way with the given object.
* <p>
* This method is final because the older wrongly spelled method {@link #getInstrinciDiagnostics(Object, boolean)} may have been used to specialize the behavior,
* so developers needing to specialize the behavior of this method should continue to use the older wrongly spelled method.
* </p>
*
* @since 2.14
*/
public final List<? extends Diagnostic> getIntrinsicDiagnostics(Object object, boolean wrap)
{
return getInstrinciDiagnostics(object, wrap);
}
/**
* {@link #deleteMarkers(Object) deletes} any markers associated with the resource of the given diagnostic and the {@link #createMarkers(Diagnostic) creates} new markers for it.
* All processing is done with as a single {@link IWorkspace#run(IWorkspaceRunnable, IProgressMonitor) workspace operation}.
* @param diagnostic the diagnostic to process.
* @throws CoreException if creating markers results in a core exception.
* @since 2.13
*/
public void updateMarkers(final Diagnostic diagnostic) throws CoreException
{
ResourcesPlugin.getWorkspace().run
(new IWorkspaceRunnable()
{
public void run(IProgressMonitor monitor) throws CoreException
{
deleteMarkers(diagnostic);
if (diagnostic.getSeverity() != Diagnostic.OK)
{
createMarkers(diagnostic);
}
}
},
null);
}
}