| /** |
| * 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); |
| } |
| } |