/*******************************************************************************
 * Copyright (c) 2007 IBM Corporation and others.
 * 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdt.debug.tests.ui;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.model.IThread;
import org.eclipse.debug.internal.core.IInternalDebugCoreConstants;
import org.eclipse.debug.internal.ui.DebugUIPlugin;
import org.eclipse.debug.internal.ui.InstructionPointerAnnotation;
import org.eclipse.debug.internal.ui.InstructionPointerManager;
import org.eclipse.debug.internal.ui.viewers.model.InternalTreeModelViewer;
import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.debug.ui.IDebugView;
import org.eclipse.jdt.debug.core.IJavaDebugTarget;
import org.eclipse.jdt.debug.core.IJavaLineBreakpoint;
import org.eclipse.jdt.debug.core.IJavaStackFrame;
import org.eclipse.jdt.debug.core.IJavaThread;
import org.eclipse.jdt.debug.tests.AbstractDebugTest;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.AnnotationModelEvent;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.jface.text.source.IAnnotationModelListener;
import org.eclipse.jface.text.source.IAnnotationModelListenerExtension;
import org.eclipse.jface.viewers.TreePath;
import org.eclipse.jface.viewers.TreeSelection;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IPartListener2;
import org.eclipse.ui.IPerspectiveDescriptor;
import org.eclipse.ui.IPerspectiveListener2;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.ITextEditor;

/**
 * Tests functionality of the InstructionPointerManager.
 * The tests are not currently part of the automated suite because they produce
 * transient failures that could not be tracked down.
 * 
 * @since 3.3
 * @see InstructionPointerManager
 */
public class InstructionPointerManagerTests extends AbstractDebugTest {

	private Object fLock = new Object();
	private Annotation fAddedAnnotation = null;
	private Annotation fRemovedAnnotation = null;
	
	private MyPerspectiveListener fPerspectiveListener;
	private MyAnnotationListener fAnnotationListener;
	private IPartListener2 fPartListener;
	private Set fAnnotationModelsWithListeners = new HashSet();
	
	private static final String typeThreadStack = "org.eclipse.debug.tests.targets.ThreadStack";
	private static final String typeClassOne = "org.eclipse.debug.tests.targets.ClassOne";
	private static final String typeClassTwo = "org.eclipse.debug.tests.targets.ClassTwo";
	
	private IJavaDebugTarget target1;
	private IJavaDebugTarget target2;
	private IJavaThread thread1;
	private IJavaThread thread2;
	private IJavaThread thread3;
	private IJavaThread thread4;
	
	public InstructionPointerManagerTests(String name) {
		super(name);
	}
	
	public void testManagerWithEditorReuse() throws Exception{
		boolean restore = DebugUIPlugin.getDefault().getPreferenceStore().getBoolean(IDebugUIConstants.PREF_REUSE_EDITOR);
		DebugUIPlugin.getDefault().getPreferenceStore().setValue(IDebugUIConstants.PREF_REUSE_EDITOR, true);
		
		try{
			addAndRemoveAnnotations(new int[]{1,2,1,2,1,0,1,1}, new int[]{1,1,1,1,1,0,1,1});
		} finally {
			System.out.println("Cleanup");
			if (target1 != null){
				terminateAndRemove(target1);
			}
			if (target2 != null){
				terminateAndRemove(target2);
			}
			Iterator annModels = fAnnotationModelsWithListeners.iterator();
			while (annModels.hasNext()) {
				IAnnotationModel currentModel = (IAnnotationModel) annModels.next();
				currentModel.removeAnnotationModelListener(getAnnotationListener());
			}
			removeAllBreakpoints();
			DebugUIPlugin.getDefault().getPreferenceStore().setValue(IDebugUIConstants.PREF_REUSE_EDITOR, restore);
			Runnable cleanup = new Runnable() {
                public void run() {
                    IWorkbenchWindow activeWorkbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
                    activeWorkbenchWindow.removePerspectiveListener(getPerspectiveListener());
                }
            };
            DebugUIPlugin.getStandardDisplay().asyncExec(cleanup);	
		}
	}
	
