/******************************************************************************* * Copyright (c) 2010 Herman Lee. * 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: * Herman Lee - initial API and implementation ******************************************************************************/ package ca.uwaterloo.gsd.fsml.outline.popup.actions; import java.util.HashMap; import java.util.List; import java.util.Vector; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.emf.common.notify.impl.AdapterFactoryImpl; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.emf.edit.provider.ComposedAdapterFactory; import org.eclipse.emf.edit.provider.ReflectiveItemProviderAdapterFactory; import org.eclipse.emf.edit.provider.resource.ResourceItemProviderAdapterFactory; import org.eclipse.emf.edit.ui.provider.AdapterFactoryContentProvider; import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.ITypeRoot; import org.eclipse.jdt.core.dom.AST; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.ASTParser; import org.eclipse.jdt.internal.corext.dom.NodeFinder; import org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor; import org.eclipse.jdt.ui.JavaUI; import org.eclipse.jface.action.IAction; import org.eclipse.jface.text.DocumentEvent; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IDocumentListener; import org.eclipse.jface.text.ITextSelection; import org.eclipse.jface.util.OpenStrategy; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.TreeItem; import org.eclipse.ui.IEditorActionDelegate; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.ISelectionListener; import org.eclipse.ui.ISelectionService; import org.eclipse.ui.IViewSite; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.PartInitException; import org.eclipse.ui.ide.IDE; import org.eclipse.ui.part.FileEditorInput; import org.eclipse.ui.part.ViewPart; import org.eclipse.ui.texteditor.ITextEditor; import ca.uwaterloo.gsd.fsml.core.MarkerDescriptor; import ca.uwaterloo.gsd.fsml.core.Markers; import ca.uwaterloo.gsd.fsml.ecore.FSMLEcoreUtil; import ca.uwaterloo.gsd.fsml.fsml.Model; import ca.uwaterloo.gsd.fsml.fsml.ModelContainer; import ca.uwaterloo.gsd.fsml.javaMappingInterpreter.JavaMarkers; public class FSMLModelOutlineView extends ViewPart implements ISelectionListener, IEditorActionDelegate, ISelectionChangedListener, IDocumentListener { public final static String[] supportedProjectExtensions = new String[] { ".applet", ".struts", ".wpi" }; private IJavaElement cu; private HashMap<String, EObject> fsmlId2ModelEObject; private TreeViewer viewer; private ITextEditor activeEditor; private Model assertedModel; private IFile fsmlModelFile; @Override public void init(IViewSite site) throws PartInitException { super.init(site); ISelectionService service = site.getWorkbenchWindow() .getSelectionService(); service.addPostSelectionListener(this); IWorkbenchPage activePage = site.getWorkbenchWindow().getActivePage(); if (activePage!=null){ IEditorPart activeEditor = activePage.getActiveEditor(); if (activeEditor instanceof ITextEditor){ this.activeEditor = (ITextEditor)activeEditor; } } } @Override public void createPartControl(Composite parent) { // TODO Auto-generated method stub List<AdapterFactoryImpl> factories = new Vector<AdapterFactoryImpl>(); factories.add(new ResourceItemProviderAdapterFactory()); factories.add(new ReflectiveItemProviderAdapterFactory()); ComposedAdapterFactory adapterFactory = new ComposedAdapterFactory( factories); viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); viewer.setContentProvider(new AdapterFactoryContentProvider( adapterFactory)); viewer .setLabelProvider(new AdapterFactoryLabelProvider( adapterFactory)); viewer.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent event) { if (viewer.getControl().isFocusControl()) { TreeItem[] selection = viewer.getTree().getSelection(); EObject selectedEObject = (EObject) selection[0].getData(); List<IMarker> markers = Markers.INSTANCE .getMarkers(FSMLEcoreUtil.getFSMLId( selectedEObject, null)); if (markers.size() > 0) { try { IDE.openEditor(getSite().getPage(), markers.get(0), OpenStrategy.activateOnOpen()); } catch (PartInitException e) { e.printStackTrace(); } } } } }); if (activeEditor!=null){ linkEditorWithOutlineView(activeEditor); } } @Override public void setActiveEditor(IAction action, IEditorPart sourceEditor) { if (sourceEditor instanceof ITextEditor) { this.activeEditor = (ITextEditor) sourceEditor; } } @Override public void run(IAction action) { if (activeEditor != null) { try { activeEditor.getSite().getPage().showView( "ca.uwaterloo.gsd.fsml.outline.FSMLModelOutlineView"); } catch (PartInitException e) { e.printStackTrace(); } } } @Override public void selectionChanged(IAction action, ISelection selection) { } @Override public void selectionChanged(SelectionChangedEvent event) { } @Override public void selectionChanged(IWorkbenchPart part, ISelection selection) { if (!(selection instanceof ITextSelection) || !(part instanceof CompilationUnitEditor)) { return; } IEditorInput editorInput = ((CompilationUnitEditor)part).getEditorInput(); IJavaElement currentEditorCU=null; if (editorInput != null) currentEditorCU = JavaUI.getEditorInputJavaElement(editorInput); if (cu == null || !currentEditorCU.equals(cu)) { boolean result = linkEditorWithOutlineView((ITextEditor) part); if (!result){ return; } } ITextSelection textSelection = (ITextSelection) selection; NodeFinder finder = new NodeFinder(textSelection.getOffset(), 0); // compute actual code transformation proposals ASTParser parser = ASTParser.newParser(AST.JLS3); parser.setSource((ITypeRoot) cu); parser.setStatementsRecovery(true); parser.setResolveBindings(true); parser.createAST(null).accept(finder); ASTNode coveringNode = finder.getCoveringNode(); Vector<IMarker> markers = JavaMarkers.getMarkersCoveredByNode(coveringNode); IMarker targetMarker = null; int targetMarkerRange = 0; int markerStartPos = 0; int markerEndPos = 0; for (IMarker marker : markers) { try { markerStartPos = ((Integer) marker .getAttribute(MarkerDescriptor.ATTRIBUTE_CHAR_START)) .intValue(); markerEndPos = ((Integer) marker .getAttribute(MarkerDescriptor.ATTRIBUTE_CHAR_END)) .intValue(); if (targetMarker == null) { targetMarker = marker; targetMarkerRange = markerEndPos - markerStartPos; } else if (markerEndPos - markerStartPos < targetMarkerRange) { targetMarkerRange = markerEndPos - markerStartPos; targetMarker = marker; } } catch (CoreException e) { e.printStackTrace(); } } if (targetMarker != null) { EObject eObject; try { eObject = fsmlId2ModelEObject.get(targetMarker .getAttribute(MarkerDescriptor.ATTRIBUTE_ID)); if (eObject != null) { eObject = assertedModel.eResource() .getResourceSet().getEObject( EcoreUtil.getURI(eObject), true); viewer.setSelection(new StructuredSelection(eObject), true); } } catch (CoreException e) { e.printStackTrace(); } } } private boolean linkEditorWithOutlineView(ITextEditor sourceEditor) { activeEditor = sourceEditor; IFile editorFile=null; if (sourceEditor.getEditorInput() instanceof FileEditorInput) { FileEditorInput editorInput = (FileEditorInput) sourceEditor .getEditorInput(); editorFile = editorInput.getFile(); IDocument document = sourceEditor.getDocumentProvider() .getDocument(editorInput); document.addDocumentListener(this); } fsmlModelFile = null; int retryAttempt = 0; boolean foundFile = false; String numbering = null; while (retryAttempt < 10 && !foundFile) { for (int i = 0; i < supportedProjectExtensions.length; i++) { numbering = (retryAttempt == 0) ? "" : "_" + retryAttempt; fsmlModelFile = ResourcesPlugin .getWorkspace() .getRoot() .getFile( editorFile .getProject() .getFullPath() .append( editorFile.getProject().getName() + numbering + supportedProjectExtensions[i])); if (fsmlModelFile.exists()) { foundFile = true; break; } } retryAttempt++; } if (!fsmlModelFile.exists()){ return false; } IEditorInput editorInput = sourceEditor.getEditorInput(); if (editorInput != null) cu = JavaUI.getEditorInputJavaElement(editorInput); Markers.INSTANCE.setProject(cu.getJavaProject().getProject()); reloadModelFromDisk(); return true; } private void reloadModelFromDisk() { ResourceSet resourceSet = new ResourceSetImpl(); URI fsmlModelURI = URI.createPlatformResourceURI(fsmlModelFile .getFullPath().toString(), true); if (fsmlModelFile.exists()) { Resource resource = resourceSet.getResource(fsmlModelURI, true); EList<EObject> fsmlModel = resource.getContents(); assertedModel = ((ModelContainer) fsmlModel.get(0)) .getAssertedModel(); fsmlId2ModelEObject = new HashMap<String, EObject>(); FSMLEcoreUtil.createFsmlId2EObjectMap(assertedModel, fsmlId2ModelEObject); viewer.setInput(assertedModel); viewer.expandAll(); viewer.refresh(); } } @Override public void setFocus() { viewer.getControl().setFocus(); } public void refresh() { viewer.refresh(); } public void documentAboutToBeChanged(DocumentEvent event) { } public void documentChanged(DocumentEvent event) { reloadModelFromDisk(); } }