added new tests suite + improved stability
diff --git a/.gitignore b/.gitignore
index 3fc56cb..1fcbde8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,6 +17,7 @@
 /tests/org.eclipse.mylyn.docs.intent.collab.test/bin

 /tests/org.eclipse.mylyn.docs.intent.markup.test/bin

 /tests/org.eclipse.mylyn.docs.intent.parser.test/bin

+/tests/org.eclipse.mylyn.docs.intent.client.ui.test/bin

 /examples/org.eclipse.mylyn.docs.intent.retro/bin

 /plugins/org.eclipse.mylyn.docs.intent/target

 /plugins/org.eclipse.mylyn.docs.intent.client.compiler/target

@@ -37,6 +38,7 @@
 /tests/org.eclipse.mylyn.docs.intent.collab.test/target

 /tests/org.eclipse.mylyn.docs.intent.markup.test/target

 /tests/org.eclipse.mylyn.docs.intent.parser.test/target

+/tests/org.eclipse.mylyn.docs.intent.client.ui.test/target

 /examples/org.eclipse.mylyn.docs.intent.retro/target

 features/org.eclipse.mylyn.docs.intent-feature/target/

 features/org.eclipse.mylyn.docs.intent.markup-feature/target/

diff --git a/plugins/org.eclipse.mylyn.docs.intent.client.indexer/src/org/eclipse/mylyn/docs/intent/client/indexer/IndexerRepositoryClient.java b/plugins/org.eclipse.mylyn.docs.intent.client.indexer/src/org/eclipse/mylyn/docs/intent/client/indexer/IndexerRepositoryClient.java
index 43fe0c2..55796b1 100644
--- a/plugins/org.eclipse.mylyn.docs.intent.client.indexer/src/org/eclipse/mylyn/docs/intent/client/indexer/IndexerRepositoryClient.java
+++ b/plugins/org.eclipse.mylyn.docs.intent.client.indexer/src/org/eclipse/mylyn/docs/intent/client/indexer/IndexerRepositoryClient.java
@@ -52,30 +52,33 @@
 	 */
 	public void makeToc() {
 		final RepositoryAdapter repositoryAdapter = repositoryObjectHandler.getRepositoryAdapter();
-		repositoryAdapter.execute(new IntentCommand() {
+		if (repositoryAdapter != null) {
+			repositoryAdapter.execute(new IntentCommand() {
 
-			public void execute() {
-				final IntentIndex index = getIntentIndex();
-				final IntentDocument document = getIntentDocument();
-				System.out.println("[Indexer] Making Toc on " + document.getChapters().size() + "chapters...");
-				
-				repositoryAdapter.openSaveContext();
-				indexComputor.computeIndex(index, document);
-				try {
-					repositoryAdapter.save();
-				} catch (SaveException e) {
+				public void execute() {
+					final IntentIndex index = getIntentIndex();
+					final IntentDocument document = getIntentDocument();
+					System.out.println("[Indexer] Making Toc on " + document.getChapters().size()
+							+ "chapters...");
+
+					repositoryAdapter.openSaveContext();
+					indexComputor.computeIndex(index, document);
 					try {
-						repositoryAdapter.undo();
-					} catch (ReadOnlyException e1) {
-						e1.printStackTrace(); // initially was "CANCEL_STATUS" return
+						repositoryAdapter.save();
+					} catch (SaveException e) {
+						try {
+							repositoryAdapter.undo();
+						} catch (ReadOnlyException e1) {
+							e1.printStackTrace(); // initially was "CANCEL_STATUS" return
+						}
+					} catch (ReadOnlyException e) {
+						e.printStackTrace(); // initially was "CANCEL_STATUS" return
 					}
-				} catch (ReadOnlyException e) {
-					e.printStackTrace(); // initially was "CANCEL_STATUS" return
+					repositoryAdapter.closeContext();
+					System.out.println("[Indexer] Toc made.");
 				}
-				repositoryAdapter.closeContext();
-			}
-		});
-		System.out.println("[Indexer] Toc made.");
+			});
+		}
 	}
 
 	/**
diff --git a/plugins/org.eclipse.mylyn.docs.intent.client.ui.ide/META-INF/MANIFEST.MF b/plugins/org.eclipse.mylyn.docs.intent.client.ui.ide/META-INF/MANIFEST.MF
index 522a23e..41c79f0 100644
--- a/plugins/org.eclipse.mylyn.docs.intent.client.ui.ide/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.mylyn.docs.intent.client.ui.ide/META-INF/MANIFEST.MF
@@ -22,3 +22,5 @@
 Bundle-RequiredExecutionEnvironment: J2SE-1.5
 Import-Package: com.google.common.base,
  com.google.common.collect
+Export-Package: org.eclipse.mylyn.docs.intent.client.ui.ide.builder,
+ org.eclipse.mylyn.docs.intent.client.ui.ide.launcher
diff --git a/plugins/org.eclipse.mylyn.docs.intent.client.ui.ide/src/org/eclipse/mylyn/docs/intent/client/ui/ide/builder/IntentProjectListener.java b/plugins/org.eclipse.mylyn.docs.intent.client.ui.ide/src/org/eclipse/mylyn/docs/intent/client/ui/ide/builder/IntentProjectListener.java
index a325667..a10314c 100644
--- a/plugins/org.eclipse.mylyn.docs.intent.client.ui.ide/src/org/eclipse/mylyn/docs/intent/client/ui/ide/builder/IntentProjectListener.java
+++ b/plugins/org.eclipse.mylyn.docs.intent.client.ui.ide/src/org/eclipse/mylyn/docs/intent/client/ui/ide/builder/IntentProjectListener.java
@@ -74,7 +74,9 @@
 				|| event.getType() == IResourceChangeEvent.PRE_DELETE) {
 			IResource resource = event.getResource();
 			try {
-				if (resource instanceof IProject && ((IProject)resource).hasNature(IntentNature.NATURE_ID)) {
+				// TODO check if there is a repository associated to this project, even if not accessible
+				if (resource instanceof IProject && resource.isAccessible()
+						&& ((IProject)resource).hasNature(IntentNature.NATURE_ID)) {
 					handleClosedProject((IProject)resource);
 				}
 			} catch (CoreException e) {
@@ -136,7 +138,7 @@
 	public void handleOpenedProject(IProject project) {
 		IntentProjectManager projectManager = IntentProjectManager.getInstance(project, true);
 		try {
-			projectManager.createAndLaunchClients();
+			projectManager.connect();
 		} catch (RepositoryConnectionException e) {
 			IntentUiLogger.logError(e);
 		}
diff --git a/plugins/org.eclipse.mylyn.docs.intent.client.ui.ide/src/org/eclipse/mylyn/docs/intent/client/ui/ide/launcher/IDEApplicationManager.java b/plugins/org.eclipse.mylyn.docs.intent.client.ui.ide/src/org/eclipse/mylyn/docs/intent/client/ui/ide/launcher/IDEApplicationManager.java
index 8c7184b..69277d2 100644
--- a/plugins/org.eclipse.mylyn.docs.intent.client.ui.ide/src/org/eclipse/mylyn/docs/intent/client/ui/ide/launcher/IDEApplicationManager.java
+++ b/plugins/org.eclipse.mylyn.docs.intent.client.ui.ide/src/org/eclipse/mylyn/docs/intent/client/ui/ide/launcher/IDEApplicationManager.java
@@ -58,7 +58,7 @@
 	public static void initializeContent(IProject project, String initialContent) {
 		try {
 			if (project.isAccessible()) {
-				IntentProjectManager.getInstance(project, true).connect();
+				IntentProjectManager.getRepository(project).getOrCreateSession();
 				if (project.exists()) {
 					if (!project.isOpen()) {
 						project.open(null);
diff --git a/plugins/org.eclipse.mylyn.docs.intent.client.ui.ide/src/org/eclipse/mylyn/docs/intent/client/ui/ide/launcher/IntentProjectManager.java b/plugins/org.eclipse.mylyn.docs.intent.client.ui.ide/src/org/eclipse/mylyn/docs/intent/client/ui/ide/launcher/IntentProjectManager.java
index 7031c47..d99291c 100644
--- a/plugins/org.eclipse.mylyn.docs.intent.client.ui.ide/src/org/eclipse/mylyn/docs/intent/client/ui/ide/launcher/IntentProjectManager.java
+++ b/plugins/org.eclipse.mylyn.docs.intent.client.ui.ide/src/org/eclipse/mylyn/docs/intent/client/ui/ide/launcher/IntentProjectManager.java
@@ -29,7 +29,6 @@
 import org.eclipse.mylyn.docs.intent.client.ui.ide.generatedelementlistener.IDEGeneratedElementListener;
 import org.eclipse.mylyn.docs.intent.client.ui.ide.navigator.ProjectExplorerRefresher;
 import org.eclipse.mylyn.docs.intent.client.ui.ide.structurer.IntentWorkspaceRepositoryStructurer;
-import org.eclipse.mylyn.docs.intent.client.ui.logger.IntentUiLogger;
 import org.eclipse.mylyn.docs.intent.collab.common.location.IntentLocations;
 import org.eclipse.mylyn.docs.intent.collab.handlers.notification.RepositoryChangeNotificationFactoryHolder;
 import org.eclipse.mylyn.docs.intent.collab.ide.notification.WorkspaceRepositoryChangeNotificationFactory;
@@ -46,6 +45,7 @@
 import org.eclipse.ui.IEditorPart;
 import org.eclipse.ui.IEditorReference;
 import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
 import org.eclipse.ui.PlatformUI;
 
 /**
@@ -103,10 +103,10 @@
 	 * @throws RepositoryConnectionException
 	 *             if the {@link Repository} cannot be created or accessed
 	 */
-	public void createAndLaunchClients() throws RepositoryConnectionException {
+	public synchronized void connect() throws RepositoryConnectionException {
 		try {
 			if (project.isAccessible() && project.getNature(IntentNature.NATURE_ID) != null) {
-				connect();
+				getRepository().getOrCreateSession();
 
 				// Clients creation (if needed)
 
@@ -140,8 +140,8 @@
 				compilerClient.handleChangeNotification(null);
 
 			} else {
-				IntentUiLogger.logError(new RepositoryConnectionException(
-						"Cannot create Repository on project " + project.getName()));
+				throw new RepositoryConnectionException("Cannot create Repository on project "
+						+ project.getName());
 			}
 		} catch (CoreException e) {
 			throw new RepositoryConnectionException(e.getMessage());
@@ -149,34 +149,28 @@
 	}
 
 	/**
-	 * Connects to the {@link Repository}.
-	 * 
-	 * @throws RepositoryConnectionException
-	 *             if the {@link Repository} cannot be created or accessed
-	 */
-	public void connect() throws RepositoryConnectionException {
-		getRepository().getOrCreateSession();
-	}
-
-	/**
 	 * Disconnects the given project by closing the session and the repository.
 	 * 
 	 * @throws RepositoryConnectionException
 	 *             if the {@link Repository} cannot be deleted or accessed
 	 */
-	public void disconnect() throws RepositoryConnectionException {
+	public synchronized void disconnect() throws RepositoryConnectionException {
 		PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
 			public void run() {
-				IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
-				IEditorReference[] references = page.getEditorReferences();
-				for (IEditorReference reference : references) {
-					IEditorPart part = reference.getEditor(false);
-					if (part instanceof IntentEditor) {
-						IntentEditor editor = (IntentEditor)part;
-						IntentDocumentProvider provider = (IntentDocumentProvider)editor
-								.getDocumentProvider();
-						if (repository.equals(provider.getRepository())) {
-							editor.close(editor.isSaveOnCloseNeeded()); // this will dispose clients
+				final IWorkbenchWindow activeWorkbenchWindow = PlatformUI.getWorkbench()
+						.getActiveWorkbenchWindow();
+				if (activeWorkbenchWindow != null) {
+					IWorkbenchPage page = activeWorkbenchWindow.getActivePage();
+					IEditorReference[] references = page.getEditorReferences();
+					for (IEditorReference reference : references) {
+						IEditorPart part = reference.getEditor(false);
+						if (part instanceof IntentEditor) {
+							IntentEditor editor = (IntentEditor)part;
+							IntentDocumentProvider provider = (IntentDocumentProvider)editor
+									.getDocumentProvider();
+							if (repository.equals(provider.getRepository())) {
+								editor.close(editor.isSaveOnCloseNeeded()); // this will dispose clients
+							}
 						}
 					}
 				}
@@ -184,9 +178,7 @@
 			}
 		});
 
-		if (repository != null) {
-			repository.closeSession();
-		}
+		repository.closeSession();
 
 		compilerClient.dispose();
 		synchronizerClient.dispose();
diff --git a/plugins/org.eclipse.mylyn.docs.intent.client.ui.ide/src/org/eclipse/mylyn/docs/intent/client/ui/ide/navigator/ProjectExplorerRefreshJob.java b/plugins/org.eclipse.mylyn.docs.intent.client.ui.ide/src/org/eclipse/mylyn/docs/intent/client/ui/ide/navigator/ProjectExplorerRefreshJob.java
index 222b467..040864f 100644
--- a/plugins/org.eclipse.mylyn.docs.intent.client.ui.ide/src/org/eclipse/mylyn/docs/intent/client/ui/ide/navigator/ProjectExplorerRefreshJob.java
+++ b/plugins/org.eclipse.mylyn.docs.intent.client.ui.ide/src/org/eclipse/mylyn/docs/intent/client/ui/ide/navigator/ProjectExplorerRefreshJob.java
@@ -107,15 +107,17 @@
 	 */
 	private void refreshProjectExplorer(final ProjectExplorer projectExplorer) {
 		CommonViewer commonViewer = projectExplorer.getCommonViewer();
-		if (elementToRefresh != null) {
-			// We try to refresh the element container (if not null)
-			if (elementToRefresh.eContainer() != null) {
-				commonViewer.refresh(elementToRefresh.eContainer(), true);
+		if (!commonViewer.getControl().isDisposed()) {
+			if (elementToRefresh != null) {
+				// We try to refresh the element container (if not null)
+				if (elementToRefresh.eContainer() != null) {
+					commonViewer.refresh(elementToRefresh.eContainer(), true);
+				} else {
+					commonViewer.refresh(elementToRefresh, true);
+				}
 			} else {
-				commonViewer.refresh(elementToRefresh, true);
+				commonViewer.refresh(project, true);
 			}
-		} else {
-			commonViewer.refresh(project, true);
 		}
 	}
 }
diff --git a/plugins/org.eclipse.mylyn.docs.intent.client.ui.ide/src/org/eclipse/mylyn/docs/intent/client/ui/ide/navigator/RepositoryContentProvider.java b/plugins/org.eclipse.mylyn.docs.intent.client.ui.ide/src/org/eclipse/mylyn/docs/intent/client/ui/ide/navigator/RepositoryContentProvider.java
index e6e3ae1..6258ec7 100644
--- a/plugins/org.eclipse.mylyn.docs.intent.client.ui.ide/src/org/eclipse/mylyn/docs/intent/client/ui/ide/navigator/RepositoryContentProvider.java
+++ b/plugins/org.eclipse.mylyn.docs.intent.client.ui.ide/src/org/eclipse/mylyn/docs/intent/client/ui/ide/navigator/RepositoryContentProvider.java
@@ -55,7 +55,7 @@
 			IFile file = (IFile)parentElement;
 			// We connect to the repository
 			try {
-				IntentProjectManager.getInstance(file.getProject(), true).connect();
+				IntentProjectManager.getRepository(file.getProject()).getOrCreateSession();
 				RepositoryAdapter repositoryAdapter = RepositoryCreatorHolder.getCreator()
 						.createRepositoryAdapterForRepository(
 								IntentProjectManager.getRepository(file.getProject()));
diff --git a/plugins/org.eclipse.mylyn.docs.intent.client.ui/src/org/eclipse/mylyn/docs/intent/client/ui/editor/IntentEditorDocument.java b/plugins/org.eclipse.mylyn.docs.intent.client.ui/src/org/eclipse/mylyn/docs/intent/client/ui/editor/IntentEditorDocument.java
index ad6f5e2..803f59a 100644
--- a/plugins/org.eclipse.mylyn.docs.intent.client.ui/src/org/eclipse/mylyn/docs/intent/client/ui/editor/IntentEditorDocument.java
+++ b/plugins/org.eclipse.mylyn.docs.intent.client.ui/src/org/eclipse/mylyn/docs/intent/client/ui/editor/IntentEditorDocument.java
@@ -130,17 +130,19 @@
 		Display.getDefault().syncExec(new Runnable() {
 
 			public void run() {
-				ISelection selection = associatedEditor.getSelectionProvider().getSelection();
-				try {
-					String serializedForm = serializer.serialize(newAST);
-					if (!get().equals(serializedForm)) {
-						replace(0, getLength(), serializedForm);
+				if (associatedEditor.getSelectionProvider() != null) {
+					ISelection selection = associatedEditor.getSelectionProvider().getSelection();
+					try {
+						String serializedForm = serializer.serialize(newAST);
+						if (!get().equals(serializedForm)) {
+							replace(0, getLength(), serializedForm);
+						}
+						setAST(newAST);
+					} catch (BadLocationException e) {
+						IntentUiLogger.logError("Error encountered while refreshing the document ", e);
 					}
-					setAST(newAST);
-				} catch (BadLocationException e) {
-					IntentUiLogger.logError("Error encountered while refreshing the document ", e);
+					associatedEditor.getSelectionProvider().setSelection(selection);
 				}
-				associatedEditor.getSelectionProvider().setSelection(selection);
 			}
 		});
 
diff --git a/plugins/org.eclipse.mylyn.docs.intent.client.ui/src/org/eclipse/mylyn/docs/intent/client/ui/utils/IntentEditorOpener.java b/plugins/org.eclipse.mylyn.docs.intent.client.ui/src/org/eclipse/mylyn/docs/intent/client/ui/utils/IntentEditorOpener.java
index 96cc9b9..d44708c 100644
--- a/plugins/org.eclipse.mylyn.docs.intent.client.ui/src/org/eclipse/mylyn/docs/intent/client/ui/utils/IntentEditorOpener.java
+++ b/plugins/org.eclipse.mylyn.docs.intent.client.ui/src/org/eclipse/mylyn/docs/intent/client/ui/utils/IntentEditorOpener.java
@@ -78,21 +78,11 @@
 		try {
 			final RepositoryAdapter repositoryAdapter = RepositoryCreatorHolder.getCreator()
 					.createRepositoryAdapterForRepository(repository);
-
-			// We need to launch through a command because the editor register adapters on the model, which
-			// makes the resource appear as modified and being updated by the repository save.
-			repositoryAdapter.execute(new IntentCommand() {
-				public void execute() {
-					try {
-						openIntentEditor(repositoryAdapter, repository, elementToOpen, false, elementToOpen,
-								false);
-					} catch (PartInitException e) {
-						IntentUiLogger.logError(e);
-					}
-				}
-			});
+			openIntentEditor(repositoryAdapter, repository, elementToOpen, false, elementToOpen, false);
 		} catch (RepositoryConnectionException rce) {
 			IntentUiLogger.logError(rce);
+		} catch (PartInitException e) {
+			IntentUiLogger.logError(e);
 		}
 	}
 
@@ -142,22 +132,23 @@
 		if (openedEditor == null) {
 
 			// Step 3 : creation of the Handler in the correct mode
-			RepositoryObjectHandler elementHandler = null;
-
-			if (readOnlyMode) {
-				elementHandler = new ReadOnlyRepositoryObjectHandlerImpl();
-				elementHandler.setRepositoryAdapter(repositoryAdapter);
-			} else {
-				elementHandler = new ReadWriteRepositoryObjectHandlerImpl(repositoryAdapter);
-			}
+			final RepositoryObjectHandler elementHandler = createElementHandler(repositoryAdapter,
+					readOnlyMode);
 
 			// Step 4 : creation of a Notificator listening changes on this element and compilation
 			// errors.
-			Set<EObject> listenedObjects = new LinkedHashSet<EObject>();
+			final Set<EObject> listenedObjects = new LinkedHashSet<EObject>();
 			listenedObjects.add(elementToOpen);
-			ElementListAdapter adapter = new EditorElementListAdapter();
-			Notificator listenedElementsNotificator = new ElementListNotificator(listenedObjects, adapter);
-			elementHandler.setNotificator(listenedElementsNotificator);
+			final ElementListAdapter adapter = new EditorElementListAdapter();
+
+			repositoryAdapter.execute(new IntentCommand() {
+
+				public void execute() {
+					Notificator listenedElementsNotificator = new ElementListNotificator(listenedObjects,
+							adapter);
+					elementHandler.setNotificator(listenedElementsNotificator);
+				}
+			});
 
 			// Step 5 : we open a new editor.
 			IWorkbenchPage page = null;
@@ -176,6 +167,27 @@
 	}
 
 	/**
+	 * Creates the element handler matching the given mode.
+	 * 
+	 * @param repositoryAdapter
+	 *            the repository adapter
+	 * @param readOnlyMode
+	 *            the access mode
+	 * @return the handler
+	 */
+	private static RepositoryObjectHandler createElementHandler(RepositoryAdapter repositoryAdapter,
+			boolean readOnlyMode) {
+		final RepositoryObjectHandler elementHandler;
+		if (readOnlyMode) {
+			elementHandler = new ReadOnlyRepositoryObjectHandlerImpl();
+			elementHandler.setRepositoryAdapter(repositoryAdapter);
+		} else {
+			elementHandler = new ReadWriteRepositoryObjectHandlerImpl(repositoryAdapter);
+		}
+		return elementHandler;
+	}
+
+	/**
 	 * If an editor is already opened on the given element, returns it ; return null otherwise.
 	 * 
 	 * @param elementToOpen
diff --git a/plugins/org.eclipse.mylyn.docs.intent.collab.ide/META-INF/MANIFEST.MF b/plugins/org.eclipse.mylyn.docs.intent.collab.ide/META-INF/MANIFEST.MF
index cd79a5f..50a1d72 100644
--- a/plugins/org.eclipse.mylyn.docs.intent.collab.ide/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.mylyn.docs.intent.collab.ide/META-INF/MANIFEST.MF
@@ -7,7 +7,7 @@
 Require-Bundle: org.eclipse.core.runtime,
  org.eclipse.mylyn.docs.intent.collab;visibility:=reexport,
  org.eclipse.core.resources;visibility:=reexport,
- org.eclipse.emf.transaction;bundle-version="1.4.0"
+ org.eclipse.emf.transaction;bundle-version="1.4.0";visibility:=reexport
 Bundle-ActivationPolicy: lazy
 Bundle-RequiredExecutionEnvironment: J2SE-1.5
 Export-Package: org.eclipse.mylyn.docs.intent.collab.ide.repository,
diff --git a/plugins/org.eclipse.mylyn.docs.intent.collab.ide/src/org/eclipse/mylyn/docs/intent/collab/ide/adapters/WorkspaceAdapter.java b/plugins/org.eclipse.mylyn.docs.intent.collab.ide/src/org/eclipse/mylyn/docs/intent/collab/ide/adapters/WorkspaceAdapter.java
index 394f1c6..81ba7b5 100644
--- a/plugins/org.eclipse.mylyn.docs.intent.collab.ide/src/org/eclipse/mylyn/docs/intent/collab/ide/adapters/WorkspaceAdapter.java
+++ b/plugins/org.eclipse.mylyn.docs.intent.collab.ide/src/org/eclipse/mylyn/docs/intent/collab/ide/adapters/WorkspaceAdapter.java
@@ -543,15 +543,15 @@
 		final TransactionalEditingDomain editingDomain = repository.getEditingDomain();
 
 		// first we check that the repository has not been disposed
-		// TODO replace by a proper closing strategy
-		if (editingDomain.getCommandStack() != null) {
+		final CommandStack commandStack = editingDomain.getCommandStack();
+		if (commandStack != null) {
 			RecordingCommand recordingCommand = new RecordingCommand(editingDomain) {
 				@Override
 				protected void doExecute() {
 					command.execute();
 				}
 			};
-			editingDomain.getCommandStack().execute(recordingCommand);
+			commandStack.execute(recordingCommand);
 		}
 	}
 
diff --git a/plugins/org.eclipse.mylyn.docs.intent.collab.ide/src/org/eclipse/mylyn/docs/intent/collab/ide/repository/WorkspaceRepository.java b/plugins/org.eclipse.mylyn.docs.intent.collab.ide/src/org/eclipse/mylyn/docs/intent/collab/ide/repository/WorkspaceRepository.java
index 3746455..984235b 100644
--- a/plugins/org.eclipse.mylyn.docs.intent.collab.ide/src/org/eclipse/mylyn/docs/intent/collab/ide/repository/WorkspaceRepository.java
+++ b/plugins/org.eclipse.mylyn.docs.intent.collab.ide/src/org/eclipse/mylyn/docs/intent/collab/ide/repository/WorkspaceRepository.java
@@ -159,10 +159,9 @@
 	 */
 	public void closeSession() throws RepositoryConnectionException {
 		if (this.session != null) {
+			ResourcesPlugin.getWorkspace().removeResourceChangeListener(session);
 			this.session.close();
-			IWorkspace workspace = ResourcesPlugin.getWorkspace();
-			workspace.removeResourceChangeListener(session);
-			session = null;
+			this.session = null;
 		}
 		this.editingDomain.dispose();
 	}
diff --git a/plugins/org.eclipse.mylyn.docs.intent/dev/launchconfigs/tests/UI-TestSuite.launch b/plugins/org.eclipse.mylyn.docs.intent/dev/launchconfigs/tests/UI-TestSuite.launch
new file mode 100644
index 0000000..cab9923
--- /dev/null
+++ b/plugins/org.eclipse.mylyn.docs.intent/dev/launchconfigs/tests/UI-TestSuite.launch
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>

+<launchConfiguration type="org.eclipse.pde.ui.JunitLaunchConfig">

+<booleanAttribute key="append.args" value="true"/>

+<booleanAttribute key="askclear" value="false"/>

+<booleanAttribute key="automaticAdd" value="true"/>

+<booleanAttribute key="automaticValidate" value="false"/>

+<stringAttribute key="bootstrap" value=""/>

+<stringAttribute key="checked" value="[NONE]"/>

+<booleanAttribute key="clearConfig" value="true"/>

+<booleanAttribute key="clearws" value="true"/>

+<booleanAttribute key="clearwslog" value="false"/>

+<stringAttribute key="configLocation" value="${workspace_loc}/.metadata/.plugins/org.eclipse.pde.core/pde-junit"/>

+<booleanAttribute key="default" value="true"/>

+<booleanAttribute key="includeOptional" value="true"/>

+<stringAttribute key="location" value="${workspace_loc}/../junit-workspace"/>

+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">

+<listEntry value="/org.eclipse.mylyn.docs.intent.client.ui.test/src/org/eclipse/mylyn/docs/intent/client/ui/test/suite/UITestSuite.java"/>

+</listAttribute>

+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">

+<listEntry value="1"/>

+</listAttribute>

+<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value=""/>

+<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>

+<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>

+<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>

+<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.eclipse.mylyn.docs.intent.client.ui.test.suite.UITestSuite"/>

+<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -consoleLog"/>

+<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.mylyn.docs.intent.client.ui.test"/>

+<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/>

+<stringAttribute key="pde.version" value="3.3"/>

+<stringAttribute key="product" value="org.eclipse.platform.ide"/>

+<booleanAttribute key="run_in_ui_thread" value="true"/>

+<booleanAttribute key="show_selected_only" value="false"/>

+<booleanAttribute key="tracing" value="false"/>

+<booleanAttribute key="useCustomFeatures" value="false"/>

+<booleanAttribute key="useDefaultConfig" value="true"/>

+<booleanAttribute key="useDefaultConfigArea" value="false"/>

+<booleanAttribute key="useProduct" value="true"/>

+</launchConfiguration>

diff --git a/pom.xml b/pom.xml
index e760f89..e05c519 100644
--- a/pom.xml
+++ b/pom.xml
@@ -65,6 +65,7 @@
 
     <module>tests/org.eclipse.mylyn.docs.intent.parser.test</module>
     <module>tests/org.eclipse.mylyn.docs.intent.collab.test</module>
+    <module>tests/org.eclipse.mylyn.docs.intent.client.ui.test</module>
    </modules>
 <!--
   <repositories>
diff --git a/tests/org.eclipse.mylyn.docs.intent.client.ui.test/.checkstyle b/tests/org.eclipse.mylyn.docs.intent.client.ui.test/.checkstyle
new file mode 100644
index 0000000..c8682c8
--- /dev/null
+++ b/tests/org.eclipse.mylyn.docs.intent.client.ui.test/.checkstyle
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<fileset-config file-format-version="1.2.0" simple-config="true">
+    <local-check-config name="Intent" location="/org.eclipse.mylyn.docs.intent/dev/code/checkstyleConfiguration.xml" type="project" description="">
+        <additional-data name="protect-config-file" value="false"/>
+    </local-check-config>
+    <fileset name="tous" enabled="true" check-config-name="Intent" local="true">
+        <file-match-pattern match-pattern="." include-pattern="true"/>
+    </fileset>
+</fileset-config>
diff --git a/tests/org.eclipse.mylyn.docs.intent.client.ui.test/.classpath b/tests/org.eclipse.mylyn.docs.intent.client.ui.test/.classpath
new file mode 100644
index 0000000..64c5e31
--- /dev/null
+++ b/tests/org.eclipse.mylyn.docs.intent.client.ui.test/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/tests/org.eclipse.mylyn.docs.intent.client.ui.test/.project b/tests/org.eclipse.mylyn.docs.intent.client.ui.test/.project
new file mode 100644
index 0000000..8610d97
--- /dev/null
+++ b/tests/org.eclipse.mylyn.docs.intent.client.ui.test/.project
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<projectDescription>

+	<name>org.eclipse.mylyn.docs.intent.client.ui.test</name>

+	<comment></comment>

+	<projects>

+	</projects>

+	<buildSpec>

+		<buildCommand>

+			<name>org.eclipse.jdt.core.javabuilder</name>

+			<arguments>

+			</arguments>

+		</buildCommand>

+		<buildCommand>

+			<name>org.eclipse.pde.ManifestBuilder</name>

+			<arguments>

+			</arguments>

+		</buildCommand>

+		<buildCommand>

+			<name>org.eclipse.pde.SchemaBuilder</name>

+			<arguments>

+			</arguments>

+		</buildCommand>

+		<buildCommand>

+			<name>com.atlassw.tools.eclipse.checkstyle.CheckstyleBuilder</name>

+			<arguments>

+			</arguments>

+		</buildCommand>

+	</buildSpec>

+	<natures>

+		<nature>org.eclipse.pde.PluginNature</nature>

+		<nature>org.eclipse.jdt.core.javanature</nature>

+		<nature>com.atlassw.tools.eclipse.checkstyle.CheckstyleNature</nature>

+	</natures>

+</projectDescription>

diff --git a/tests/org.eclipse.mylyn.docs.intent.client.ui.test/.settings/org.eclipse.jdt.core.prefs b/tests/org.eclipse.mylyn.docs.intent.client.ui.test/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..ca38006
--- /dev/null
+++ b/tests/org.eclipse.mylyn.docs.intent.client.ui.test/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,8 @@
+#Wed Jul 28 17:23:25 CEST 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/tests/org.eclipse.mylyn.docs.intent.client.ui.test/META-INF/MANIFEST.MF b/tests/org.eclipse.mylyn.docs.intent.client.ui.test/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..a689e75
--- /dev/null
+++ b/tests/org.eclipse.mylyn.docs.intent.client.ui.test/META-INF/MANIFEST.MF
@@ -0,0 +1,21 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-SymbolicName: org.eclipse.mylyn.docs.intent.client.ui.test
+Bundle-Version: 0.7.0.qualifier
+Bundle-ClassPath: .
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
+Require-Bundle: org.junit;bundle-version="4.8.1",
+ org.eclipse.mylyn.docs.intent.client.ui.ide;bundle-version="0.7.0",
+ org.eclipse.ui;bundle-version="3.7.0",
+ org.eclipse.core.runtime;bundle-version="3.7.0",
+ org.eclipse.core.resources;bundle-version="3.7.100",
+ org.eclipse.mylyn.docs.intent.parser.test;bundle-version="0.7.0",
+ org.eclipse.mylyn.docs.intent.client.ui;bundle-version="0.7.0",
+ org.eclipse.mylyn.docs.intent.collab;bundle-version="0.7.0",
+ org.eclipse.mylyn.docs.intent.collab.common;bundle-version="0.7.0",
+ org.eclipse.mylyn.docs.intent.core;bundle-version="0.7.0",
+ org.eclipse.jface.text;bundle-version="3.7.0",
+ org.eclipse.mylyn.docs.intent.collab.ide;bundle-version="0.7.0"
diff --git a/tests/org.eclipse.mylyn.docs.intent.client.ui.test/about.html b/tests/org.eclipse.mylyn.docs.intent.client.ui.test/about.html
new file mode 100644
index 0000000..34ab520
--- /dev/null
+++ b/tests/org.eclipse.mylyn.docs.intent.client.ui.test/about.html
@@ -0,0 +1,106 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 

+<html xmlns="http://www.w3.org/1999/xhtml"> 

+<head> 

+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" /> 

+<title>Eclipse Foundation Software User Agreement</title> 

+</head> 

+ 

+<body lang="EN-US"> 

+<h2>Eclipse Foundation Software User Agreement</h2> 

+<p>April 14, 2010</p> 

+ 

+<h3>Usage Of Content</h3> 

+ 

+<p>THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR OTHER MATERIALS FOR OPEN SOURCE PROJECTS

+   (COLLECTIVELY &quot;CONTENT&quot;).  USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE TERMS AND

+   CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW.  BY USING THE CONTENT, YOU AGREE THAT YOUR USE

+   OF THE CONTENT IS GOVERNED BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR

+   NOTICES INDICATED OR REFERENCED BELOW.  IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND

+   CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW, THEN YOU MAY NOT USE THE CONTENT.</p> 

+ 

+<h3>Applicable Licenses</h3> 

+ 

+<p>Unless otherwise indicated, all Content made available by the Eclipse Foundation is provided to you under the terms and conditions of the Eclipse Public License Version 1.0

+   (&quot;EPL&quot;).  A copy of the EPL is provided with this Content and is also available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.

+   For purposes of the EPL, &quot;Program&quot; will mean the Content.</p> 

+ 

+<p>Content includes, but is not limited to, source code, object code, documentation and other files maintained in the Eclipse Foundation source code

+   repository (&quot;Repository&quot;) in software modules (&quot;Modules&quot;) and made available as downloadable archives (&quot;Downloads&quot;).</p> 

+ 

+<ul> 

+       <li>Content may be structured and packaged into modules to facilitate delivering, extending, and upgrading the Content.  Typical modules may include plug-ins (&quot;Plug-ins&quot;), plug-in fragments (&quot;Fragments&quot;), and features (&quot;Features&quot;).</li> 

+       <li>Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java&trade; ARchive) in a directory named &quot;plugins&quot;.</li> 

+       <li>A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material.  Each Feature may be packaged as a sub-directory in a directory named &quot;features&quot;.  Within a Feature, files named &quot;feature.xml&quot; may contain a list of the names and version numbers of the Plug-ins

+      and/or Fragments associated with that Feature.</li> 

+       <li>Features may also include other Features (&quot;Included Features&quot;). Within a Feature, files named &quot;feature.xml&quot; may contain a list of the names and version numbers of Included Features.</li> 

+</ul> 

+ 

+<p>The terms and conditions governing Plug-ins and Fragments should be contained in files named &quot;about.html&quot; (&quot;Abouts&quot;). The terms and conditions governing Features and

+Included Features should be contained in files named &quot;license.html&quot; (&quot;Feature Licenses&quot;).  Abouts and Feature Licenses may be located in any directory of a Download or Module

+including, but not limited to the following locations:</p> 

+ 

+<ul> 

+       <li>The top-level (root) directory</li> 

+       <li>Plug-in and Fragment directories</li> 

+       <li>Inside Plug-ins and Fragments packaged as JARs</li> 

+       <li>Sub-directories of the directory named &quot;src&quot; of certain Plug-ins</li> 

+       <li>Feature directories</li> 

+</ul> 

+ 

+<p>Note: if a Feature made available by the Eclipse Foundation is installed using the Provisioning Technology (as defined below), you must agree to a license (&quot;Feature Update License&quot;) during the

+installation process.  If the Feature contains Included Features, the Feature Update License should either provide you with the terms and conditions governing the Included Features or

+inform you where you can locate them.  Feature Update Licenses may be found in the &quot;license&quot; property of files named &quot;feature.properties&quot; found within a Feature.

+Such Abouts, Feature Licenses, and Feature Update Licenses contain the terms and conditions (or references to such terms and conditions) that govern your use of the associated Content in

+that directory.</p> 

+ 

+<p>THE ABOUTS, FEATURE LICENSES, AND FEATURE UPDATE LICENSES MAY REFER TO THE EPL OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS.  SOME OF THESE

+OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):</p> 

+ 

+<ul> 

+       <li>Common Public License Version 1.0 (available at <a href="http://www.eclipse.org/legal/cpl-v10.html">http://www.eclipse.org/legal/cpl-v10.html</a>)</li> 

+       <li>Apache Software License 1.1 (available at <a href="http://www.apache.org/licenses/LICENSE">http://www.apache.org/licenses/LICENSE</a>)</li> 

+       <li>Apache Software License 2.0 (available at <a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>)</li> 

+       <li>Metro Link Public License 1.00 (available at <a href="http://www.opengroup.org/openmotif/supporters/metrolink/license.html">http://www.opengroup.org/openmotif/supporters/metrolink/license.html</a>)</li> 

+       <li>Mozilla Public License Version 1.1 (available at <a href="http://www.mozilla.org/MPL/MPL-1.1.html">http://www.mozilla.org/MPL/MPL-1.1.html</a>)</li> 

+</ul> 

+ 

+<p>IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR TO USE OF THE CONTENT.  If no About, Feature License, or Feature Update License is provided, please

+contact the Eclipse Foundation to determine what terms and conditions govern that particular Content.</p> 

+ 

+ 

+<h3>Use of Provisioning Technology</h3> 

+ 

+<p>The Eclipse Foundation makes available provisioning software, examples of which include, but are not limited to, p2 and the Eclipse

+   Update Manager (&quot;Provisioning Technology&quot;) for the purpose of allowing users to install software, documentation, information and/or

+   other materials (collectively &quot;Installable Software&quot;). This capability is provided with the intent of allowing such users to

+   install, extend and update Eclipse-based products. Information about packaging Installable Software is available at <a 

+       href="http://eclipse.org/equinox/p2/repository_packaging.html">http://eclipse.org/equinox/p2/repository_packaging.html</a> 

+   (&quot;Specification&quot;).</p> 

+ 

+<p>You may use Provisioning Technology to allow other parties to install Installable Software. You shall be responsible for enabling the

+   applicable license agreements relating to the Installable Software to be presented to, and accepted by, the users of the Provisioning Technology

+   in accordance with the Specification. By using Provisioning Technology in such a manner and making it available in accordance with the

+   Specification, you further acknowledge your agreement to, and the acquisition of all necessary rights to permit the following:</p> 

+ 

+<ol> 

+       <li>A series of actions may occur (&quot;Provisioning Process&quot;) in which a user may execute the Provisioning Technology

+       on a machine (&quot;Target Machine&quot;) with the intent of installing, extending or updating the functionality of an Eclipse-based

+       product.</li> 

+       <li>During the Provisioning Process, the Provisioning Technology may cause third party Installable Software or a portion thereof to be

+       accessed and copied to the Target Machine.</li> 

+       <li>Pursuant to the Specification, you will provide to the user the terms and conditions that govern the use of the Installable

+       Software (&quot;Installable Software Agreement&quot;) and such Installable Software Agreement shall be accessed from the Target

+       Machine in accordance with the Specification. Such Installable Software Agreement must inform the user of the terms and conditions that govern

+       the Installable Software and must solicit acceptance by the end user in the manner prescribed in such Installable Software Agreement. Upon such

+       indication of agreement by the user, the provisioning Technology will complete installation of the Installable Software.</li> 

+</ol> 

+ 

+<h3>Cryptography</h3> 

+ 

+<p>Content may contain encryption software. The country in which you are currently may have restrictions on the import, possession, and use, and/or re-export to

+   another country, of encryption software. BEFORE using any encryption software, please check the country's laws, regulations and policies concerning the import,

+   possession, or use, and re-export of encryption software, to see if this is permitted.</p> 

+ 

+<p><small>Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.</small></p> 

+</body> 

+</html> 
\ No newline at end of file
diff --git a/tests/org.eclipse.mylyn.docs.intent.client.ui.test/build.properties b/tests/org.eclipse.mylyn.docs.intent.client.ui.test/build.properties
new file mode 100644
index 0000000..41eb6ad
--- /dev/null
+++ b/tests/org.eclipse.mylyn.docs.intent.client.ui.test/build.properties
@@ -0,0 +1,4 @@
+source.. = src/

+output.. = bin/

+bin.includes = META-INF/,\

+               .

diff --git a/tests/org.eclipse.mylyn.docs.intent.client.ui.test/data/unit/documents/editorupdates/changeEditorUpdateTest.intent b/tests/org.eclipse.mylyn.docs.intent.client.ui.test/data/unit/documents/editorupdates/changeEditorUpdateTest.intent
new file mode 100644
index 0000000..c6b7c1b
--- /dev/null
+++ b/tests/org.eclipse.mylyn.docs.intent.client.ui.test/data/unit/documents/editorupdates/changeEditorUpdateTest.intent
@@ -0,0 +1,44 @@
+Document {
+	Chapter {
+		
+		Section {
+			Differencing the left model from right model when comparaison fails
+		
+			During the Match process, deleted or added elements are considered as unmatched.
+		
+			Two different situations can occur : 
+		
+			* an element defined in the left model is not matching any element in the right model (deleted element)
+			* an element defined in the right model is not matching any element in the left model (added element)
+			
+		
+			
+			
+			@M SidedataTypeDefinition 
+				match {
+					eClassifiers += new EEnum Side {
+						serializable = "true";
+						eLiterals += new EEnumLiteral {
+							name = "Left";
+							literal = "Left";
+							value = "0";
+						};
+						eLiterals += new EEnumLiteral {
+							name = "Right";
+							literal = "Right";
+							value = "1";
+						};
+					};
+				}
+			M@
+			
+		
+			If the feature @side@ of an UnmatchElement is _Right_, then it must be considered as an added element. 
+			Otherwise, it is a deleted element.
+		
+			The MatchModel store suchs an element using @UnmatchElement@s (
+			@see "TheUnmatchElementConcept" ). To differenciate
+			added element from deleted element, we define the @EEnum@ *Side* :
+		}
+	}
+}
diff --git a/tests/org.eclipse.mylyn.docs.intent.client.ui.test/plugin.properties b/tests/org.eclipse.mylyn.docs.intent.client.ui.test/plugin.properties
new file mode 100644
index 0000000..8eec0c5
--- /dev/null
+++ b/tests/org.eclipse.mylyn.docs.intent.client.ui.test/plugin.properties
@@ -0,0 +1,12 @@
+#################################################################################
+# Copyright (c) 2010, 2011 Obeo.
+# 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
+#################################################################################
+pluginName = Intent UI Test
+providerName = Eclipse Mylyn
\ No newline at end of file
diff --git a/tests/org.eclipse.mylyn.docs.intent.client.ui.test/src/org/eclipse/mylyn/docs/intent/client/ui/test/suite/UITestSuite.java b/tests/org.eclipse.mylyn.docs.intent.client.ui.test/src/org/eclipse/mylyn/docs/intent/client/ui/test/suite/UITestSuite.java
new file mode 100644
index 0000000..f0d080d
--- /dev/null
+++ b/tests/org.eclipse.mylyn.docs.intent.client.ui.test/src/org/eclipse/mylyn/docs/intent/client/ui/test/suite/UITestSuite.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2011 Obeo.
+ * 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.mylyn.docs.intent.client.ui.test.suite;
+
+import junit.framework.TestSuite;
+
+import org.eclipse.mylyn.docs.intent.client.ui.test.unit.compare.ChangeEditorUpdateTest;
+import org.eclipse.mylyn.docs.intent.client.ui.test.unit.project.ProjectTest;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+/**
+ * This suite will launch all the tests relative to the UI behavior.
+ * 
+ * @author <a href="mailto:alex.lagarde@obeo.fr">Alex Lagarde</a>
+ * @author <a href="mailto:william.piers@obeo.fr">William Piers</a>
+ */
+@RunWith(Suite.class)
+@Suite.SuiteClasses({ProjectTest.class, ChangeEditorUpdateTest.class
+})
+public class UITestSuite extends TestSuite {
+
+}
diff --git a/tests/org.eclipse.mylyn.docs.intent.client.ui.test/src/org/eclipse/mylyn/docs/intent/client/ui/test/unit/compare/ChangeEditorUpdateTest.java b/tests/org.eclipse.mylyn.docs.intent.client.ui.test/src/org/eclipse/mylyn/docs/intent/client/ui/test/unit/compare/ChangeEditorUpdateTest.java
new file mode 100644
index 0000000..6637386
--- /dev/null
+++ b/tests/org.eclipse.mylyn.docs.intent.client.ui.test/src/org/eclipse/mylyn/docs/intent/client/ui/test/unit/compare/ChangeEditorUpdateTest.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2011 Obeo.
+ * 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.mylyn.docs.intent.client.ui.test.unit.compare;
+
+import org.eclipse.mylyn.docs.intent.client.ui.editor.IntentEditor;
+import org.eclipse.mylyn.docs.intent.client.ui.editor.IntentEditorDocument;
+import org.eclipse.mylyn.docs.intent.client.ui.test.util.AbstractUITest;
+import org.eclipse.mylyn.docs.intent.core.document.IntentSection;
+
+/**
+ * Tests the correct behavior of Intent editor changes.
+ * 
+ * @author <a href="mailto:alex.lagarde@obeo.fr">Alex Lagarde</a>
+ * @author <a href="mailto:william.piers@obeo.fr">William Piers</a>
+ */
+public class ChangeEditorUpdateTest extends AbstractUITest {
+
+	private IntentSection section;
+
+	private IntentEditor editor;
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see junit.framework.TestCase#setUp()
+	 */
+	@Override
+	protected void setUp() throws Exception {
+		super.setUp();
+		setUpIntentProject("intentProject", "data/unit/documents/editorupdates/changeEditorUpdateTest.intent");
+		section = getIntentDocument().getChapters().iterator().next().getSubSections().iterator().next();
+		editor = openIntentEditor(section);
+	}
+
+	/**
+	 * Ensures that changes are correctly managed by the editor.
+	 */
+	public void testChanges() {
+		IntentEditorDocument document = (IntentEditorDocument)editor.getDocumentProvider().getDocument(
+				editor.getEditorInput());
+
+		String string = document.get();
+		document.set(string + "test");
+
+		// Iterator annotationIterator = ((IntentDocumentProvider)editor.getDocumentProvider())
+		// .getAnnotationModel(null).getAnnotationIterator();
+		// while (annotationIterator.hasNext()) {
+		// System.err.println(annotationIterator.next());
+		// }
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see junit.framework.TestCase#tearDown()
+	 */
+	@Override
+	protected void tearDown() throws Exception {
+		if (editor != null) {
+			editor.close(false);
+		}
+		super.tearDown();
+	}
+}
diff --git a/tests/org.eclipse.mylyn.docs.intent.client.ui.test/src/org/eclipse/mylyn/docs/intent/client/ui/test/unit/project/ProjectTest.java b/tests/org.eclipse.mylyn.docs.intent.client.ui.test/src/org/eclipse/mylyn/docs/intent/client/ui/test/unit/project/ProjectTest.java
new file mode 100644
index 0000000..79cf24b
--- /dev/null
+++ b/tests/org.eclipse.mylyn.docs.intent.client.ui.test/src/org/eclipse/mylyn/docs/intent/client/ui/test/unit/project/ProjectTest.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2011 Obeo.
+ * 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.mylyn.docs.intent.client.ui.test.unit.project;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.mylyn.docs.intent.client.ui.ide.builder.ToggleNatureAction;
+import org.eclipse.mylyn.docs.intent.client.ui.test.util.AbstractUITest;
+
+/**
+ * Tests the correct behavior of Intent projects.
+ * 
+ * @author <a href="mailto:william.piers@obeo.fr">William Piers</a>
+ */
+public class ProjectTest extends AbstractUITest {
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see junit.framework.TestCase#setUp()
+	 */
+	@Override
+	protected void setUp() throws Exception {
+		super.setUp();
+		setUpIntentProject("intentProject", "data/unit/documents/editorupdates/changeEditorUpdateTest.intent");
+		openIntentEditor();
+	}
+
+	/**
+	 * Ensures that a project can be closed.
+	 */
+	public void testCloseProject() {
+		try {
+			intentProject.close(new NullProgressMonitor());
+		} catch (CoreException e) {
+			fail(e.getMessage());
+		}
+	}
+
+	/**
+	 * Ensures that the project nature can be activated/deactivated.
+	 */
+	public void testToggleNature() {
+		ToggleNatureAction.toggleNature(intentProject);
+		ToggleNatureAction.toggleNature(intentProject);
+		openIntentEditor();
+	}
+
+}
diff --git a/tests/org.eclipse.mylyn.docs.intent.client.ui.test/src/org/eclipse/mylyn/docs/intent/client/ui/test/util/AbstractUITest.java b/tests/org.eclipse.mylyn.docs.intent.client.ui.test/src/org/eclipse/mylyn/docs/intent/client/ui/test/util/AbstractUITest.java
new file mode 100644
index 0000000..c9daf00
--- /dev/null
+++ b/tests/org.eclipse.mylyn.docs.intent.client.ui.test/src/org/eclipse/mylyn/docs/intent/client/ui/test/util/AbstractUITest.java
@@ -0,0 +1,262 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2011 Obeo.
+ * 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.mylyn.docs.intent.client.ui.test.util;
+
+import java.io.File;
+import java.io.IOException;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.jface.wizard.IWizard;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.mylyn.docs.intent.client.ui.editor.IntentEditor;
+import org.eclipse.mylyn.docs.intent.client.ui.ide.builder.ToggleNatureAction;
+import org.eclipse.mylyn.docs.intent.client.ui.ide.launcher.IDEApplicationManager;
+import org.eclipse.mylyn.docs.intent.client.ui.ide.launcher.IntentProjectManager;
+import org.eclipse.mylyn.docs.intent.client.ui.utils.IntentEditorOpener;
+import org.eclipse.mylyn.docs.intent.collab.common.location.IntentLocations;
+import org.eclipse.mylyn.docs.intent.collab.handlers.adapters.ReadOnlyException;
+import org.eclipse.mylyn.docs.intent.collab.handlers.adapters.RepositoryAdapter;
+import org.eclipse.mylyn.docs.intent.collab.repository.Repository;
+import org.eclipse.mylyn.docs.intent.collab.repository.RepositoryConnectionException;
+import org.eclipse.mylyn.docs.intent.collab.utils.RepositoryCreatorHolder;
+import org.eclipse.mylyn.docs.intent.core.document.IntentDocument;
+import org.eclipse.mylyn.docs.intent.core.document.IntentStructuredElement;
+import org.eclipse.mylyn.docs.intent.parser.modelingunit.test.utils.FileToStringConverter;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IViewPart;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.wizards.IWizardDescriptor;
+
+/**
+ * An abstract test class providing API for manage an Intent IDE projects and editors.
+ * 
+ * @author <a href="mailto:alex.lagarde@obeo.fr">Alex Lagarde</a>
+ */
+public abstract class AbstractUITest extends TestCase {
+
+	public static final String INTENT_NEW_PROJECT_WIZARD_ID = "org.eclipse.mylyn.docs.intent.client.ui.ide.wizards.NewIntentProjectWizard";
+
+	protected IProject intentProject;
+
+	protected Repository repository;
+
+	protected RepositoryAdapter repositoryAdapter;
+
+	private IntentDocument intentDocument;
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see junit.framework.TestCase#setUp()
+	 */
+	@Override
+	protected void setUp() throws Exception {
+		super.setUp();
+		closeWelcomePage();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see junit.framework.TestCase#tearDown()
+	 */
+	@Override
+	protected void tearDown() throws Exception {
+		if (intentProject != null) {
+			intentProject.delete(true, new NullProgressMonitor());
+		}
+		super.tearDown();
+	}
+
+	/**
+	 * Close the welcomePage.
+	 */
+	protected void closeWelcomePage() {
+		IWorkbenchPart activePart = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage()
+				.getActivePart();
+		if (activePart != null && "Welcome".equals(activePart.getTitle()) && activePart instanceof IViewPart) {
+			PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage()
+					.hideView((IViewPart)activePart);
+		}
+		waitForAllOperationsInUIThread();
+	}
+
+	/**
+	 * Creates a new Intent project using the intent document located at the given path.
+	 * 
+	 * @param projectName
+	 *            the intent project name
+	 * @param intentDocumentPath
+	 *            the path of the intent document to use (relative to the
+	 *            org.eclipse.mylyn.docs.intent.client.ui.test project).
+	 */
+	public void setUpIntentProject(final String projectName, String intentDocumentPath) {
+		try {
+			// Step 1 : getting the content of the intent document located at the given path.
+			File file = new File(intentDocumentPath);
+			final String intentDocumentContent = FileToStringConverter.getFileAsString(file);
+
+			// Step 2 : creating the intent project
+			IWorkspaceRunnable create = new IWorkspaceRunnable() {
+				public void run(IProgressMonitor monitor) throws CoreException {
+					IProject project = createProject(projectName, monitor);
+
+					IDEApplicationManager.initializeContent(project, intentDocumentContent);
+					ToggleNatureAction.toggleNature(project);
+
+					// Step 3 : initializing all useful informations
+					intentProject = project;
+					repository = IntentProjectManager.getRepository(project);
+					try {
+						repositoryAdapter = RepositoryCreatorHolder.getCreator()
+								.createRepositoryAdapterForRepository(repository);
+					} catch (RepositoryConnectionException e) {
+						AssertionFailedError error = new AssertionFailedError(
+								"Cannot connect to the created IntentRepository");
+						error.setStackTrace(e.getStackTrace());
+						throw error;
+					}
+				}
+
+			};
+			ResourcesPlugin.getWorkspace().run(create, null);
+
+			while (repositoryAdapter == null
+			// && (repository == null || ((WorkspaceRepository)repository).getEditingDomain()
+			// .getCommandStack() == null)
+			) {
+				Thread.sleep(10);
+			}
+		} catch (CoreException e) {
+			AssertionFailedError error = new AssertionFailedError("Failed to create Intent project");
+			error.setStackTrace(e.getStackTrace());
+			throw error;
+		} catch (IOException e) {
+			AssertionFailedError error = new AssertionFailedError(
+					"Failed to get content of intent document '" + intentDocumentPath + "'");
+			error.setStackTrace(e.getStackTrace());
+			throw error;
+		} catch (InterruptedException e) {
+			AssertionFailedError error = new AssertionFailedError("Failed to create Intent project");
+			error.setStackTrace(e.getStackTrace());
+			throw error;
+		}
+	}
+
+	private static IProject createProject(final String projectName, IProgressMonitor monitor)
+			throws CoreException {
+		IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
+		IPath location = project.getFullPath();
+		if (!project.exists()) {
+			IProjectDescription desc = project.getWorkspace().newProjectDescription(projectName);
+			if (location != null && ResourcesPlugin.getWorkspace().getRoot().getLocation().equals(location)) {
+				location = null;
+			}
+			desc.setLocation(location);
+			project.create(desc, monitor);
+			project.open(monitor);
+		}
+		if (!project.isOpen()) {
+			project.open(monitor);
+		}
+		return project;
+	}
+
+	/**
+	 * Returns the intentDocument associated to the current Intent project.
+	 * 
+	 * @return the intentDocument associated to the current Intent project
+	 */
+	public IntentDocument getIntentDocument() {
+		if (intentDocument == null) {
+			try {
+				Resource documentResource = repositoryAdapter
+						.getOrCreateResource(IntentLocations.INTENT_INDEX);
+				assertTrue("Invalid content of resource '" + IntentLocations.INTENT_INDEX + "'",
+						documentResource.getContents().iterator().next() instanceof IntentDocument);
+				intentDocument = (IntentDocument)documentResource.getContents().iterator().next();
+			} catch (ReadOnlyException e) {
+				// Cannot happen in the test context : no readonly access
+			}
+
+		}
+		return intentDocument;
+	}
+
+	/**
+	 * Opens an editor on the Document contained in the intent project.
+	 */
+	public IntentEditor openIntentEditor() {
+		return openIntentEditor(getIntentDocument());
+	}
+
+	public IntentEditor openIntentEditor(IntentStructuredElement element) {
+		IntentEditorOpener.openIntentEditor(repository, element, true, null, true);
+		return IntentEditorOpener.getAlreadyOpenedEditor(element);
+	}
+
+	/**
+	 * Wait until the end of all asynchronous operations launched in the UI Thread.
+	 */
+	public static void waitForAllOperationsInUIThread() {
+		while (PlatformUI.getWorkbench().getDisplay().readAndDispatch()) {
+			try {
+				Thread.sleep(10);
+			} catch (InterruptedException e) {
+				// Nothing to do
+			}
+		}
+	}
+
+	/**
+	 * Opens the intent wizard.
+	 */
+	private void openIntentWizard() {
+		IWizardDescriptor descriptor = PlatformUI.getWorkbench().getNewWizardRegistry()
+				.findWizard(INTENT_NEW_PROJECT_WIZARD_ID);
+		// If not check if it is an "import wizard".
+		if (descriptor == null) {
+			descriptor = PlatformUI.getWorkbench().getImportWizardRegistry()
+					.findWizard(INTENT_NEW_PROJECT_WIZARD_ID);
+		}
+		// Or maybe an export wizard
+		if (descriptor == null) {
+			descriptor = PlatformUI.getWorkbench().getExportWizardRegistry()
+					.findWizard(INTENT_NEW_PROJECT_WIZARD_ID);
+		}
+		try {
+			// Then if we have a wizard, open it.
+			if (descriptor != null) {
+				IWizard wizard = descriptor.createWizard();
+				WizardDialog wd = new WizardDialog(Display.getDefault().getActiveShell(), wizard);
+				wd.setTitle(wizard.getWindowTitle());
+				wd.open();
+			}
+		} catch (CoreException e) {
+			AssertionFailedError error = new AssertionFailedError(
+					"Failed to create Intent project : cannot properly open wizard");
+			error.setStackTrace(e.getStackTrace());
+			throw error;
+		}
+	}
+}
diff --git a/tests/org.eclipse.mylyn.docs.intent.parser.test/META-INF/MANIFEST.MF b/tests/org.eclipse.mylyn.docs.intent.parser.test/META-INF/MANIFEST.MF
index c0801aa..3f77d13 100644
--- a/tests/org.eclipse.mylyn.docs.intent.parser.test/META-INF/MANIFEST.MF
+++ b/tests/org.eclipse.mylyn.docs.intent.parser.test/META-INF/MANIFEST.MF
@@ -3,7 +3,8 @@
 Bundle-Name: org.eclipse.mylyn.docs.intent.modelingunit.parser.test
 Bundle-SymbolicName: org.eclipse.mylyn.docs.intent.parser.test
 Bundle-Version: 0.7.0.qualifier
-Export-Package: org.eclipse.mylyn.docs.intent.parser.test
+Export-Package: org.eclipse.mylyn.docs.intent.parser.modelingunit.test.utils,
+ org.eclipse.mylyn.docs.intent.parser.test
 Require-Bundle: org.eclipse.emf.common;bundle-version="2.6.0",
  org.eclipse.emf.ecore;bundle-version="2.6.0",
  org.eclipse.mylyn.docs.intent.core,