	public void testManagerWithNoEditorReuse() throws Exception{
		boolean restore = DebugUIPlugin.getDefault().getPreferenceStore().getBoolean(IDebugUIConstants.PREF_REUSE_EDITOR);
		DebugUIPlugin.getDefault().getPreferenceStore().setValue(IDebugUIConstants.PREF_REUSE_EDITOR, false);
		
		try{
			addAndRemoveAnnotations(new int[]{1,2,3,4,5,3,2,1}, new int[]{1,1,2,2,3,2,2,1});
		} finally {
			System.out.println("Cleanup");
			if (target1 != null){
				terminateAndRemove(target1);
			}
			if (target2 != null){
				terminateAndRemove(target2);
			}
			Iterator annModels = fAnnotationModelsWithListeners.iterator();
			while (annModels.hasNext()) {
				IAnnotationModel currentModel = (IAnnotationModel) annModels.next();
				currentModel.removeAnnotationModelListener(getAnnotationListener());
			}
			removeAllBreakpoints();
			DebugUIPlugin.getDefault().getPreferenceStore().setValue(IDebugUIConstants.PREF_REUSE_EDITOR, restore);
			Runnable cleanup = new Runnable() {
                public void run() {
                    IWorkbenchWindow activeWorkbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
                    activeWorkbenchWindow.removePerspectiveListener(getPerspectiveListener());
                }
            };
            DebugUIPlugin.getStandardDisplay().asyncExec(cleanup);	
		}
	}
	
