/* This file is part of Green. * * Copyright (C) 2005 The Research Foundation of State University of New York * All Rights Under Copyright Reserved, The Research Foundation of S.U.N.Y. * * Green is free software, licensed under the terms of the Eclipse * Public License, version 1.0. The license is available at * http://www.eclipse.org/legal/epl-v10.html */ package edu.buffalo.cse.green.editor.model; import static edu.buffalo.cse.green.editor.controller.PropertyChange.Element; import static org.eclipse.core.resources.IMarker.SEVERITY_INFO; import static org.eclipse.core.resources.IMarker.SEVERITY_WARNING; import static org.eclipse.core.resources.IResource.DEPTH_ZERO; import static org.eclipse.jdt.core.Flags.AccDefault; import static org.eclipse.jdt.core.Flags.AccPrivate; import static org.eclipse.jdt.core.Flags.AccProtected; import static org.eclipse.jdt.core.Flags.AccPublic; import static org.eclipse.jdt.core.IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER; import static org.eclipse.jdt.ui.JavaElementImageDescriptor.ERROR; import static org.eclipse.jdt.ui.JavaElementImageDescriptor.WARNING; //TODO Call to element marked internal by JDT import static org.eclipse.jdt.internal.ui.JavaPluginImages.DESC_OBJS_QUICK_FIX; import java.util.ArrayList; import java.util.List; import org.eclipse.core.internal.resources.ResourceException; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.jdt.core.IJavaModelMarker; import org.eclipse.jdt.core.IMember; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.Signature; import org.eclipse.jdt.ui.JavaElementImageDescriptor; import org.eclipse.jdt.ui.JavaElementLabelProvider; import org.eclipse.jdt.ui.refactoring.RenameSupport; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.ui.IMarkerResolution; import org.eclipse.ui.ide.IDE; import edu.buffalo.cse.green.editor.action.QuickFix; import edu.buffalo.cse.green.editor.action.QuickFixAction; /** * Superclass that provides functionality that is common to all * <code>IMember</code>s. * * @author bcmartin */ public abstract class MemberModel<C extends AbstractModel, P extends AbstractModel, E extends IMember> extends AbstractModel<C, P, E> { private static JavaElementLabelProvider ICON_PROVIDER = new JavaElementLabelProvider(); private E _member = null; protected MemberModel(E element) { setMember(element); } /** * @see edu.buffalo.cse.green.editor.model.AbstractModel#getJavaElement() */ public final E getJavaElement() { return _member; } /** * @return the <code>IMember</code> represented by this model. */ public final E getMember() { return _member; } /** * Sets the member that is represented by this model. * * @param member - The member. */ public final void setMember(E member) { E oldMember = _member; _member = member; firePropertyChange(Element, oldMember, _member); } /** * @return the visibility of this <code>IMember</code> */ protected String getVisibility() { try { int flags = _member.getFlags(); if ((flags & AccPublic) == AccPublic) { return "public"; } else if ((flags & AccProtected) == AccProtected) { return "protected"; } else if ((flags & AccPrivate) == AccPrivate) { return "private"; } else if ((flags & AccDefault) == AccDefault) { return ""; } } catch (JavaModelException e) { e.printStackTrace(); } return null; } /** * @see edu.buffalo.cse.green.editor.model.AbstractModel#removeFromParent() */ public void removeFromParent() { getParent().removeChild(this); } /** * Gets the appropriate icon to represent the given <code>IMember</code>. * * @param member - The <code>IMember</code> to represent. * @return The icon. */ protected Image getImage(MemberModel<?, ?, E> model) { E member = model.getMember(); ImageDescriptor id = ImageDescriptor.createFromImage( ICON_PROVIDER.getImage(member)); int adornments = 0; IResource memberResource = member.getResource(); if (memberResource != null && member instanceof IMember && member.exists()) { try { IMarker[] errorMarkers = memberResource.findMarkers( IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, false, IResource.DEPTH_ZERO); for (IMarker marker : errorMarkers) { // see if the error/warning is inside this member's scope int errStart = (Integer) marker.getAttribute("charStart"); int errEnd = (Integer) marker.getAttribute("charEnd"); int memStart = member.getSourceRange().getOffset(); int memEnd = memStart + member.getSourceRange().getLength(); if (memStart > errStart || memEnd < errEnd) continue; int severity = marker.getAttribute( IMarker.SEVERITY, SEVERITY_INFO); if (severity == IMarker.SEVERITY_ERROR) { adornments = ERROR; break; } else if (severity == SEVERITY_WARNING) { adornments = WARNING; } } } catch (ResourceException e) { // TODO Issue: when Java editor is open, stack trace // is printed during a refactoring, because we're trying // to access old model, not new model. If Java editor // is not open, we're OK. // RETHROWING THIS EXCEPTION causes a cascade of THROWS clauses being required... // throw e; System.err.println("[GREEN] Resource exception was thrown - probably OK"); } catch (CoreException e) { e.printStackTrace(); } } return new JavaElementImageDescriptor(id, adornments, new Point(id.getImageData().width, id.getImageData().height)).createImage(); } /** * @see java.lang.Object#toString() */ public String toString() { return getDisplayName(); } /** * @see edu.buffalo.cse.green.editor.model.AbstractModel#handleDispose() */ public void handleDispose() { // do nothing } /** * @return The image representing the type. */ public Image getIcon() { return getImage(this); } /** * @return The caption to display on the label in the diagram. */ public abstract String getDisplayName(); /** * @param signature - The type signature. * @param fqn - If true, fully-qualified names should be used. * @return The string representing the member's signature. */ protected static final String getSignatureName( String signature, boolean fqn) { String sig = Signature.toString(signature); if (!fqn) { sig = sig.substring(sig.lastIndexOf('.') + 1); } return sig; } /** * @see edu.buffalo.cse.green.editor.model.AbstractModel#getTypeModel() */ public TypeModel getTypeModel() { AbstractModel<?,?,?> parent = getParent(); return parent.getTypeModel(); } /** * @return A <code>RenameSupport</code> for use by * <code>RefactorRenameAction</code> * @throws CoreException */ public abstract RenameSupport getRenameSupport() throws CoreException; // /** // * @see java.lang.Object#equals(java.lang.Object) // */ // public final boolean equals(Object o) { // System.err.println(o + ":" + this); // // if (!(o instanceof MemberModel)) return false; // // MemberModel model = (MemberModel) o; // return getMember().getHandleIdentifier().equals( // model.getMember().getHandleIdentifier()); // } /** * Appends quick fix actions for this element to the given menu. * * @param menu - The target menu. */ public void appendQuickFixActionsToMenu(MenuManager menu) { List<QuickFix> fixes = getQuickFixes(); if (fixes.size() > 0) { MenuManager qf = new MenuManager("Quick Fixes", DESC_OBJS_QUICK_FIX, null); qf.setVisible(true); menu.add(new Separator()); menu.add(qf); for (QuickFix fix : fixes) { qf.add(new QuickFixAction(fix)); } } } /** * Finds the quick fixes corresponding to this model. */ private List<QuickFix> getQuickFixes() { boolean isBinary = getMember().isBinary(); if (!isBinary) { try { IResource resource = getMember().getUnderlyingResource(); IMarker[] errorMarkers = resource.findMarkers( JAVA_MODEL_PROBLEM_MARKER, false, DEPTH_ZERO); for (IMarker marker : errorMarkers) { // see if the error/warning is inside this member's scope int errStart = (Integer) marker.getAttribute("charStart"); int errEnd = (Integer) marker.getAttribute("charEnd"); int memStart = getMember().getSourceRange().getOffset(); int memEnd = memStart + getMember().getSourceRange().getLength(); if (memStart > errStart || memEnd < errEnd) continue; return getQuickFix(marker); } } catch (CoreException e) { // do nothing } } return new ArrayList<QuickFix>(); } /** * Finds the quick fixes corresponding to the given error markers and * displays a dialog for the user to select the desired action to take. * * @param errorMarkers - The given <code>IMarker</code>s. */ private List<QuickFix> getQuickFix(IMarker errorMarker) { List<QuickFix> fixes = new ArrayList<QuickFix>(); for (IMarkerResolution resolution : IDE.getMarkerHelpRegistry().getResolutions(errorMarker)) { fixes.add(new QuickFix(errorMarker, resolution)); } return fixes; } }