Java tutorial
/******************************************************************************* * Copyright (c) 2010, 2015 THALES GLOBAL SERVICES. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Obeo - initial API and implementation *******************************************************************************/ package org.eclipse.sirius.ui.debug; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.InvocationTargetException; import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.core.commands.operations.IOperationHistory; import org.eclipse.core.commands.operations.IUndoContext; import org.eclipse.core.commands.operations.IUndoableOperation; import org.eclipse.core.commands.operations.OperationHistoryFactory; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.draw2d.Bendpoint; import org.eclipse.draw2d.Connection; import org.eclipse.draw2d.ConnectionAnchor; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.geometry.Point; import org.eclipse.draw2d.geometry.Rectangle; import org.eclipse.emf.common.notify.Adapter; import org.eclipse.emf.common.notify.Notifier; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EAttribute; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.InternalEObject; import org.eclipse.emf.ecore.resource.ContentHandler; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.resource.URIConverter; import org.eclipse.emf.ecore.resource.URIHandler; import org.eclipse.emf.ecore.resource.impl.ExtensibleURIConverterImpl; import org.eclipse.emf.ecore.resource.impl.FileURIHandlerImpl; import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider; import org.eclipse.emf.transaction.RecordingCommand; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.emf.transaction.util.TransactionUtil; import org.eclipse.emf.workspace.IWorkspaceCommandStack; import org.eclipse.gmf.runtime.diagram.ui.editparts.ConnectionEditPart; import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramEditPart; import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart; import org.eclipse.gmf.runtime.diagram.ui.editparts.ShapeEditPart; import org.eclipse.gmf.runtime.draw2d.ui.figures.PolylineConnectionEx; import org.eclipse.gmf.runtime.gef.ui.figures.SlidableAnchor; import org.eclipse.gmf.runtime.notation.Bounds; import org.eclipse.gmf.runtime.notation.Edge; import org.eclipse.gmf.runtime.notation.IdentityAnchor; import org.eclipse.gmf.runtime.notation.LayoutConstraint; import org.eclipse.gmf.runtime.notation.Location; import org.eclipse.gmf.runtime.notation.Node; import org.eclipse.gmf.runtime.notation.RelativeBendpoints; import org.eclipse.gmf.runtime.notation.datatype.RelativeBendpoint; import org.eclipse.jface.dialogs.ProgressMonitorDialog; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.window.Window; import org.eclipse.sirius.business.api.session.Session; import org.eclipse.sirius.business.api.session.SessionManager; import org.eclipse.sirius.business.internal.movida.ViewpointSelection; import org.eclipse.sirius.business.internal.movida.registry.ViewpointRegistry; import org.eclipse.sirius.business.internal.movida.registry.ViewpointRegistryListener; import org.eclipse.sirius.business.internal.session.danalysis.DAnalysisSessionImpl; import org.eclipse.sirius.diagram.AbsoluteBoundsFilter; import org.eclipse.sirius.diagram.DDiagramElement; import org.eclipse.sirius.diagram.EdgeTarget; import org.eclipse.sirius.diagram.sequence.SequenceDDiagram; import org.eclipse.sirius.diagram.sequence.business.internal.VerticalPositionFunction; import org.eclipse.sirius.diagram.sequence.business.internal.elements.ISequenceElement; import org.eclipse.sirius.diagram.sequence.business.internal.elements.ISequenceElementAccessor; import org.eclipse.sirius.diagram.sequence.business.internal.elements.ISequenceEvent; import org.eclipse.sirius.diagram.sequence.business.internal.elements.Lifeline; import org.eclipse.sirius.diagram.sequence.business.internal.operation.VerticalSpaceExpansion; import org.eclipse.sirius.diagram.sequence.ordering.EventEnd; import org.eclipse.sirius.diagram.sequence.ui.tool.api.SequenceDiagramLayout; import org.eclipse.sirius.diagram.sequence.ui.tool.internal.edit.part.ISequenceEventEditPart; import org.eclipse.sirius.diagram.sequence.ui.tool.internal.edit.part.InstanceRoleEditPart; import org.eclipse.sirius.diagram.sequence.ui.tool.internal.edit.part.LifelineEditPart; import org.eclipse.sirius.diagram.sequence.ui.tool.internal.edit.part.SequenceDiagramEditPart; import org.eclipse.sirius.diagram.sequence.ui.tool.internal.edit.part.SequenceMessageEditPart; import org.eclipse.sirius.diagram.sequence.util.Range; import org.eclipse.sirius.diagram.ui.business.internal.query.EdgeTargetQuery; import org.eclipse.sirius.diagram.ui.edit.api.part.AbstractDiagramContainerEditPart; import org.eclipse.sirius.diagram.ui.edit.api.part.AbstractDiagramElementContainerEditPart; import org.eclipse.sirius.diagram.ui.edit.api.part.AbstractDiagramNameEditPart; import org.eclipse.sirius.diagram.ui.edit.api.part.IAbstractDiagramNodeEditPart; import org.eclipse.sirius.diagram.ui.edit.api.part.IDiagramEdgeEditPart; import org.eclipse.sirius.diagram.ui.edit.api.part.IDiagramElementEditPart; import org.eclipse.sirius.diagram.ui.internal.edit.parts.DDiagramEditPart; import org.eclipse.sirius.diagram.ui.internal.refresh.GMFHelper; import org.eclipse.sirius.diagram.ui.tools.internal.commands.ToggleFoldingStateCommand; import org.eclipse.sirius.diagram.ui.tools.internal.edit.command.CommandFactory; import org.eclipse.sirius.editor.tools.internal.presentation.ViewpoitnDependenciesSelectionDialog; import org.eclipse.sirius.ext.base.Option; import org.eclipse.sirius.ext.emf.AllContents; import org.eclipse.sirius.tests.sample.component.Component; import org.eclipse.sirius.tests.sample.component.util.PayloadMarkerAdapter; import org.eclipse.sirius.tests.sample.component.util.PayloadMarkerAdapter.FeatureAccess; import org.eclipse.sirius.ui.business.api.viewpoint.ViewpointSelectionDialog; import org.eclipse.sirius.ui.debug.ResourceSetTopologyAnalyzer.Reference; import org.eclipse.sirius.viewpoint.DRepresentationElement; import org.eclipse.sirius.viewpoint.DSemanticDecorator; import org.eclipse.sirius.viewpoint.description.DescriptionPackage; import org.eclipse.sirius.viewpoint.description.Viewpoint; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.team.internal.core.streams.ProgressMonitorInputStream; import com.google.common.base.Functions; import com.google.common.base.Objects; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Multimap; import com.google.common.collect.Multiset; import com.google.common.collect.Ordering; /** * A simple view synchronized with the Eclipse selection, used to show arbitrary * computed information from the currently selected edit part of a diagram and * launch actions on them. This view is targeted to developers to help * debugging, it should not be packaged in the final product and should not be * available to end users. * * @author pcdavid */ @SuppressWarnings({ "restriction", "unused" }) public class SiriusDebugView extends AbstractDebugView { /** * The global ID for the Eclipse View. */ public static final String ID = "org.eclipse.sirius.ui.debug.DebugView"; /** * Memento used by the Store Positions/Show position changes actions. */ protected Map<EObject, Integer> storedPositions; protected ViewpointRegistry registry; /** * Returns the text to show in the main text area for the specified object. */ @Override protected String getTextFor(Object obj) { if (obj instanceof IDiagramElementEditPart) { return getTextFor((IDiagramElementEditPart) obj); } else if (obj instanceof DDiagramEditPart) { return getTextForDiagram((DDiagramEditPart) obj); } else if (obj instanceof ConnectionEditPart) { return getTextForConnection((ConnectionEditPart) obj); } else { return "Selection type not supported: " + obj; } } private String getTextForDiagram(DDiagramEditPart sdep) { StringBuilder sb = new StringBuilder(); sb.append("Direct diagram children:\n"); for (IGraphicalEditPart child : Iterables.filter(sdep.getChildren(), IGraphicalEditPart.class)) { sb.append("- " + toString(child)); sb.append("\n - sources: "); for (IGraphicalEditPart sourceConn : Iterables.filter(child.getSourceConnections(), IGraphicalEditPart.class)) { sb.append("\n ").append(toString(sourceConn)); } sb.append("\n - targets: "); for (IGraphicalEditPart targetConn : Iterables.filter(child.getTargetConnections(), IGraphicalEditPart.class)) { sb.append("\n ").append(toString(targetConn)); } sb.append("\n"); } return sb.toString(); } private String toString(IGraphicalEditPart part) { return String.valueOf(part).replace("org.eclipse.gmf.runtime.notation.impl.", "") + " #" + Long.toHexString(part.hashCode()); } private String getTextFor(IDiagramElementEditPart part) { StringBuilder sb = new StringBuilder(); if (part instanceof ShapeEditPart) { appendSequenceEventInfo(part, sb); appendBoundsDetails(part, sb); if (part instanceof AbstractDiagramContainerEditPart && ((AbstractDiagramContainerEditPart) part).isRegionContainer()) { IGraphicalEditPart compartment = null; for (IGraphicalEditPart child : Iterables.filter(part.getChildren(), IGraphicalEditPart.class)) { sb.append("Children bounds:\n"); appendBoundsDetails(child, sb); compartment = child; } for (IGraphicalEditPart child2 : Iterables.filter(compartment.getChildren(), IGraphicalEditPart.class)) { sb.append("Region bounds:\n"); appendBoundsDetails(child2, sb); } } else if (part instanceof AbstractDiagramElementContainerEditPart && ((AbstractDiagramElementContainerEditPart) part).isRegion()) { IGraphicalEditPart parent = (IGraphicalEditPart) part.getParent(); sb.append("Compartment bounds:\n"); appendBoundsDetails(parent, sb); parent = (IGraphicalEditPart) parent.getParent(); sb.append("Region Container bounds:\n"); appendBoundsDetails(parent, sb); } else if (part instanceof InstanceRoleEditPart) { LifelineEditPart lep = Iterables.filter(part.getChildren(), LifelineEditPart.class).iterator() .next(); appendSequenceEventInfo(lep, sb); } } else if (part instanceof ConnectionEditPart) { ConnectionEditPart conn = (ConnectionEditPart) part; sb.append(getTextForConnection(conn)); } else if (part instanceof AbstractDiagramNameEditPart) { appendBoundsDetails(part, sb); } else { sb.append("unknown"); } return sb.toString(); } private void appendBoundsDetails(IGraphicalEditPart part, StringBuilder sb) { Node node = (Node) part.getNotationView(); LayoutConstraint layoutConstraint = node.getLayoutConstraint(); if (layoutConstraint instanceof Bounds) { Bounds bounds = (Bounds) layoutConstraint; sb.append("Bounds (GMF): Rectangle(" + bounds.getX() + ", " + bounds.getY() + ", " + bounds.getWidth() + ", " + bounds.getHeight() + ")\n"); } else if (layoutConstraint instanceof Location) { Location location = (Location) layoutConstraint; sb.append("Location (GMF): Location(" + location.getX() + ", " + location.getY() + ")\n"); } Rectangle absoluteBounds = GMFHelper.getAbsoluteBounds(node, true); sb.append("Bounds (GMF absolute - insets): " + absoluteBounds + "\n"); absoluteBounds = GMFHelper.getAbsoluteBounds(node, false); sb.append("Bounds (GMF absolute - no insets): " + absoluteBounds + "\n"); Option<ISequenceElement> elt = ISequenceElementAccessor.getISequenceElement(part.getNotationView()); if (elt.some()) { sb.append("Bounds (logical): " + elt.get().getProperLogicalBounds()).append("\n"); } Rectangle bounds = part.getFigure().getBounds().getCopy(); sb.append("Bounds (Draw2D): " + bounds.toString() + " --> center: " + bounds.getCenter() + "\n"); part.getFigure().translateToAbsolute(bounds); sb.append("Bounds (Draw2D absolute): " + bounds.toString() + " --> center: " + bounds.getCenter() + "\n"); sb.append("\n"); } private String getTextForConnection(ConnectionEditPart conn) { Edge edge = (Edge) conn.getNotationView(); StringBuilder sb = new StringBuilder(); if (conn instanceof IDiagramElementEditPart) { appendSequenceEventInfo((IDiagramElementEditPart) conn, sb); } if (conn instanceof IDiagramEdgeEditPart) { PolylineConnectionEx polyline = ((IDiagramEdgeEditPart) conn).getPolylineConnectionFigure(); sb.append( "Line width = " + polyline.getLineWidth() + " (float: " + polyline.getLineWidthFloat() + ")\n"); } sb.append("GMF Notation (Edge):\n"); Point srcAnchorLoc = appendAnchorDetails(conn, (IdentityAnchor) edge.getSourceAnchor(), ((Connection) conn.getFigure()).getSourceAnchor(), " . sourceAnchor", sb); Point tgtAnchorLoc = appendAnchorDetails(conn, (IdentityAnchor) edge.getTargetAnchor(), ((Connection) conn.getFigure()).getTargetAnchor(), " . targetAnchor", sb); appendRelativeBenpointsDetails(edge, conn, sb); sb.append("\nDraw2D Connection:\n"); Connection connFigure = conn.getConnectionFigure(); sb.append(" . routing constraint:\n"); @SuppressWarnings("unchecked") List<Bendpoint> bendpoints = (List<Bendpoint>) connFigure.getRoutingConstraint(); if (bendpoints != null) { for (int i = 0; i < bendpoints.size(); i++) { Point location = bendpoints.get(i).getLocation(); sb.append(" " + i + ":"); sb.append(location); sb.append("\n"); } } sb.append(" . sourceAnchor: "); if (connFigure.getSourceAnchor() instanceof SlidableAnchor) { sb.append(((SlidableAnchor) connFigure.getSourceAnchor()).getTerminal() + " ==> "); } sb.append(connFigure.getSourceAnchor().getReferencePoint()).append("\n"); sb.append(" . targetAnchor: "); if (connFigure.getTargetAnchor() instanceof SlidableAnchor) { sb.append(((SlidableAnchor) connFigure.getTargetAnchor()).getTerminal() + " ==> "); } sb.append(connFigure.getTargetAnchor().getReferencePoint()).append("\n"); sb.append(" . points:\n"); for (int i = 0; i < connFigure.getPoints().size(); i++) { sb.append(" " + i + ": " + connFigure.getPoints().getPoint(i).toString()).append("\n"); } return sb.toString(); } private void appendSequenceEventInfo(IDiagramElementEditPart part, StringBuilder sb) { if (part instanceof ISequenceEventEditPart) { ISequenceEvent iSequenceEvent = ((ISequenceEventEditPart) part).getISequenceEvent(); Range range = iSequenceEvent.getVerticalRange(); sb.append("Range: " + range.toString() + " (height = " + range.width() + ")\n"); Rectangle properLogicalBounds = iSequenceEvent.getProperLogicalBounds(); sb.append("Absolute Bounds: " + properLogicalBounds + ")\n"); DDiagramElement dde = (DDiagramElement) iSequenceEvent.getNotationView().getElement(); if (!Lifeline.viewpointElementPredicate().apply(dde) && !Iterables .isEmpty(Iterables.filter(dde.getGraphicalFilters(), AbsoluteBoundsFilter.class))) { AbsoluteBoundsFilter flag = Iterables .getOnlyElement(Iterables.filter(dde.getGraphicalFilters(), AbsoluteBoundsFilter.class)); sb.append("Bounds flag: (" + flag.getX() + ", " + flag.getY() + ", " + flag.getWidth() + ", " + flag.getHeight() + ")\n\n"); } } } private void appendRelativeBenpointsDetails(Edge edge, ConnectionEditPart conn, StringBuilder sb) { sb.append(" . bendpoints ="); StringBuilder fromSourceSB = new StringBuilder(); List<Point> pointsFromSource = GMFHelper.getPointsFromSource(conn); for (Point point : pointsFromSource) { fromSourceSB.append(point); fromSourceSB.append(" "); } StringBuilder fromTargetSB = new StringBuilder(); List<Point> pointsFromTarget = GMFHelper.getPointsFromTarget(conn); for (Point point : pointsFromTarget) { fromTargetSB.append(point); fromTargetSB.append(" "); } if (fromSourceSB.toString().equals(fromTargetSB.toString())) { sb.append("\n . Computed points: "); sb.append(fromSourceSB); } else { sb.append(" **** WARNING: points computed from source != points computed from target ****"); sb.append("\n . Points computed from source: "); sb.append(fromSourceSB); sb.append("\n . Points computed from target: "); sb.append(fromTargetSB); } sb.append("\n . Source vectors: "); RelativeBendpoints bp = (RelativeBendpoints) edge.getBendpoints(); for (int i = 0; i < bp.getPoints().size(); i++) { RelativeBendpoint rbp = (RelativeBendpoint) bp.getPoints().get(i); sb.append("[" + rbp.getSourceX() + ", " + rbp.getSourceY() + "] "); } sb.append("\n . Target vectors: "); for (int i = 0; i < bp.getPoints().size(); i++) { RelativeBendpoint rbp = (RelativeBendpoint) bp.getPoints().get(i); sb.append("[" + rbp.getTargetX() + ", " + rbp.getTargetY() + "] "); } sb.append("\n"); } private Point appendAnchorDetails(ConnectionEditPart origin, IdentityAnchor anchor, ConnectionAnchor connectionAnchor, String name, StringBuilder sb) { sb.append(name).append(" = "); if (anchor != null) { sb.append(anchor.getId()); } else { sb.append("null "); } Point location = connectionAnchor.getReferencePoint(); origin.getFigure().translateToRelative(location); sb.append(" => ").append(location).append("\n"); return location; } /** * Creates the actions available to users. */ @Override protected void createActionButtons() { // addFoldingToggleAction(); // addShowOrderingsAction(); // addStorePositionsAction(); // addShowPositionChangesAction(); addShowFiguresHierarchyAction(); addShowEditPartsHierarchyAction(); // addRefreshBenpointsAction(); // addResetBendpointsAction(); // addExpandAction(); // addRefreshCoverageAction(); // addRefreshDiagramAction(); // addStartMovidaRegistryAction(); // addShowMovidaRegistryStatusAction(); // addSelectReusedSiriussAction(); // addShowCommandStackAction(); // addSiriusSelectionAction(); // addExtractExpressionsAction(); // addLoadResourceWithProgressAction(); addShowPayloadAccessLogAction(); addClearPayloadAccessLogAction(); addShowResourceSetTopologyAction(); addShowAdaptersAction(); addShowSessionStructureAction(); // addShowCrossReferencerMap(); } private void addShowSessionStructureAction() { addAction("Show session structure", new Runnable() { @Override public void run() { EObject current = getCurrentEObject(); if (current != null) { Session s = SessionManager.INSTANCE.getSession(current); if (s instanceof DAnalysisSessionImpl) { setText(getStructure(((DAnalysisSessionImpl) s))); } else if (s == null && current instanceof DSemanticDecorator) { s = SessionManager.INSTANCE.getSession(((DSemanticDecorator) current).getTarget()); if (s instanceof DAnalysisSessionImpl) { setText(getStructure(((DAnalysisSessionImpl) s))); } } } } private String getStructure(DAnalysisSessionImpl session) { StringBuilder sb = new StringBuilder(); sb.append("DAnalysisSessionEObject references:\n"); for (EStructuralFeature esf : session.eClass().getEAllStructuralFeatures()) { sb.append("* ").append(esf.getName()).append(":\n"); appendValue(session, esf, sb); } return sb.toString(); } private void appendValue(EObject obj, EStructuralFeature esf, StringBuilder sb) { Object value = obj.eGet(esf); if (esf.isMany()) { EList<?> values = (EList<?>) value; for (int i = 0; i < values.size(); i++) { Object v = values.get(i); sb.append(" ").append(i + 1).append(". ") .append(v instanceof EObject ? toString((EObject) v) : String.valueOf(v)) .append("\n"); } } else { sb.append(" - ") .append(value instanceof EObject ? toString((EObject) value) : String.valueOf(value)) .append("\n"); } } private String toString(EObject obj) { if (obj == null) { return null; } else if (obj.eIsProxy()) { return ((InternalEObject) obj).eProxyURI().toString(); } else { return obj.getClass().getName() + "@" + Integer.toHexString(obj.hashCode()); } } }); } private void addShowPayloadAccessLogAction() { addAction("Show Payload Access Log", new Runnable() { @Override public void run() { int max = 50; List<FeatureAccess> log = PayloadMarkerAdapter.INSTANCE.getAccessLog(); int totalSize = log.size(); int shown = Math.min(totalSize, max); TabularReport tr = new TabularReport(/* "Timestamp", */"EObject", "Feature"); try { PayloadMarkerAdapter.INSTANCE.setEnable(false); for (int i = log.size() > max ? log.size() - max : 0; i < log.size(); i++) { FeatureAccess featureAccess = log.get(i); tr.addLine(Arrays.asList(/* * String.format("%tT", * featureAccess.timestamp), */((Component) featureAccess.setting.getEObject()).getName(), featureAccess.setting.getEStructuralFeature().getName())); } } finally { PayloadMarkerAdapter.INSTANCE.setEnable(true); } StringBuilder sb = new StringBuilder(); sb.append("Showing " + shown + " of " + totalSize + " accesses.\n"); Multiset<String> contexts = PayloadMarkerAdapter.INSTANCE.getUniqueContexts(); sb.append("Unique contexts: " + contexts.elementSet().size()).append("\n\n"); int i = 0; for (String stack : contexts.elementSet()) { int count = contexts.count(stack); sb.append("Context #" + i++ + " (" + count + " occurrences)").append("\n"); sb.append(stack).append("\n"); } sb.append("\n").append(tr.print()).append("\n"); setText(sb.toString()); } }); } private void addClearPayloadAccessLogAction() { addAction("Clear Payload Access Log", new Runnable() { @Override public void run() { PayloadMarkerAdapter.INSTANCE.clearAccessLog(); } }); } private void addShowAdaptersAction() { addAction("Show adapters", new Runnable() { @Override public void run() { StringBuilder sb = new StringBuilder(); EObject current = getCurrentEObject(); if (current != null) { sb.append("Selected element:\n"); appendAdapters(sb, current); if (current instanceof DSemanticDecorator) { sb.append("\nDSemanticDecorator.target:\n"); appendAdapters(sb, ((DSemanticDecorator) current).getTarget()); } if (current instanceof DRepresentationElement) { sb.append("\nDRepresentationElement.semanticElements:\n"); for (EObject o : ((DRepresentationElement) current).getSemanticElements()) { if (o != null) { appendAdapters(sb, o); } } } if (current.eResource() != null) { Resource r = current.eResource(); sb.append("\nAdapters on Resource " + r.getURI().toString()).append(":\n"); appendAdapters2(sb, r); if (r.getResourceSet() != null) { ResourceSet rs = r.getResourceSet(); sb.append("\nAdapters on ResourceSet:\n"); appendAdapters2(sb, rs); } } } setText(sb.toString()); } private void appendAdapters(StringBuilder sb, EObject current) { sb.append("Adapters on ").append(current.eClass().getName()).append("\n"); appendAdapters2(sb, current); } private void appendAdapters2(StringBuilder sb, Notifier current) { EList<Adapter> adapters = current.eAdapters(); for (int i = 0; i < adapters.size(); i++) { Adapter adapter = adapters.get(i); sb.append(i + 1).append(". ").append(adapter.getClass().getName()).append("@") .append(Integer.toHexString(adapter.hashCode())).append("\n"); } } }); } private void addShowCrossReferencerMap() { addAction("Show Cross Referencer Map", new ShowCrossReferencerMap(this)); } EObject getCurrentEObject() { if (selection instanceof IGraphicalEditPart) { return ((IGraphicalEditPart) selection).resolveSemanticElement(); } else if (selection instanceof EObject) { return (EObject) selection; } else { return null; } } private void addShowResourceSetTopologyAction() { addAction("Show ResourceSet Topology", new Runnable() { @Override public void run() { for (Session s : SessionManager.INSTANCE.getSessions()) { ResourceSetTopologyAnalyzer rsta = new ResourceSetTopologyAnalyzer( s.getTransactionalEditingDomain().getResourceSet()); Multimap<EStructuralFeature, Reference> result = rsta.analyze(); StringBuilder sb = new StringBuilder(); sb.append("Found " + result.keys().size() + " distinct kinds of cross-resource references:\n"); for (EStructuralFeature esf : result.keys()) { sb.append("- "); appendFeatureName(sb, esf); sb.append("\n"); for (Reference ref : result.get(esf)) { sb.append(" - ").append(renderResource(ref.sourceResource)).append(" => ") .append(renderResource(ref.targetResource)).append(" [" + ref.count + "]") .append("\n"); } } setText(sb.toString()); } } private final void appendFeatureName(StringBuilder out, EStructuralFeature esf) { out.append(esf.getEContainingClass().getEPackage().getName()).append("::") .append(esf.getEContainingClass().getName()).append(".").append(esf.getName()); } private final String renderResource(Resource res) { if (res == null) { return "(no resource)"; } else if (res.getURI() == null) { return "(resource with no URI)"; } else { return res.getURI().toString(); } } }); } private void addLoadResourceWithProgressAction() { addAction("Load with progress", new Runnable() { @Override public void run() { FileDialog dia = new FileDialog(getSite().getShell(), SWT.OPEN); dia.setFilterExtensions(new String[] { "*.ecore" }); final String path = dia.open(); final Resource[] result = new Resource[1]; if (path != null) { try { IRunnableWithProgress op = new IRunnableWithProgress() { @Override public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { ResourceSet rs = new ResourceSetImpl(); final SubMonitor loadingMonitor = SubMonitor.convert(monitor, (int) new File(path).length()); List<URIHandler> handlers = Lists.newArrayList(URIHandler.DEFAULT_HANDLERS); handlers.set(1, new FileURIHandlerImpl() { @Override public InputStream createInputStream(URI uri, Map<?, ?> options) throws IOException { String filePath = uri.toFileString(); File file = new File(filePath); InputStream inputStream = new ProgressMonitorInputStream( new FileInputStream(file), file.length(), 1, loadingMonitor) { private long previousRead = 0; @Override protected void updateMonitor(long bytesRead, long size, IProgressMonitor monitor) { long progress = bytesRead - previousRead; while (progress > Integer.MAX_VALUE) { loadingMonitor.worked(Integer.MAX_VALUE); progress -= Integer.MAX_VALUE; } loadingMonitor.worked((int) progress); previousRead = bytesRead; } }; Map<Object, Object> response = getResponse(options); if (response != null) { response.put(URIConverter.RESPONSE_TIME_STAMP_PROPERTY, file.lastModified()); } return inputStream; } }); rs.setURIConverter(new ExtensibleURIConverterImpl(handlers, ContentHandler.Registry.INSTANCE.contentHandlers())); result[0] = rs.getResource(URI.createFileURI(path), true); } }; new ProgressMonitorDialog(getSite().getShell()).run(true, false, op); } catch (InvocationTargetException e) { // handle exception } catch (InterruptedException e) { // handle cancelation } if (result[0] != null) { setText("Loaded resource " + result[0] + " with " + Iterables.size(AllContents.of(result[0].getContents().get(0))) + " elements."); } else { setText("Failed loading resource at " + path); } } } }); } private void addExtractExpressionsAction() { addAction("Extract Expressions", new Runnable() { @Override public void run() { FileDialog dia = new FileDialog(getSite().getShell(), SWT.OPEN | SWT.MULTI); dia.setFilterExtensions(new String[] { "*.odesign" }); String path = dia.open(); List<String[]> lines = Lists.newArrayList(); if (path != null) { for (String file : dia.getFileNames()) { ResourceSet rs = new ResourceSetImpl(); Resource vsm = rs.getResource(URI.createFileURI(dia.getFilterPath() + "/" + file), true); for (EObject obj : AllContents.of(vsm.getContents().get(0))) { EClass klass = obj.eClass(); for (EAttribute attr : klass.getEAllAttributes()) { if (attr.getEType() == DescriptionPackage.Literals.INTERPRETED_EXPRESSION) { String value = Objects.firstNonNull((String) obj.eGet(attr), "").trim(); if (value.length() > 100) { value = value.substring(0, 97) + "..."; } lines.add(new String[] { value, attr.getEContainingClass().getName() + "." + attr.getName() }); } } } } } StringBuilder result = new StringBuilder(); for (String[] line : lines) { result.append(line[0] + "\n"); } result.append("Total: " + lines.size() + " expressions"); setText(result.toString()); // Collections.sort(lines, new Comparator<String[]>() { // public int compare(String[] o1, String[] o2) { // return o1[0].compareTo(o2[0]); // } // }); // TabularReport report = new TabularReport("Expression", // "Feature"); // for (String[] line : lines) { // report.addLine(line[0], line[1]); // } // setText(report.print()); } }); } private ViewpointSelection currentSelection = null; private void addSiriusSelectionAction() { addAction("Sirius Selection", new Runnable() { @Override public void run() { ViewpointRegistry reg = (ViewpointRegistry) org.eclipse.sirius.business.api.componentization.ViewpointRegistry .getInstance(); if (currentSelection == null) { currentSelection = new ViewpointSelection(reg); } ViewpointSelectionDialog dlg = new ViewpointSelectionDialog(getSite().getShell(), reg, currentSelection, null); if (dlg.open() == Window.OK) { // Do nothing here. } } }); } private void addShowCommandStackAction() { addAction("Show CommandStack", new Runnable() { @Override public void run() { IUndoContext undoContext = getUndoContext(selection); if (undoContext != null) { TabularReport report = new TabularReport("IUndoableOperation's name"); IUndoableOperation[] redoableOperations = OperationHistoryFactory.getOperationHistory() .getRedoHistory(undoContext); if (redoableOperations != null) { for (int i = redoableOperations.length - 1; i >= 0; i--) { IUndoableOperation redoableOperation = redoableOperations[i]; report.addLine(redoableOperation.getLabel()); } } report.addLine("---------"); IUndoableOperation[] undoableOperations = OperationHistoryFactory.getOperationHistory() .getUndoHistory(undoContext); if (undoableOperations != null) { for (int i = undoableOperations.length - 1; i >= 0; i--) { IUndoableOperation undoableOperation = undoableOperations[i]; report.addLine(undoableOperation.getLabel()); } } setText(report.print()); } } private IUndoContext getUndoContext(Object selection) { IUndoContext undoContext = IOperationHistory.GLOBAL_UNDO_CONTEXT; EObject eObject = null; if (selection instanceof EObject) { eObject = (EObject) selection; } else if (selection instanceof IAdaptable) { IAdaptable adaptable = (IAdaptable) selection; eObject = (EObject) adaptable.getAdapter(EObject.class); } if (eObject != null) { TransactionalEditingDomain domain = TransactionUtil.getEditingDomain(eObject); if (domain == null && eObject instanceof Session) { Session session = (Session) eObject; domain = session.getTransactionalEditingDomain(); } if (domain != null && domain.getCommandStack() instanceof IWorkspaceCommandStack) { IWorkspaceCommandStack workspaceCommandStack = (IWorkspaceCommandStack) domain .getCommandStack(); undoContext = workspaceCommandStack.getDefaultUndoContext(); } } return undoContext; } }); } private void addSelectReusedSiriussAction() { addAction("Select reused", new Runnable() { @Override public void run() { if (selection instanceof Viewpoint) { final Option<Set<URI>> sel = new ViewpoitnDependenciesSelectionDialog((Viewpoint) selection) .selectReusedViewpoints(getSite().getShell()); if (sel.some()) { ((Viewpoint) selection).getReuses().clear(); Iterables.addAll(((Viewpoint) selection).getReuses(), sel.get()); } } } }); } private void addShowMovidaRegistryStatusAction() { addAction("Show Registry Status", new Runnable() { @Override public void run() { if (registry != null) { StringBuilder status = new StringBuilder(); registry.dumpStatus(status); setText(status.toString()); } } }); } private void addStartMovidaRegistryAction() { addAction("Start Registry", new Runnable() { @Override public void run() { if (registry != null) { registry.stop(); } registry = new ViewpointRegistry(); registry.addListener(new ViewpointRegistryListener() { @Override public void registryChanged(ViewpointRegistry registry, Set<URI> removed, Set<URI> added, Set<URI> changed) { System.out.println(); System.out.println("Added:"); for (URI a : added) { System.out.println(" - " + a); } System.out.println("Removed:"); for (URI r : removed) { System.out.println(" - " + r); } System.out.println("Changed:"); for (URI c : changed) { System.out.println(" - " + c); } } }); registry.start(); } }); } private void addRefreshDiagramAction() { addAction("Refresh diagram", new Runnable() { @Override public void run() { if (selection instanceof DiagramEditPart) { final DiagramEditPart diag = (DiagramEditPart) selection; diag.refresh(); for (IGraphicalEditPart child : Iterables.filter(diag.getChildren(), IGraphicalEditPart.class)) { child.refresh(); } } } }); } private void addRefreshCoverageAction() { addAction("Refresh coverage", new Runnable() { @Override public void run() { if (selection instanceof SequenceDiagramEditPart) { final SequenceDiagramEditPart sdep = (SequenceDiagramEditPart) selection; TransactionalEditingDomain ted = sdep.getEditingDomain(); RefreshGraphicalCoverage refreshGraphicalCoverage = new RefreshGraphicalCoverage(ted, sdep); sdep.getEditingDomain().getCommandStack().execute(refreshGraphicalCoverage); } } }); } private void addExpandAction() { addAction("Expand", new Runnable() { @Override public void run() { if (selection instanceof SequenceDiagramEditPart) { final int start = Integer.parseInt(askStringFromUser("Expansion", "Start y", "0")); final int size = Integer.parseInt(askStringFromUser("Expansion", "Size", "0")); final SequenceDiagramEditPart sdep = (SequenceDiagramEditPart) selection; TransactionalEditingDomain ted = sdep.getEditingDomain(); RecordingCommand verticalSpaceExpansion = CommandFactory.createRecordingCommand(ted, new VerticalSpaceExpansion(sdep.getSequenceDiagram(), new Range(start, start + size), 0, Collections.<ISequenceEvent>emptyList())); sdep.getEditingDomain().getCommandStack().execute(verticalSpaceExpansion); } } }); } private void addRefreshBenpointsAction() { addAction("Refresh bendpoints", new Runnable() { @Override public void run() { if (selection instanceof SequenceMessageEditPart) { final SequenceMessageEditPart smep = (SequenceMessageEditPart) selection; TransactionalEditingDomain ted = smep.getEditingDomain(); RefreshBendpoints refreshBendpoints = new RefreshBendpoints(ted, smep); smep.getEditingDomain().getCommandStack().execute(refreshBendpoints); } else if (selection instanceof SequenceDiagramEditPart) { for (final SequenceMessageEditPart smep : Iterables.filter( ((SequenceDiagramEditPart) selection).getChildren(), SequenceMessageEditPart.class)) { TransactionalEditingDomain ted = smep.getEditingDomain(); RefreshBendpoints refreshBendpoints = new RefreshBendpoints(ted, smep); smep.getEditingDomain().getCommandStack().execute(refreshBendpoints); } } } }); } private void addResetBendpointsAction() { addAction("Reset bendpoints", new Runnable() { @Override public void run() { if (selection instanceof SequenceDiagramEditPart) { final SequenceDiagramEditPart sdep = (SequenceDiagramEditPart) selection; TransactionalEditingDomain ted = sdep.getEditingDomain(); RecordingCommand verticalSpaceExpansion = CommandFactory.createRecordingCommand(ted, new VerticalSpaceExpansion(sdep.getSequenceDiagram(), new Range(0, 0), 0, Lists.<ISequenceEvent>newArrayList())); sdep.getEditingDomain().getCommandStack().execute(verticalSpaceExpansion); } } }); } /** * Reads and remembers the vertical position of each element in a sequence * diagram. Use in conjunction with "Show Position Changes". */ private void addStorePositionsAction() { addAction("Store positions", new Runnable() { @Override public void run() { if (selection instanceof SequenceDiagramEditPart) { SequenceDiagramEditPart sdep = (SequenceDiagramEditPart) selection; storedPositions = readVerticalPositions(sdep); } } }); } /** * Prints a report of which elements changed position in a sequence diagram * since the last call to "Store positions". Only the elements whose * position is different are shown (i.e. an empty report means nothing * changed). */ private void addShowPositionChangesAction() { addAction("Show Position Changes", new Runnable() { @Override public void run() { if (selection instanceof SequenceDiagramEditPart) { SequenceDiagramEditPart sdep = (SequenceDiagramEditPart) selection; if (storedPositions != null) { Map<EObject, Integer> newPositions = readVerticalPositions(sdep); List<EObject> elements = Lists.newArrayList(newPositions.keySet()); Collections.sort(elements, Ordering.natural().onResultOf(Functions.forMap(newPositions))); TabularReport report = new TabularReport("Semantic element", "Old Position", "New Position", "deltaY"); AdapterFactoryLabelProvider lp = new AdapterFactoryLabelProvider(getAdapterFactory()); for (EObject element : elements) { Integer oldY = storedPositions.get(element); Integer newY = newPositions.get(element); if (oldY != null && !oldY.equals(newY)) { report.addLine(lp.getText(element), String.valueOf(oldY), String.valueOf(newY), String.valueOf(newY - oldY)); } else if (oldY == null) { report.addLine(lp.getText(element), "-", String.valueOf(newY), "n/a"); } else if (newY == VerticalPositionFunction.INVALID_POSITION) { report.addLine(lp.getText(element), String.valueOf(oldY), "-", "n/a"); } } setText(report.print()); } } } }); } private Map<EObject, Integer> readVerticalPositions(SequenceDiagramEditPart sdep) { SequenceDDiagram diag = (SequenceDDiagram) sdep.resolveSemanticElement(); VerticalPositionFunction vpf = new VerticalPositionFunction(diag); Map<EObject, Integer> positions = Maps.newHashMap(); for (EventEnd end : diag.getGraphicalOrdering().getEventEnds()) { positions.put(end.getSemanticEnd(), (int) vpf.apply(end)); } return positions; } /** * Prints a report of the graphical and semantic orderings on a sequence * diagram. For elements which have a valid graphical position, it is also * reported. */ private void addShowOrderingsAction() { addAction("Orderings", new Runnable() { @Override public void run() { if (selection instanceof SequenceDiagramEditPart) { AdapterFactoryLabelProvider lp = new AdapterFactoryLabelProvider(getAdapterFactory()); SequenceDiagramEditPart sdep = (SequenceDiagramEditPart) selection; SequenceDDiagram diag = (SequenceDDiagram) sdep.resolveSemanticElement(); VerticalPositionFunction vpf = new VerticalPositionFunction(diag); Iterator<EventEnd> go = diag.getGraphicalOrdering().getEventEnds().iterator(); Iterator<EventEnd> so = diag.getSemanticOrdering().getEventEnds().iterator(); TabularReport report = new TabularReport("Semantic", "Graphical", "Sync?", "Y"); while (so.hasNext() || go.hasNext()) { List<String> line = Lists.newArrayList(); final EObject sosEnd; if (so.hasNext()) { EventEnd soEnd = so.next(); sosEnd = soEnd.getSemanticEnd(); line.add(lp.getText(sosEnd)); } else { sosEnd = null; line.add("<none>"); } final EObject gosEnd; final int y; if (go.hasNext()) { EventEnd goEnd = go.next(); gosEnd = goEnd.getSemanticEnd(); line.add(lp.getText(gosEnd)); y = vpf.apply(goEnd); } else { gosEnd = null; line.add("<none>"); y = -1; } if (sosEnd == gosEnd) { line.add("yes"); } else { line.add("NO"); } line.add(y != -1 ? String.valueOf(y) : "n/a"); report.addLine(line); } setText(report.print()); } } }); } private void addFoldingToggleAction() { addAction("Toggle folding", new Runnable() { @Override public void run() { if (selection instanceof IAbstractDiagramNodeEditPart) { IAbstractDiagramNodeEditPart part = (IAbstractDiagramNodeEditPart) selection; EdgeTargetQuery query = new EdgeTargetQuery((EdgeTarget) part.resolveDiagramElement()); boolean isFoldingPoint = query.isFoldingPoint(); if (isFoldingPoint) { part.getEditingDomain().getCommandStack() .execute(new ToggleFoldingStateCommand(part.getEditingDomain(), part)); } } } }); } /** * Show details about each edit part */ private void addShowEditPartsHierarchyAction() { addAction("Show Edit Parts", new ShowEditPartsHierarchy(this)); } /** * Show details about each figure in the Draw2D hierarchy starting from the * current selection's figure. See {@link #figureDetails(IFigure)} for what * information is actually shown for each figure. */ private void addShowFiguresHierarchyAction() { addAction("Show figures", new Runnable() { @Override public void run() { if (selection instanceof IAbstractDiagramNodeEditPart) { IAbstractDiagramNodeEditPart part = (IAbstractDiagramNodeEditPart) selection; StringBuilder sb = new StringBuilder(); showFigures(part.getFigure(), 0, sb); setText(sb.toString()); } } }); } private void showFigures(IFigure figure, int level, StringBuilder out) { for (int i = 0; i < level; i++) { out.append(" "); } out.append(figureDetails(figure)).append("\n"); for (IFigure child : Iterables.filter(figure.getChildren(), IFigure.class)) { showFigures(child, level + 1, out); } } private String figureDetails(IFigure figure) { return "Opaque: " + figure.isOpaque() + " Color: " + figure.getBackgroundColor() + " Class: " + figure.getClass().getSimpleName() + " Size: " + figure.getBounds().getSize(); } private static class RefreshGraphicalCoverage extends RecordingCommand { private SequenceDiagramEditPart sdep; public RefreshGraphicalCoverage(TransactionalEditingDomain domain, SequenceDiagramEditPart sdep) { super(domain); this.sdep = sdep; } @Override protected void doExecute() { new SequenceDiagramLayout(sdep).refreshGraphicalCoverage(); } } private static class RefreshBendpoints extends RecordingCommand { private SequenceMessageEditPart smep; public RefreshBendpoints(TransactionalEditingDomain domain, SequenceMessageEditPart smep) { super(domain); this.smep = smep; } @Override protected void doExecute() { smep.refreshBendpoints(); } } }