	/**
	 * Tests the ability of the manager to update it's set and mapping as
	 * annotations are added and removed.
	 * 
	 * First, all editors are closed and the manager is checked to ensure there are 0 IPCs.
	 * 
	 * <p>Next, annotations are created as follows:<br>
	 * (numbers in brackets correspond to index of expected IPC and Mapping counts checked)
	 * <pre>
	 * Target1	- Thread1	- IPC1	- ClassOne		- Editor1 (line 20)	[0]
	 *      	- Thread2	- IPC2	- ClassOne		- Editor1 (line 20)	[1]
	 * 						- IPC3	- ThreadStack	- Editor2 (line 28)	[2]
	 * 
	 * Target2	- Thread3	- IPC4	- ThreadStack	- Editor2 (line 41) [3]
	 *      	- Thread4	- IPC5	- ClassTwo		- Editor3 (line 24) [4]
	 * </pre>
	 * </p>
	 * <p>They are then removed as follows:<br>
	 * (numbers in brackets correspond to index of expected IPC and Mapping counts checked)
	 * <ol>
	 * <li>Target2 is terminated [5]</li>
	 * <li>Thread1 is resumed [6]</li>
	 * <li>Editor2 is closed [7]</li>
	 * <li>All editors are closed, closing Editor1, No IPCs should exist</li>
	 * </ol>
	 * </p>
	 * @param expectedIPCCounts array of expected values for IPC count at each step as marked above, length must be 8
	 * @param expectedMappingCounts array of expected values for editor mapping count at each step as marked above, length must be 8
	 * @throws Exception
	 */
	private void addAndRemoveAnnotations(int[] expectedIPCCounts, int[] expectedMappingCounts) throws Exception{
		assertEquals("Incorrect number of expected counts", 8, expectedIPCCounts.length);
		assertEquals("Incorrect number of expected counts", 8, expectedMappingCounts.length);
		
		// Close all editors
	    Runnable closeAll = new Runnable() {
            public void run() {
                IWorkbenchWindow activeWorkbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
                activeWorkbenchWindow.getActivePage().closeAllEditors(false);
                activeWorkbenchWindow.addPerspectiveListener(getPerspectiveListener());
            }
        };
        DebugUIPlugin.getStandardDisplay().syncExec(closeAll);
        assertEquals("Instruction pointer count was incorrect", 0, InstructionPointerManager.getDefault().getInstructionPointerCount());
        assertEquals("Editor mapping count was incorrect", 0, InstructionPointerManager.getDefault().getEditorMappingCount());
		         
        // ADD ANNOTATIONS
        
        // Launch a target creating two threads, both suspend in ClassOne, one will automatically be selected
        IJavaLineBreakpoint breakpoint = createLineBreakpoint(20, typeClassOne);
        fAddedAnnotation = null;
        getPerspectiveListener().setTitle(typeClassOne);
        thread1 = launchAndSuspend(typeThreadStack);
        target1 = (IJavaDebugTarget)thread1.getDebugTarget();
        assertNotNull("Target was not launched.",target1);
        assertNotNull("Target was not launched.",thread1);
        waitForAnnotationToBeAdded();
        assertEquals("Instruction pointer count was incorrect", expectedIPCCounts[0], InstructionPointerManager.getDefault().getInstructionPointerCount());
        assertEquals("Editor mapping count was incorrect", expectedMappingCounts[0], InstructionPointerManager.getDefault().getEditorMappingCount());
        
        // Find and select the top stack frame of the other thread
        Runnable openParent = new Runnable() {
            public void run() {
                IDebugView debugView = (IDebugView)PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().findView("org.eclipse.debug.ui.DebugView");
                Object[] newSegments = new Object[4];
            	newSegments[0] = target1.getLaunch();
            	newSegments[1] = target1;
            	try{
                	IThread[] threads = ((IJavaDebugTarget)newSegments[1]).getThreads();
                	for (int i = 0; i < threads.length; i++) {
						if (threads[i].isSuspended() && !threads[i].equals(thread1)){
							thread2 = (IJavaThread)threads[i];
							newSegments[2] = threads[i];
							newSegments[3] = threads[i].getTopStackFrame();
						}
					}
                	((InternalTreeModelViewer)debugView.getViewer()).setSelection(new TreeSelection(new TreePath(newSegments)), true, true);
            	} catch (DebugException e){
            		fail("Exception: " + e.getMessage());
            	}
            }
        };
        fAddedAnnotation = null;
        getPerspectiveListener().setTitle(typeClassOne);
        DebugUIPlugin.getStandardDisplay().syncExec(openParent);
        waitForAnnotationToBeAdded();
        assertNotNull("Thread not selected",thread2);
        assertEquals("Instruction pointer count was incorrect", expectedIPCCounts[1], InstructionPointerManager.getDefault().getInstructionPointerCount());
        assertEquals("Editor mapping count was incorrect", expectedMappingCounts[1], InstructionPointerManager.getDefault().getEditorMappingCount());
        
        // Select the same stack frame and make sure IPC count doesn't change
        Runnable selectSameStackFrame = new Runnable() {
            public void run() {
                IDebugView debugView = (IDebugView)PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().findView("org.eclipse.debug.ui.DebugView");
                Object[] newSegments = new Object[4];
            	newSegments[0] = target1.getLaunch();
            	newSegments[1] = target1;
            	newSegments[2] = thread2;
            	try { 
            		newSegments[3] = thread2.getTopStackFrame();
            	} catch (DebugException e) {
					fail("Exception: " + e.getMessage());
				}
                ((InternalTreeModelViewer)debugView.getViewer()).setSelection(new TreeSelection(new TreePath(newSegments)), true, true);
            }
        };
        fAddedAnnotation = null;
        getPerspectiveListener().setTitle(typeClassOne);
        DebugUIPlugin.getStandardDisplay().syncExec(selectSameStackFrame);
        waitForAnnotationToBeAdded();
        assertEquals("Instruction pointer count was incorrect", expectedIPCCounts[1], InstructionPointerManager.getDefault().getInstructionPointerCount());
        assertEquals("Editor mapping count was incorrect", expectedMappingCounts[1], InstructionPointerManager.getDefault().getEditorMappingCount());
        
        // Select the next stack frame in the same thread
        Runnable selectSecondStackFrame = new Runnable() {
            public void run() {
                IDebugView debugView = (IDebugView)PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().findView("org.eclipse.debug.ui.DebugView");
                Object[] newSegments = new Object[4];
            	newSegments[0] = target1.getLaunch();
            	newSegments[1] = target1;
            	newSegments[2] = thread2;
            	try{
            		newSegments[3] = thread2.getStackFrames()[1];  // Select the next stack frame
            	} catch (DebugException e){
            		fail("Exception: " + e.getMessage());
            	}
            	((InternalTreeModelViewer)debugView.getViewer()).setSelection(new TreeSelection(new TreePath(newSegments)), true, true);
            }
        };
        fAddedAnnotation = null;
        getPerspectiveListener().setTitle(typeThreadStack);
        DebugUIPlugin.getStandardDisplay().syncExec(selectSecondStackFrame);
        waitForAnnotationToBeAdded();
        // Failure here, reuse, expected 1 but was 2, also with no reuse, expected 3 but was 2
        assertEquals("Instruction pointer count was incorrect", expectedIPCCounts[2], InstructionPointerManager.getDefault().getInstructionPointerCount());
        assertEquals("Editor mapping count was incorrect", expectedMappingCounts[2], InstructionPointerManager.getDefault().getEditorMappingCount());
	
        // Remove the breakpoint from before and create new ones, start a new target
        breakpoint.delete();
        createLineBreakpoint(41, typeThreadStack);
        createLineBreakpoint(24, typeClassTwo);
        target2 = (IJavaDebugTarget)launchAndSuspend(typeThreadStack).getDebugTarget();
        assertNotNull("Target was not launched", target2);
        assertEquals("Instruction pointer count was incorrect", expectedIPCCounts[2], InstructionPointerManager.getDefault().getInstructionPointerCount());
        assertEquals("Editor mapping count was incorrect", expectedMappingCounts[2], InstructionPointerManager.getDefault().getEditorMappingCount());
	
       // Select the stack frame from the new debug target displaying ThreadStack
       Runnable openOtherDebugTarget = new Runnable() {
            public void run() {
                IDebugView debugView = (IDebugView)PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().findView("org.eclipse.debug.ui.DebugView");
                ILaunch[] launches = DebugPlugin.getDefault().getLaunchManager().getLaunches();
                Object[] newSegments = new Object[4];
                for (int i = 0; i < launches.length; i++) {
					if (target2.equals(launches[i].getDebugTarget())){
						newSegments[0] = launches[i];
						newSegments[1] = target2;
						try{
							IThread[] threads = target2.getThreads();
							for (int j = 0; j < threads.length; j++) {
								if (threads[j].isSuspended()){
									if (typeThreadStack.equals(((IJavaStackFrame)threads[j].getTopStackFrame()).getDeclaringTypeName())){
										thread3 = (IJavaThread)threads[j];
										newSegments[2] = threads[j];
										newSegments[3] = threads[j].getTopStackFrame();
										break;
									}
								}
							}
						} catch (DebugException e){
							fail("Exception: " + e.getMessage());
						}
						break;
					}
				}
				((InternalTreeModelViewer)debugView.getViewer()).setSelection(new TreeSelection(new TreePath(newSegments)), true, true);
            }
       };
       fAddedAnnotation = null;
       getPerspectiveListener().setTitle(typeThreadStack);
       DebugUIPlugin.getStandardDisplay().syncExec(openOtherDebugTarget);
       assertNotNull("Thread was not selected",thread3);
       waitForAnnotationToBeAdded();
       assertEquals("Instruction pointer count was incorrect", expectedIPCCounts[3], InstructionPointerManager.getDefault().getInstructionPointerCount());
       assertEquals("Editor mapping count was incorrect", expectedMappingCounts[3], InstructionPointerManager.getDefault().getEditorMappingCount());
       
       // Select the other thread from the new target displaying ClassTwo
       Runnable openOtherThread = new Runnable() {
            public void run() {
            	IDebugView debugView = (IDebugView)PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().findView("org.eclipse.debug.ui.DebugView");
                Object[] newSegments = new Object[4];
            	newSegments[0] = target2.getLaunch();
            	newSegments[1] = target2;
            	try{
                	IThread[] threads = target2.getThreads();
                	for (int i = 0; i < threads.length; i++) {
						if (threads[i].isSuspended() && !threads[i].equals(thread3)){
							thread4 = (IJavaThread)threads[i];
							newSegments[2] = threads[i];
							newSegments[3] = threads[i].getTopStackFrame();
						}
					}
                	((InternalTreeModelViewer)debugView.getViewer()).setSelection(new TreeSelection(new TreePath(newSegments)), true, true);
            	} catch (DebugException e){
            		fail("Exception: " + e.getMessage());
            	}
            }
       };
       fAddedAnnotation = null;
       getPerspectiveListener().setTitle(typeClassTwo);
       DebugUIPlugin.getStandardDisplay().syncExec(openOtherThread);
       assertNotNull("Thread was not selected",thread4);
       waitForAnnotationToBeAdded();
       assertEquals("Instruction pointer count was incorrect", expectedIPCCounts[4], InstructionPointerManager.getDefault().getInstructionPointerCount());
       assertEquals("Editor mapping count was incorrect", expectedMappingCounts[4], InstructionPointerManager.getDefault().getEditorMappingCount());

       // REMOVE ANNOTATIONS
       
       // Remove target2
       fRemovedAnnotation = null;
       target2.terminate();
       waitForAnnotationToBeRemoved();
       assertEquals("Instruction pointer count was incorrect", expectedIPCCounts[5], InstructionPointerManager.getDefault().getInstructionPointerCount());
       assertEquals("Editor mapping count was incorrect", expectedMappingCounts[5], InstructionPointerManager.getDefault().getEditorMappingCount());

       // TODO Selection of the other target does not occur automatically.  This functionality may change and will break this test.
       
       // Resume thread1
       fRemovedAnnotation = null;
       thread1.resume();
       waitForAnnotationToBeRemoved();
       assertEquals("Instruction pointer count was incorrect", expectedIPCCounts[6], InstructionPointerManager.getDefault().getInstructionPointerCount());
       assertEquals("Editor mapping count was incorrect", expectedMappingCounts[6], InstructionPointerManager.getDefault().getEditorMappingCount());

       // Close the editor displaying ThreadStack.java if it is open
	   Runnable closeEditor2 = new Runnable() {
           public void run() {
               IWorkbenchWindow activeWorkbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
               IEditorReference[] editors = activeWorkbenchWindow.getActivePage().getEditorReferences();
               for (int i = 0; i < editors.length; i++) {
            	   if (editors[i].getTitle().equals("ThreadStack.java")){
            		   activeWorkbenchWindow.getActivePage().closeEditors(new IEditorReference[]{editors[i]},false);
            		   fRemovedAnnotation = null;  // Clear the removed annotation so the test waits for the annotation to be removed
            		   break;
            	   }
               }
			}
	   };
	   // fRemovedAnnotation is used here to check if the editor has been found and closed successfully.  It is set to a annotation object, and will only be reset to null (causing the wait to occur) if the editor is closed.
       fRemovedAnnotation = new Annotation(true);
       DebugUIPlugin.getStandardDisplay().syncExec(closeEditor2);
       waitForAnnotationToBeRemoved();
       assertEquals("Instruction pointer count was incorrect", expectedIPCCounts[7], InstructionPointerManager.getDefault().getInstructionPointerCount());
       assertEquals("Editor mapping count was incorrect", expectedMappingCounts[7], InstructionPointerManager.getDefault().getEditorMappingCount());

       // Close all editors
	   Runnable closeAllEditors = new Runnable() {
           public void run() {
               IWorkbenchWindow activeWorkbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
               activeWorkbenchWindow.getActivePage().closeAllEditors(false);
			}
	   };
       fRemovedAnnotation = null;
       DebugUIPlugin.getStandardDisplay().syncExec(closeAllEditors);
       waitForAnnotationToBeRemoved();
       assertEquals("Instruction pointer count was incorrect", 0, InstructionPointerManager.getDefault().getInstructionPointerCount());
       assertEquals("Editor mapping count was incorrect", 0, InstructionPointerManager.getDefault().getEditorMappingCount());
	}
	
	protected MyPerspectiveListener getPerspectiveListener(){
		if (fPerspectiveListener == null){
			fPerspectiveListener = new MyPerspectiveListener();
			return fPerspectiveListener;
		} else {
			return fPerspectiveListener;
		}
	}
	
	protected MyAnnotationListener getAnnotationListener(){
		if (fAnnotationListener == null){
			fAnnotationListener = new MyAnnotationListener();
			return fAnnotationListener;
		} else {
			return fAnnotationListener;
		}
	}
	
	private IPartListener2 getPartListener(){
		if (fPartListener == null){
			fPartListener = new MyPartListener();
			return fPartListener;
		} else {
			return fPartListener;
		}
	}
	
	private void waitForAnnotationToBeAdded() throws Exception{
		synchronized (fLock) {
		    if (fAddedAnnotation == null) {
		        fLock.wait(5000);
		    }
        }		
		assertNotNull("Annotation was not added properly");
		
		// Synchronize with the UI thread so we know that the annotations have finished
		Runnable runner = new Runnable(){
			public void run() {
				// Do nothing, just waiting for the UI thread to finish annotations
			}
		};
		DebugUIPlugin.getStandardDisplay().syncExec(runner);
	}
	
	private void waitForAnnotationToBeRemoved() throws Exception{
		synchronized (fLock) {
		    if (fRemovedAnnotation == null) {
		    	fLock.wait(5000);
		    }
        }		
		assertNotNull("Annotation was not removed properly");
		
		// Synchronize with the UI thread so we know that the annotations have finished
		Runnable runner = new Runnable(){
			public void run() {
				// Do nothing, just waiting for the UI thread to finish annotations
			}
		};
		DebugUIPlugin.getStandardDisplay().syncExec(runner);
	}
	
	class MyPerspectiveListener implements IPerspectiveListener2 {

		private String fTypeName = IInternalDebugCoreConstants.EMPTY_STRING;
		private String fTitle = IInternalDebugCoreConstants.EMPTY_STRING;
		
		public void perspectiveActivated(IWorkbenchPage page, IPerspectiveDescriptor perspective) {}
		public void perspectiveChanged(IWorkbenchPage page, IPerspectiveDescriptor perspective, String changeId) {}
			
		/* (non-Javadoc)
		 * @see org.eclipse.ui.IPerspectiveListener2#perspectiveChanged(org.eclipse.ui.IWorkbenchPage, org.eclipse.ui.IPerspectiveDescriptor, org.eclipse.ui.IWorkbenchPartReference, java.lang.String)
		 */
		public void perspectiveChanged(IWorkbenchPage page, IPerspectiveDescriptor perspective, IWorkbenchPartReference partRef, String changeId) {
            if (partRef.getTitle().equals(fTitle) && changeId == IWorkbenchPage.CHANGE_EDITOR_OPEN) {
            	IEditorPart editor = (IEditorPart) partRef.getPart(true);
            	if (editor instanceof ITextEditor){
        			IDocumentProvider docProvider = ((ITextEditor)editor).getDocumentProvider();
        			IEditorInput editorInput = editor.getEditorInput();
        	        // If there is no annotation model, there's nothing more to do
        	        IAnnotationModel annModel = docProvider.getAnnotationModel(editorInput);
        	        if (annModel == null) {
        	            fail("Could not get the annotation model");
        	        }  
        	        annModel.addAnnotationModelListener(getAnnotationListener());
        	        fAnnotationModelsWithListeners.add(annModel);
        		} else {
        			fail("Editor was not a text editor");
        		}
            	partRef.getPage().addPartListener(getPartListener());
            }
            if (changeId == IWorkbenchPage.CHANGE_EDITOR_CLOSE) {
            	if (partRef.getPage().getEditorReferences().length == 0){
            		partRef.getPage().removePartListener(getPartListener());
            	}
            }
		}

		public void setTitle(String typeName){
			fTypeName = typeName;
			int index = typeName.lastIndexOf('.');
			if (index >= 0){
				fTitle = typeName.substring(index+1) + ".java";
			} else {
				fTitle = typeName + ".java";
			}
		}
		
		public String getTypeName(){
			return fTypeName;
		}
	}
	
	class MyPartListener implements IPartListener2{
		public void partActivated(IWorkbenchPartReference partRef) {}
		public void partDeactivated(IWorkbenchPartReference partRef) {}
		public void partHidden(IWorkbenchPartReference partRef) {}
		public void partOpened(IWorkbenchPartReference partRef) {}
		public void partVisible(IWorkbenchPartReference partRef) {}
		public void partBroughtToTop(IWorkbenchPartReference partRef) {}
		public void partClosed(IWorkbenchPartReference partRef) {}
	
		/* (non-Javadoc)
		 * @see org.eclipse.ui.IPartListener2#partInputChanged(org.eclipse.ui.IWorkbenchPartReference)
		 */
		public void partInputChanged(IWorkbenchPartReference partRef) {
			IEditorPart editor = (IEditorPart) partRef.getPart(true);
        	if (editor instanceof ITextEditor){
    			IDocumentProvider docProvider = ((ITextEditor)editor).getDocumentProvider();
    			IEditorInput editorInput = editor.getEditorInput();
    	        // If there is no annotation model, there's nothing more to do
    	        IAnnotationModel annModel = docProvider.getAnnotationModel(editorInput);
    	        if (annModel == null) {
    	            fail("Could not get the annotation model");
    	        }  
    	        annModel.addAnnotationModelListener(getAnnotationListener());
    	        fAnnotationModelsWithListeners.add(annModel);
    		} else {
    			fail("Editor was not a text editor");
    		}
		}
	}
	
	class MyAnnotationListener implements IAnnotationModelListener, IAnnotationModelListenerExtension{

		public void modelChanged(AnnotationModelEvent event) {
			Annotation[] annotations = event.getAddedAnnotations();
			for (int i = 0; i < annotations.length; i++) {
				if (annotations[i] instanceof InstructionPointerAnnotation){
					synchronized (fLock) {
						fAddedAnnotation = annotations[i];
						fLock.notifyAll();
						System.out.println("Annotation added to editor: " + fAddedAnnotation + " (" + this + ")" + event.getAnnotationModel());
							
					}
				}
			}	
			annotations = event.getRemovedAnnotations();
			for (int i = 0; i < annotations.length; i++) {
				if (annotations[i] instanceof InstructionPointerAnnotation){
					synchronized (fLock) {
						fRemovedAnnotation = annotations[i];
						fLock.notifyAll();
					}
				}
			}	
		}

		public void modelChanged(IAnnotationModel model) {}
	}
}


