NEW - bug 375538: New anomaly may create duplicates 
https://bugs.eclipse.org/bugs/show_bug.cgi?id=375538

setJobInProgress has been moved to the beginning of the run method to
prevent the option of adding new anomalies while the creation of another
one is in progress.
diff --git a/org.eclipse.mylyn.reviews.r4e.ui/src/org/eclipse/mylyn/reviews/r4e/ui/internal/commands/handlers/NewAnomalyHandler.java b/org.eclipse.mylyn.reviews.r4e.ui/src/org/eclipse/mylyn/reviews/r4e/ui/internal/commands/handlers/NewAnomalyHandler.java
index ae0c10b..136ec2c 100644
--- a/org.eclipse.mylyn.reviews.r4e.ui/src/org/eclipse/mylyn/reviews/r4e/ui/internal/commands/handlers/NewAnomalyHandler.java
+++ b/org.eclipse.mylyn.reviews.r4e.ui/src/org/eclipse/mylyn/reviews/r4e/ui/internal/commands/handlers/NewAnomalyHandler.java
@@ -1,538 +1,538 @@
-// $codepro.audit.disable com.instantiations.assist.eclipse.analysis.audit.rule.effectivejava.alwaysOverridetoString.alwaysOverrideToString, com.instantiations.assist.eclipse.analysis.deserializeabilitySecurity, com.instantiations.assist.eclipse.analysis.enforceCloneableUsageSecurity

-/*******************************************************************************

- * Copyright (c) 2010 Ericsson Research Canada

- * 

- * 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

- * 

- * Description:

- * 

- * This class implements the context-sensitive command to add an anomaly on 

- * a review item

- * 

- * Contributors:

- *   Sebastien Dubois - Created for Mylyn Review R4E project

- *   

- ******************************************************************************/

-

-package org.eclipse.mylyn.reviews.r4e.ui.internal.commands.handlers;

-

-import java.util.Iterator;

-import java.util.List;

-

-import org.eclipse.core.commands.AbstractHandler;

-import org.eclipse.core.commands.ExecutionEvent;

-import org.eclipse.core.resources.IFile;

-import org.eclipse.core.runtime.CoreException;

-import org.eclipse.core.runtime.IProgressMonitor;

-import org.eclipse.core.runtime.IStatus;

-import org.eclipse.core.runtime.Status;

-import org.eclipse.core.runtime.jobs.Job;

-import org.eclipse.jdt.core.IJavaElement;

-import org.eclipse.jdt.core.ISourceReference;

-import org.eclipse.jface.dialogs.ErrorDialog;

-import org.eclipse.jface.dialogs.MessageDialog;

-import org.eclipse.jface.text.IRegion;

-import org.eclipse.jface.text.ITextSelection;

-import org.eclipse.jface.text.TextSelection;

-import org.eclipse.jface.viewers.AbstractTreeViewer;

-import org.eclipse.jface.viewers.ISelection;

-import org.eclipse.jface.viewers.IStructuredSelection;

-import org.eclipse.jface.viewers.ITreeSelection;

-import org.eclipse.jface.window.Window;

-import org.eclipse.mylyn.reviews.r4e.core.model.R4EAnomaly;

-import org.eclipse.mylyn.reviews.r4e.core.model.R4EFileVersion;

-import org.eclipse.mylyn.reviews.r4e.core.model.serial.impl.OutOfSyncException;

-import org.eclipse.mylyn.reviews.r4e.core.model.serial.impl.ResourceHandlingException;

-import org.eclipse.mylyn.reviews.r4e.core.rfs.spi.ReviewsFileStorageException;

-import org.eclipse.mylyn.reviews.r4e.ui.R4EUIPlugin;

-import org.eclipse.mylyn.reviews.r4e.ui.internal.model.IR4EUIPosition;

-import org.eclipse.mylyn.reviews.r4e.ui.internal.model.R4EUIAnomalyBasic;

-import org.eclipse.mylyn.reviews.r4e.ui.internal.model.R4EUIAnomalyContainer;

-import org.eclipse.mylyn.reviews.r4e.ui.internal.model.R4EUIFileContext;

-import org.eclipse.mylyn.reviews.r4e.ui.internal.model.R4EUIModelController;

-import org.eclipse.mylyn.reviews.r4e.ui.internal.model.R4EUIReviewBasic;

-import org.eclipse.mylyn.reviews.r4e.ui.internal.model.R4EUIReviewItem;

-import org.eclipse.mylyn.reviews.r4e.ui.internal.model.R4EUITextPosition;

-import org.eclipse.mylyn.reviews.r4e.ui.internal.utils.CommandUtils;

-import org.eclipse.mylyn.reviews.r4e.ui.internal.utils.R4EUIConstants;

-import org.eclipse.mylyn.reviews.r4e.ui.internal.utils.UIUtils;

-import org.eclipse.swt.widgets.Display;

-import org.eclipse.ui.IEditorInput;

-import org.eclipse.ui.IEditorPart;

-import org.eclipse.ui.PlatformUI;

-import org.eclipse.ui.handlers.HandlerUtil;

-import org.eclipse.ui.texteditor.ITextEditor;

-

-/**

- * @author lmcdubo

- * @version $Revision: 1.0 $

- */

-public class NewAnomalyHandler extends AbstractHandler {

-

-	// ------------------------------------------------------------------------

-	// Constants

-	// ------------------------------------------------------------------------

-

-	/**

-	 * Field WARNING_BUTTONS_LABELS.

-	 */

-	private static final String[] WARNING_BUTTONS_LABELS = { "Continue", "Cancel" }; //$NON-NLS-1$

-

-	/**

-	 * Field VERSION_STR. (value is ""Version: "")

-	 */

-	private static final String VERSION_STR = "Version: ";

-

-	/**

-	 * Field QUESTION_TITLE. (value is ""R4E question"")

-	 */

-	private static final String QUESTION_TITLE = "R4E question";

-

-	/**

-	 * Field WORKSPACE_FILE_STR. (value is ""Workspace file: "")

-	 */

-	private static final String WORKSPACE_FILE_STR = "Workspace file: ";

-

-	/**

-	 * Field FILE_VERSION_STR. (value is ""Selected file version to review: "")

-	 */

-	private static final String FILE_VERSION_STR = "Selected file version to review: ";

-

-	/**

-	 * Field QUESTION_STR. (value is ""Are you sure you want to add this anomaly to the workspace file ?"")

-	 */

-	private static final String QUESTION_STR = "Are you sure you want to add this anomaly to the workspace file ?";

-

-	/**

-	 * Field MESSAGE_STR. (value is ""You are adding an anomaly to a file version which is different from the one

-	 * selected for review."")

-	 */

-	private static final String MESSAGE_STR = "You are adding an anomaly to a file version which is different from the one selected for review.";

-

-	/**

-	 * Field COMMAND_MESSAGE. (value is ""Adding Anomaly..."")

-	 */

-	private static final String COMMAND_MESSAGE = "Adding Anomaly...";

-

-	// ------------------------------------------------------------------------

-	// Methods

-	// ------------------------------------------------------------------------

-

-	/**

-	 * Method execute.

-	 * 

-	 * @param event

-	 *            ExecutionEvent

-	 * @return Object

-	 * @see org.eclipse.core.commands.IHandler#execute(ExecutionEvent)

-	 */

-	public Object execute(final ExecutionEvent event) {

-

-		final IEditorPart editorPart = PlatformUI.getWorkbench()

-				.getActiveWorkbenchWindow()

-				.getActivePage()

-				.getActiveEditor(); // $codepro.audit.disable methodChainLength

-

-		final IEditorInput input;

-		if (null != editorPart) {

-			input = PlatformUI.getWorkbench()

-					.getActiveWorkbenchWindow()

-					.getActivePage()

-					.getActiveEditor()

-					.getEditorInput(); // $codepro.audit.disable methodChainLength

-		} else {

-			input = null;

-		}

-

-		final Job job = new Job(COMMAND_MESSAGE) {

-			public String familyName = R4EUIConstants.R4E_UI_JOB_FAMILY;

-

-			@Override

-			public boolean belongsTo(Object family) {

-				return familyName.equals(family);

-			}

-

-			@Override

-			public IStatus run(IProgressMonitor monitor) {

-

-				//Act differently depending on the type of selection we get

-				final ISelection selection = HandlerUtil.getCurrentSelection(event);

-				if (selection instanceof ITextSelection) {

-					monitor.beginTask(COMMAND_MESSAGE, IProgressMonitor.UNKNOWN);

-					R4EUIModelController.setJobInProgress(true);

-

-					addAnomalyFromText((ITextSelection) selection, input);

-

-				} else if (selection instanceof ITreeSelection) {

-

-					//First remove any editor selection (if open) if we execute the command from the review navigator view

-					if (null != editorPart && editorPart instanceof ITextEditor) {

-						((ITextEditor) editorPart).getSelectionProvider().setSelection(null);

-					}

-

-					//Then iterate through all selections

-					monitor.beginTask(COMMAND_MESSAGE, ((IStructuredSelection) selection).size());

-					for (final Iterator<?> iterator = ((ITreeSelection) selection).iterator(); iterator.hasNext();) {

-						addAnomalyFromTree(iterator.next(), monitor);

-						if (monitor.isCanceled()) {

-							R4EUIModelController.setJobInProgress(false);

-							return Status.CANCEL_STATUS;

-						}

-					}

-				} else if (selection.isEmpty()) {

-					//Try to get the active editor highlighted range and set it as the editor's selection

-					if (null != editorPart) {

-						if (editorPart instanceof ITextEditor) {

-							final IRegion region = ((ITextEditor) editorPart).getHighlightRange();

-							final TextSelection selectedText = new TextSelection(

-									((ITextEditor) editorPart).getDocumentProvider().getDocument(

-											editorPart.getEditorInput()), region.getOffset(), region.getLength());

-							((ITextEditor) editorPart).getSelectionProvider().setSelection(selectedText);

-							addAnomalyFromText(selectedText, input);

-						}

-					}

-				}

-				R4EUIModelController.setJobInProgress(false);

-				monitor.done();

-				return Status.OK_STATUS;

-			}

-		};

-		job.setUser(false);

-		job.schedule();

-		return null;

-	}

-

-	/**

-	 * Method addAnomalyFromText.

-	 * 

-	 * @param aSelection

-	 *            ITextSelection

-	 * @param aInput

-	 *            - IEditorInput

-	 */

-	private void addAnomalyFromText(ITextSelection aSelection, IEditorInput aInput) {

-		//This is a text selection in a text editor, we need to get the file path and

-		//the position of the selection within the file

-		try {

-			final R4EUITextPosition position = CommandUtils.getPosition(aSelection);

-			final R4EFileVersion baseVersion = CommandUtils.getBaseFileData(aInput);

-			final R4EFileVersion targetVersion = CommandUtils.getTargetFileData(aInput);

-

-			//Add anomaly to model

-			if (null != targetVersion) {

-				addAnomaly(baseVersion, targetVersion, position);

-			} else {

-				R4EUIPlugin.Ftracer.traceWarning("Trying to add review item to base file");

-				final ErrorDialog dialog = new ErrorDialog(null, R4EUIConstants.DIALOG_TITLE_ERROR,

-						"Add Anomaly Error", new Status(IStatus.ERROR, R4EUIPlugin.PLUGIN_ID, 0,

-								"No Target File present to Add Anomaly", null), IStatus.ERROR);

-				Display.getDefault().syncExec(new Runnable() {

-					public void run() {

-						dialog.open();

-					}

-				});

-			}

-		} catch (CoreException e) {

-			UIUtils.displayCoreErrorDialog(e);

-		} catch (ReviewsFileStorageException e) {

-			UIUtils.displayReviewsFileStorageErrorDialog(e);

-		}

-	}

-

-	/**

-	 * Method addAnomalyFromTree.

-	 * 

-	 * @param aSelection

-	 *            ITreeSelection

-	 * @param aMonitor

-	 *            IProgressMonitor

-	 */

-	private void addAnomalyFromTree(Object aSelection, IProgressMonitor aMonitor) {

-

-		//This is a selection from the tree view (e.g. Review Navigator, Package Explorer etc...)

-		//We will need to get the parent file path and the position of the element in a text editor

-		//If the selection is on the File itself, then the selection will include all the lines

-		//in the file.  Otherwise it will include all the lines corresponding to the currently 

-		//selected element	

-		try {

-

-			R4EUITextPosition position = null;

-			IFile workspaceFile = null;

-

-			if (aSelection instanceof IFile) {

-				position = CommandUtils.getPosition((IFile) aSelection);

-				workspaceFile = (IFile) aSelection;

-			} else if (R4EUIPlugin.isJDTAvailable() && aSelection instanceof ISourceReference) {

-				//NOTE:  This is always true because all elements that implement ISourceReference

-				//       also implement IJavaElement.  The resource is always an IFile

-				workspaceFile = (IFile) ((IJavaElement) aSelection).getResource();

-				//TODO is that the right file to get the position???

-				position = CommandUtils.getPosition((ISourceReference) aSelection, workspaceFile);

-			} else if (R4EUIPlugin.isCDTAvailable()

-					&& aSelection instanceof org.eclipse.cdt.core.model.ISourceReference) {

-				//NOTE:  This is always true because all elements that implement ISourceReference

-				//       also implement ICElement.  The resource is always an IFile

-				if (aSelection instanceof org.eclipse.cdt.core.model.ITranslationUnit) {

-					workspaceFile = (IFile) ((org.eclipse.cdt.core.model.ICElement) aSelection).getResource();

-				} else if (aSelection instanceof org.eclipse.cdt.core.model.ICElement) {

-					workspaceFile = (IFile) ((org.eclipse.cdt.core.model.ICElement) aSelection).getParent()

-							.getResource();

-				}

-				//TODO is that the right file to get the position???

-				position = CommandUtils.getPosition((org.eclipse.cdt.core.model.ISourceReference) aSelection,

-						workspaceFile);

-			} else {

-				//This should never happen

-				R4EUIPlugin.Ftracer.traceWarning("Invalid selection " + aSelection.getClass().toString()

-						+ ".  Ignoring");

-				return;

-			}

-

-			//Add anomaly to model

-			final R4EFileVersion baseVersion = CommandUtils.updateBaseFile(workspaceFile);

-			final R4EFileVersion targetVersion = CommandUtils.updateTargetFile(workspaceFile);

-

-			//Add anomaly to model

-			if (null != targetVersion) {

-				aMonitor.subTask("Adding " + targetVersion.getName());

-				addAnomaly(baseVersion, targetVersion, position);

-				aMonitor.worked(1);

-			} else {

-				R4EUIPlugin.Ftracer.traceWarning("Trying to add review item to base file");

-				final ErrorDialog dialog = new ErrorDialog(null, R4EUIConstants.DIALOG_TITLE_ERROR,

-						"Add Anomaly Error", new Status(IStatus.ERROR, R4EUIPlugin.PLUGIN_ID, 0,

-								"No Target File present to Add Anomaly", null), IStatus.ERROR);

-				Display.getDefault().syncExec(new Runnable() {

-					public void run() {

-						dialog.open();

-					}

-				});

-			}

-		} catch (CoreException e) {

-			UIUtils.displayCoreErrorDialog(e);

-		} catch (ReviewsFileStorageException e) {

-			UIUtils.displayReviewsFileStorageErrorDialog(e);

-		}

-	}

-

-	/**

-	 * Method AddAnomaly. Adds an anomaly to the model based on user input

-	 * 

-	 * @param aBaseFileVersion

-	 *            R4EFileVersion

-	 * @param aTargetFileVersion

-	 *            R4EFileVersion

-	 * @param aUIPosition

-	 *            IR4EUIPosition

-	 */

-	private void addAnomaly(R4EFileVersion aBaseFileVersion, R4EFileVersion aTargetFileVersion,

-			IR4EUIPosition aUIPosition) {

-

-		R4EUIFileContext tempFileContext = null;

-		//Check if the file element and/or anomaly already exist

-		//If file exists, add anomaly element to it

-		//if anomaly element already exist, add a new comment to it

-		//for all other cases, create the parent elements as needed as well.

-		final List<R4EUIReviewItem> reviewItems = R4EUIModelController.getActiveReview().getReviewItems();

-

-		boolean isNewAnomaly = true;

-		for (R4EUIReviewItem reviewItem : reviewItems) {

-			R4EUIFileContext[] files = (R4EUIFileContext[]) reviewItem.getChildren();

-			for (R4EUIFileContext file : files) {

-				if (null != file.getFileContext().getTarget()

-						&& aTargetFileVersion.getLocalVersionID().equals(

-								file.getFileContext().getTarget().getLocalVersionID())) {

-

-					//File already exists, check if anomaly also exists

-					R4EUIAnomalyContainer anomalyContainer = file.getAnomalyContainerElement();

-					R4EUIAnomalyBasic[] anomalies = (R4EUIAnomalyBasic[]) anomalyContainer.getChildren();

-					for (R4EUIAnomalyBasic uiAnomaly : anomalies) {

-						if (uiAnomaly.getPosition().isSameAs(aUIPosition)) {

-							isNewAnomaly = false;

-							addCommentToExistingAnomaly(uiAnomaly);

-							R4EUIPlugin.Ftracer.traceInfo("Added comment to existing anomaly: Target = "

-									+ file.getFileContext().getTarget().getName()

-									+ ((null != file.getFileContext().getBase()) ? "Base = "

-											+ file.getFileContext().getBase().getName() : "") + " Position = "

-									+ aUIPosition.toString());

-						}

-					}

-					if (isNewAnomaly) {

-						addAnomalyToExistingFileContext(aTargetFileVersion, anomalyContainer, aUIPosition);

-						R4EUIPlugin.Ftracer.traceInfo("Added anomaly: Target = "

-								+ file.getFileContext().getTarget().getName()

-								+ ((null != file.getFileContext().getBase()) ? "Base = "

-										+ file.getFileContext().getBase().getName() : "") + " Position = "

-								+ aUIPosition.toString());

-					}

-					return; //We found the file so we are done here	

-				} else if (null != file.getFileContext().getTarget()) {

-					//Test if we find both file in the workspace

-					String reviewPlatformURI = file.getFileContext().getTarget().getPlatformURI();

-					String targetPlatformURI = aTargetFileVersion.getPlatformURI();

-					if (null != reviewPlatformURI && null != targetPlatformURI) {

-						//Now we can compare the path

-						if (reviewPlatformURI.equals(targetPlatformURI)) {

-							//Found the same file but not the same version

-							tempFileContext = file;

-						}

-					}

-				}

-			}

-		}

-

-		//Ask a question to see if the end-user wants to continue or not

-		if (null != tempFileContext) {

-			//The file exist with a different file version

-			final int[] result = new int[1]; //We need this to be able to pass the result value outside.  This is safe as we are using SyncExec

-			final MessageDialog dialog = displayDifferentFileVersionDialog(aTargetFileVersion, tempFileContext);

-			Display.getDefault().syncExec(new Runnable() {

-				public void run() {

-					result[0] = dialog.open();

-				}

-			});

-			if (result[0] == Window.CANCEL) {

-				// Cancel selected, so just exit here and do not add anomaly

-				return;

-			}

-		}

-

-		//This is a new file create it (and its parent reviewItem) and all its children

-		addAnomalyToNewFileContext(aBaseFileVersion, aTargetFileVersion, aUIPosition);

-		R4EUIPlugin.Ftracer.traceInfo("Added Anomaly: Target = "

-				+ aTargetFileVersion.getName()

-				+ "_"

-				+ aTargetFileVersion.getVersionID()

-				+ ((null != aBaseFileVersion) ? "Base = " + aBaseFileVersion.getName() + "_"

-						+ aBaseFileVersion.getVersionID() : "") + " Position = " + aUIPosition.toString());

-	}

-

-	/**

-	 * Method displayDifferentFileVersionDialog.

-	 * 

-	 * @param aTargetFileVersion

-	 *            R4EFileVersion

-	 * @param aTempFileContext

-	 *            R4EUIFileContext

-	 * @return MessageDialog

-	 */

-	private MessageDialog displayDifferentFileVersionDialog(R4EFileVersion aTargetFileVersion,

-			R4EUIFileContext aTempFileContext) {

-

-		//The file exist with a different file version

-		final String wsFileName = aTargetFileVersion.getRepositoryPath();

-		final String wsFileVersion = aTargetFileVersion.getVersionID();

-		final String riFileName = aTempFileContext.getTargetFileVersion().getRepositoryPath();

-		final String riFileVersion = aTempFileContext.getTargetFileVersion().getVersionID();

-

-		final StringBuilder sb = new StringBuilder();

-		sb.append(MESSAGE_STR + R4EUIConstants.LINE_FEED + R4EUIConstants.LINE_FEED);

-		sb.append(FILE_VERSION_STR);

-		sb.append(riFileName + R4EUIConstants.LINE_FEED);

-		sb.append(VERSION_STR);

-		sb.append(riFileVersion + R4EUIConstants.LINE_FEED + R4EUIConstants.LINE_FEED);

-		sb.append(WORKSPACE_FILE_STR);

-		sb.append(wsFileName + R4EUIConstants.LINE_FEED);

-		sb.append(VERSION_STR);

-		sb.append(wsFileVersion + R4EUIConstants.LINE_FEED + R4EUIConstants.LINE_FEED);

-		sb.append(QUESTION_STR);

-

-		final MessageDialog dialog = new MessageDialog(null, // Shell

-				QUESTION_TITLE, // Dialog title

-				null, // Dialog title image message

-				sb.toString(), // Dialog message

-				MessageDialog.WARNING, // Dialog type

-				WARNING_BUTTONS_LABELS, // Dialog button labels

-				Window.OK // Default index (selection)

-		);

-

-		return dialog;

-	}

-

-	/**

-	 * Method addCommentToExistingAnomaly.

-	 * 

-	 * @param aUIAnomaly

-	 *            R4EUIAnomaly

-	 */

-	private void addCommentToExistingAnomaly(R4EUIAnomalyBasic aUIAnomaly) {

-		aUIAnomaly.createComment(false);

-	}

-

-	/**

-	 * Method addAnomalyToExistingFileContext.

-	 * 

-	 * @param aTargetFileVersion

-	 *            R4EFileVersion

-	 * @param aContainer

-	 *            R4EUIAnomalyContainer

-	 * @param aUIPosition

-	 *            IR4EUIPosition

-	 */

-	private void addAnomalyToExistingFileContext(R4EFileVersion aTargetFileVersion, R4EUIAnomalyContainer aContainer,

-			IR4EUIPosition aUIPosition) {

-		aContainer.createAnomaly(aTargetFileVersion, (R4EUITextPosition) aUIPosition);

-	}

-

-	/**

-	 * Method addAnomalyToNewFileContext.

-	 * 

-	 * @param aBaseFileVersion

-	 *            R4EFileVersion

-	 * @param aTargetFileVersion

-	 *            R4EFileVersion

-	 * @param aUIPosition

-	 *            IR4EUIPosition

-	 */

-	private void addAnomalyToNewFileContext(final R4EFileVersion aBaseFileVersion,

-			final R4EFileVersion aTargetFileVersion, final IR4EUIPosition aUIPosition) {

-

-		final R4EAnomaly tempAnomaly = R4EUIAnomalyContainer.createDetachedAnomaly();

-

-		if (null != tempAnomaly) {

-

-			final Job job = new Job(R4EUIAnomalyContainer.CREATE_ANOMALY_MESSAGE) {

-				public String familyName = R4EUIConstants.R4E_UI_JOB_FAMILY;

-

-				@Override

-				public boolean belongsTo(Object family) {

-					return familyName.equals(family);

-				}

-

-				@Override

-				public IStatus run(IProgressMonitor monitor) {

-					try {

-						final R4EUIReviewBasic uiReview = R4EUIModelController.getActiveReview();

-						final R4EUIReviewItem uiReviewItem = uiReview.createResourceReviewItem(aTargetFileVersion.getName());

-						if (null == uiReviewItem) {

-							return Status.CANCEL_STATUS;

-						}

-						final R4EUIFileContext uiFileContext = uiReviewItem.createFileContext(aBaseFileVersion,

-								aTargetFileVersion, null);

-						if (null == uiFileContext) {

-							uiReview.removeChildren(uiReviewItem, false);

-							return Status.CANCEL_STATUS;

-						}

-

-						final R4EUIAnomalyContainer uiAnomalyContainer = uiFileContext.getAnomalyContainerElement();

-						final R4EUIAnomalyBasic uiAnomaly = uiAnomalyContainer.createAnomalyFromDetached(

-								aTargetFileVersion, tempAnomaly, (R4EUITextPosition) aUIPosition);

-						R4EUIModelController.setJobInProgress(false);

-						UIUtils.setNavigatorViewFocus(uiAnomaly, AbstractTreeViewer.ALL_LEVELS);

-					} catch (ResourceHandlingException e) {

-						UIUtils.displayResourceErrorDialog(e);

-					} catch (OutOfSyncException e) {

-						UIUtils.displaySyncErrorDialog(e);

-					}

-					monitor.done();

-					return Status.OK_STATUS;

-				}

-			};

-			job.setUser(true);

-			job.schedule();

-		}

-	}

-}

+// $codepro.audit.disable com.instantiations.assist.eclipse.analysis.audit.rule.effectivejava.alwaysOverridetoString.alwaysOverrideToString, com.instantiations.assist.eclipse.analysis.deserializeabilitySecurity, com.instantiations.assist.eclipse.analysis.enforceCloneableUsageSecurity
+/*******************************************************************************
+ * Copyright (c) 2010 Ericsson Research Canada
+ * 
+ * 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
+ * 
+ * Description:
+ * 
+ * This class implements the context-sensitive command to add an anomaly on 
+ * a review item
+ * 
+ * Contributors:
+ *   Sebastien Dubois - Created for Mylyn Review R4E project
+ *   
+ ******************************************************************************/
+
+package org.eclipse.mylyn.reviews.r4e.ui.internal.commands.handlers;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.ISourceReference;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.TextSelection;
+import org.eclipse.jface.viewers.AbstractTreeViewer;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeSelection;
+import org.eclipse.jface.window.Window;
+import org.eclipse.mylyn.reviews.r4e.core.model.R4EAnomaly;
+import org.eclipse.mylyn.reviews.r4e.core.model.R4EFileVersion;
+import org.eclipse.mylyn.reviews.r4e.core.model.serial.impl.OutOfSyncException;
+import org.eclipse.mylyn.reviews.r4e.core.model.serial.impl.ResourceHandlingException;
+import org.eclipse.mylyn.reviews.r4e.core.rfs.spi.ReviewsFileStorageException;
+import org.eclipse.mylyn.reviews.r4e.ui.R4EUIPlugin;
+import org.eclipse.mylyn.reviews.r4e.ui.internal.model.IR4EUIPosition;
+import org.eclipse.mylyn.reviews.r4e.ui.internal.model.R4EUIAnomalyBasic;
+import org.eclipse.mylyn.reviews.r4e.ui.internal.model.R4EUIAnomalyContainer;
+import org.eclipse.mylyn.reviews.r4e.ui.internal.model.R4EUIFileContext;
+import org.eclipse.mylyn.reviews.r4e.ui.internal.model.R4EUIModelController;
+import org.eclipse.mylyn.reviews.r4e.ui.internal.model.R4EUIReviewBasic;
+import org.eclipse.mylyn.reviews.r4e.ui.internal.model.R4EUIReviewItem;
+import org.eclipse.mylyn.reviews.r4e.ui.internal.model.R4EUITextPosition;
+import org.eclipse.mylyn.reviews.r4e.ui.internal.utils.CommandUtils;
+import org.eclipse.mylyn.reviews.r4e.ui.internal.utils.R4EUIConstants;
+import org.eclipse.mylyn.reviews.r4e.ui.internal.utils.UIUtils;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.handlers.HandlerUtil;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+/**
+ * @author lmcdubo
+ * @version $Revision: 1.0 $
+ */
+public class NewAnomalyHandler extends AbstractHandler {
+
+	// ------------------------------------------------------------------------
+	// Constants
+	// ------------------------------------------------------------------------
+
+	/**
+	 * Field WARNING_BUTTONS_LABELS.
+	 */
+	private static final String[] WARNING_BUTTONS_LABELS = { "Continue", "Cancel" }; //$NON-NLS-1$
+
+	/**
+	 * Field VERSION_STR. (value is ""Version: "")
+	 */
+	private static final String VERSION_STR = "Version: ";
+
+	/**
+	 * Field QUESTION_TITLE. (value is ""R4E question"")
+	 */
+	private static final String QUESTION_TITLE = "R4E question";
+
+	/**
+	 * Field WORKSPACE_FILE_STR. (value is ""Workspace file: "")
+	 */
+	private static final String WORKSPACE_FILE_STR = "Workspace file: ";
+
+	/**
+	 * Field FILE_VERSION_STR. (value is ""Selected file version to review: "")
+	 */
+	private static final String FILE_VERSION_STR = "Selected file version to review: ";
+
+	/**
+	 * Field QUESTION_STR. (value is ""Are you sure you want to add this anomaly to the workspace file ?"")
+	 */
+	private static final String QUESTION_STR = "Are you sure you want to add this anomaly to the workspace file ?";
+
+	/**
+	 * Field MESSAGE_STR. (value is ""You are adding an anomaly to a file version which is different from the one
+	 * selected for review."")
+	 */
+	private static final String MESSAGE_STR = "You are adding an anomaly to a file version which is different from the one selected for review.";
+
+	/**
+	 * Field COMMAND_MESSAGE. (value is ""Adding Anomaly..."")
+	 */
+	private static final String COMMAND_MESSAGE = "Adding Anomaly...";
+
+	// ------------------------------------------------------------------------
+	// Methods
+	// ------------------------------------------------------------------------
+
+	/**
+	 * Method execute.
+	 * 
+	 * @param event
+	 *            ExecutionEvent
+	 * @return Object
+	 * @see org.eclipse.core.commands.IHandler#execute(ExecutionEvent)
+	 */
+	public Object execute(final ExecutionEvent event) {
+
+		final IEditorPart editorPart = PlatformUI.getWorkbench()
+				.getActiveWorkbenchWindow()
+				.getActivePage()
+				.getActiveEditor(); // $codepro.audit.disable methodChainLength
+
+		final IEditorInput input;
+		if (null != editorPart) {
+			input = PlatformUI.getWorkbench()
+					.getActiveWorkbenchWindow()
+					.getActivePage()
+					.getActiveEditor()
+					.getEditorInput(); // $codepro.audit.disable methodChainLength
+		} else {
+			input = null;
+		}
+
+		final Job job = new Job(COMMAND_MESSAGE) {
+			public String familyName = R4EUIConstants.R4E_UI_JOB_FAMILY;
+
+			@Override
+			public boolean belongsTo(Object family) {
+				return familyName.equals(family);
+			}
+
+			@Override
+			public IStatus run(IProgressMonitor monitor) {
+
+				//Act differently depending on the type of selection we get
+				final ISelection selection = HandlerUtil.getCurrentSelection(event);
+				R4EUIModelController.setJobInProgress(true);
+
+				if (selection instanceof ITextSelection) {
+					monitor.beginTask(COMMAND_MESSAGE, IProgressMonitor.UNKNOWN);
+					addAnomalyFromText((ITextSelection) selection, input);
+
+				} else if (selection instanceof ITreeSelection) {
+
+					//First remove any editor selection (if open) if we execute the command from the review navigator view
+					if (null != editorPart && editorPart instanceof ITextEditor) {
+						((ITextEditor) editorPart).getSelectionProvider().setSelection(null);
+					}
+
+					//Then iterate through all selections
+					monitor.beginTask(COMMAND_MESSAGE, ((IStructuredSelection) selection).size());
+					for (final Iterator<?> iterator = ((ITreeSelection) selection).iterator(); iterator.hasNext();) {
+						addAnomalyFromTree(iterator.next(), monitor);
+						if (monitor.isCanceled()) {
+							R4EUIModelController.setJobInProgress(false);
+							return Status.CANCEL_STATUS;
+						}
+					}
+				} else if (selection.isEmpty()) {
+					//Try to get the active editor highlighted range and set it as the editor's selection
+					if (null != editorPart) {
+						if (editorPart instanceof ITextEditor) {
+							final IRegion region = ((ITextEditor) editorPart).getHighlightRange();
+							final TextSelection selectedText = new TextSelection(
+									((ITextEditor) editorPart).getDocumentProvider().getDocument(
+											editorPart.getEditorInput()), region.getOffset(), region.getLength());
+							((ITextEditor) editorPart).getSelectionProvider().setSelection(selectedText);
+							addAnomalyFromText(selectedText, input);
+						}
+					}
+				}
+				R4EUIModelController.setJobInProgress(false);
+				monitor.done();
+				return Status.OK_STATUS;
+			}
+		};
+		job.setUser(false);
+		job.schedule();
+		return null;
+	}
+
+	/**
+	 * Method addAnomalyFromText.
+	 * 
+	 * @param aSelection
+	 *            ITextSelection
+	 * @param aInput
+	 *            - IEditorInput
+	 */
+	private void addAnomalyFromText(ITextSelection aSelection, IEditorInput aInput) {
+		//This is a text selection in a text editor, we need to get the file path and
+		//the position of the selection within the file
+		try {
+			final R4EUITextPosition position = CommandUtils.getPosition(aSelection);
+			final R4EFileVersion baseVersion = CommandUtils.getBaseFileData(aInput);
+			final R4EFileVersion targetVersion = CommandUtils.getTargetFileData(aInput);
+
+			//Add anomaly to model
+			if (null != targetVersion) {
+				addAnomaly(baseVersion, targetVersion, position);
+			} else {
+				R4EUIPlugin.Ftracer.traceWarning("Trying to add review item to base file");
+				final ErrorDialog dialog = new ErrorDialog(null, R4EUIConstants.DIALOG_TITLE_ERROR,
+						"Add Anomaly Error", new Status(IStatus.ERROR, R4EUIPlugin.PLUGIN_ID, 0,
+								"No Target File present to Add Anomaly", null), IStatus.ERROR);
+				Display.getDefault().syncExec(new Runnable() {
+					public void run() {
+						dialog.open();
+					}
+				});
+			}
+		} catch (CoreException e) {
+			UIUtils.displayCoreErrorDialog(e);
+		} catch (ReviewsFileStorageException e) {
+			UIUtils.displayReviewsFileStorageErrorDialog(e);
+		}
+	}
+
+	/**
+	 * Method addAnomalyFromTree.
+	 * 
+	 * @param aSelection
+	 *            ITreeSelection
+	 * @param aMonitor
+	 *            IProgressMonitor
+	 */
+	private void addAnomalyFromTree(Object aSelection, IProgressMonitor aMonitor) {
+
+		//This is a selection from the tree view (e.g. Review Navigator, Package Explorer etc...)
+		//We will need to get the parent file path and the position of the element in a text editor
+		//If the selection is on the File itself, then the selection will include all the lines
+		//in the file.  Otherwise it will include all the lines corresponding to the currently 
+		//selected element	
+		try {
+
+			R4EUITextPosition position = null;
+			IFile workspaceFile = null;
+
+			if (aSelection instanceof IFile) {
+				position = CommandUtils.getPosition((IFile) aSelection);
+				workspaceFile = (IFile) aSelection;
+			} else if (R4EUIPlugin.isJDTAvailable() && aSelection instanceof ISourceReference) {
+				//NOTE:  This is always true because all elements that implement ISourceReference
+				//       also implement IJavaElement.  The resource is always an IFile
+				workspaceFile = (IFile) ((IJavaElement) aSelection).getResource();
+				//TODO is that the right file to get the position???
+				position = CommandUtils.getPosition((ISourceReference) aSelection, workspaceFile);
+			} else if (R4EUIPlugin.isCDTAvailable()
+					&& aSelection instanceof org.eclipse.cdt.core.model.ISourceReference) {
+				//NOTE:  This is always true because all elements that implement ISourceReference
+				//       also implement ICElement.  The resource is always an IFile
+				if (aSelection instanceof org.eclipse.cdt.core.model.ITranslationUnit) {
+					workspaceFile = (IFile) ((org.eclipse.cdt.core.model.ICElement) aSelection).getResource();
+				} else if (aSelection instanceof org.eclipse.cdt.core.model.ICElement) {
+					workspaceFile = (IFile) ((org.eclipse.cdt.core.model.ICElement) aSelection).getParent()
+							.getResource();
+				}
+				//TODO is that the right file to get the position???
+				position = CommandUtils.getPosition((org.eclipse.cdt.core.model.ISourceReference) aSelection,
+						workspaceFile);
+			} else {
+				//This should never happen
+				R4EUIPlugin.Ftracer.traceWarning("Invalid selection " + aSelection.getClass().toString()
+						+ ".  Ignoring");
+				return;
+			}
+
+			//Add anomaly to model
+			final R4EFileVersion baseVersion = CommandUtils.updateBaseFile(workspaceFile);
+			final R4EFileVersion targetVersion = CommandUtils.updateTargetFile(workspaceFile);
+
+			//Add anomaly to model
+			if (null != targetVersion) {
+				aMonitor.subTask("Adding " + targetVersion.getName());
+				addAnomaly(baseVersion, targetVersion, position);
+				aMonitor.worked(1);
+			} else {
+				R4EUIPlugin.Ftracer.traceWarning("Trying to add review item to base file");
+				final ErrorDialog dialog = new ErrorDialog(null, R4EUIConstants.DIALOG_TITLE_ERROR,
+						"Add Anomaly Error", new Status(IStatus.ERROR, R4EUIPlugin.PLUGIN_ID, 0,
+								"No Target File present to Add Anomaly", null), IStatus.ERROR);
+				Display.getDefault().syncExec(new Runnable() {
+					public void run() {
+						dialog.open();
+					}
+				});
+			}
+		} catch (CoreException e) {
+			UIUtils.displayCoreErrorDialog(e);
+		} catch (ReviewsFileStorageException e) {
+			UIUtils.displayReviewsFileStorageErrorDialog(e);
+		}
+	}
+
+	/**
+	 * Method AddAnomaly. Adds an anomaly to the model based on user input
+	 * 
+	 * @param aBaseFileVersion
+	 *            R4EFileVersion
+	 * @param aTargetFileVersion
+	 *            R4EFileVersion
+	 * @param aUIPosition
+	 *            IR4EUIPosition
+	 */
+	private void addAnomaly(R4EFileVersion aBaseFileVersion, R4EFileVersion aTargetFileVersion,
+			IR4EUIPosition aUIPosition) {
+
+		R4EUIFileContext tempFileContext = null;
+		//Check if the file element and/or anomaly already exist
+		//If file exists, add anomaly element to it
+		//if anomaly element already exist, add a new comment to it
+		//for all other cases, create the parent elements as needed as well.
+		final List<R4EUIReviewItem> reviewItems = R4EUIModelController.getActiveReview().getReviewItems();
+
+		boolean isNewAnomaly = true;
+		for (R4EUIReviewItem reviewItem : reviewItems) {
+			R4EUIFileContext[] files = (R4EUIFileContext[]) reviewItem.getChildren();
+			for (R4EUIFileContext file : files) {
+				if (null != file.getFileContext().getTarget()
+						&& aTargetFileVersion.getLocalVersionID().equals(
+								file.getFileContext().getTarget().getLocalVersionID())) {
+
+					//File already exists, check if anomaly also exists
+					R4EUIAnomalyContainer anomalyContainer = file.getAnomalyContainerElement();
+					R4EUIAnomalyBasic[] anomalies = (R4EUIAnomalyBasic[]) anomalyContainer.getChildren();
+					for (R4EUIAnomalyBasic uiAnomaly : anomalies) {
+						if (uiAnomaly.getPosition().isSameAs(aUIPosition)) {
+							isNewAnomaly = false;
+							addCommentToExistingAnomaly(uiAnomaly);
+							R4EUIPlugin.Ftracer.traceInfo("Added comment to existing anomaly: Target = "
+									+ file.getFileContext().getTarget().getName()
+									+ ((null != file.getFileContext().getBase()) ? "Base = "
+											+ file.getFileContext().getBase().getName() : "") + " Position = "
+									+ aUIPosition.toString());
+						}
+					}
+					if (isNewAnomaly) {
+						addAnomalyToExistingFileContext(aTargetFileVersion, anomalyContainer, aUIPosition);
+						R4EUIPlugin.Ftracer.traceInfo("Added anomaly: Target = "
+								+ file.getFileContext().getTarget().getName()
+								+ ((null != file.getFileContext().getBase()) ? "Base = "
+										+ file.getFileContext().getBase().getName() : "") + " Position = "
+								+ aUIPosition.toString());
+					}
+					return; //We found the file so we are done here	
+				} else if (null != file.getFileContext().getTarget()) {
+					//Test if we find both file in the workspace
+					String reviewPlatformURI = file.getFileContext().getTarget().getPlatformURI();
+					String targetPlatformURI = aTargetFileVersion.getPlatformURI();
+					if (null != reviewPlatformURI && null != targetPlatformURI) {
+						//Now we can compare the path
+						if (reviewPlatformURI.equals(targetPlatformURI)) {
+							//Found the same file but not the same version
+							tempFileContext = file;
+						}
+					}
+				}
+			}
+		}
+
+		//Ask a question to see if the end-user wants to continue or not
+		if (null != tempFileContext) {
+			//The file exist with a different file version
+			final int[] result = new int[1]; //We need this to be able to pass the result value outside.  This is safe as we are using SyncExec
+			final MessageDialog dialog = displayDifferentFileVersionDialog(aTargetFileVersion, tempFileContext);
+			Display.getDefault().syncExec(new Runnable() {
+				public void run() {
+					result[0] = dialog.open();
+				}
+			});
+			if (result[0] == Window.CANCEL) {
+				// Cancel selected, so just exit here and do not add anomaly
+				return;
+			}
+		}
+
+		//This is a new file create it (and its parent reviewItem) and all its children
+		addAnomalyToNewFileContext(aBaseFileVersion, aTargetFileVersion, aUIPosition);
+		R4EUIPlugin.Ftracer.traceInfo("Added Anomaly: Target = "
+				+ aTargetFileVersion.getName()
+				+ "_"
+				+ aTargetFileVersion.getVersionID()
+				+ ((null != aBaseFileVersion) ? "Base = " + aBaseFileVersion.getName() + "_"
+						+ aBaseFileVersion.getVersionID() : "") + " Position = " + aUIPosition.toString());
+	}
+
+	/**
+	 * Method displayDifferentFileVersionDialog.
+	 * 
+	 * @param aTargetFileVersion
+	 *            R4EFileVersion
+	 * @param aTempFileContext
+	 *            R4EUIFileContext
+	 * @return MessageDialog
+	 */
+	private MessageDialog displayDifferentFileVersionDialog(R4EFileVersion aTargetFileVersion,
+			R4EUIFileContext aTempFileContext) {
+
+		//The file exist with a different file version
+		final String wsFileName = aTargetFileVersion.getRepositoryPath();
+		final String wsFileVersion = aTargetFileVersion.getVersionID();
+		final String riFileName = aTempFileContext.getTargetFileVersion().getRepositoryPath();
+		final String riFileVersion = aTempFileContext.getTargetFileVersion().getVersionID();
+
+		final StringBuilder sb = new StringBuilder();
+		sb.append(MESSAGE_STR + R4EUIConstants.LINE_FEED + R4EUIConstants.LINE_FEED);
+		sb.append(FILE_VERSION_STR);
+		sb.append(riFileName + R4EUIConstants.LINE_FEED);
+		sb.append(VERSION_STR);
+		sb.append(riFileVersion + R4EUIConstants.LINE_FEED + R4EUIConstants.LINE_FEED);
+		sb.append(WORKSPACE_FILE_STR);
+		sb.append(wsFileName + R4EUIConstants.LINE_FEED);
+		sb.append(VERSION_STR);
+		sb.append(wsFileVersion + R4EUIConstants.LINE_FEED + R4EUIConstants.LINE_FEED);
+		sb.append(QUESTION_STR);
+
+		final MessageDialog dialog = new MessageDialog(null, // Shell
+				QUESTION_TITLE, // Dialog title
+				null, // Dialog title image message
+				sb.toString(), // Dialog message
+				MessageDialog.WARNING, // Dialog type
+				WARNING_BUTTONS_LABELS, // Dialog button labels
+				Window.OK // Default index (selection)
+		);
+
+		return dialog;
+	}
+
+	/**
+	 * Method addCommentToExistingAnomaly.
+	 * 
+	 * @param aUIAnomaly
+	 *            R4EUIAnomaly
+	 */
+	private void addCommentToExistingAnomaly(R4EUIAnomalyBasic aUIAnomaly) {
+		aUIAnomaly.createComment(false);
+	}
+
+	/**
+	 * Method addAnomalyToExistingFileContext.
+	 * 
+	 * @param aTargetFileVersion
+	 *            R4EFileVersion
+	 * @param aContainer
+	 *            R4EUIAnomalyContainer
+	 * @param aUIPosition
+	 *            IR4EUIPosition
+	 */
+	private void addAnomalyToExistingFileContext(R4EFileVersion aTargetFileVersion, R4EUIAnomalyContainer aContainer,
+			IR4EUIPosition aUIPosition) {
+		aContainer.createAnomaly(aTargetFileVersion, (R4EUITextPosition) aUIPosition);
+	}
+
+	/**
+	 * Method addAnomalyToNewFileContext.
+	 * 
+	 * @param aBaseFileVersion
+	 *            R4EFileVersion
+	 * @param aTargetFileVersion
+	 *            R4EFileVersion
+	 * @param aUIPosition
+	 *            IR4EUIPosition
+	 */
+	private void addAnomalyToNewFileContext(final R4EFileVersion aBaseFileVersion,
+			final R4EFileVersion aTargetFileVersion, final IR4EUIPosition aUIPosition) {
+
+		final R4EAnomaly tempAnomaly = R4EUIAnomalyContainer.createDetachedAnomaly();
+
+		if (null != tempAnomaly) {
+
+			final Job job = new Job(R4EUIAnomalyContainer.CREATE_ANOMALY_MESSAGE) {
+				public String familyName = R4EUIConstants.R4E_UI_JOB_FAMILY;
+
+				@Override
+				public boolean belongsTo(Object family) {
+					return familyName.equals(family);
+				}
+
+				@Override
+				public IStatus run(IProgressMonitor monitor) {
+					try {
+						final R4EUIReviewBasic uiReview = R4EUIModelController.getActiveReview();
+						final R4EUIReviewItem uiReviewItem = uiReview.createResourceReviewItem(aTargetFileVersion.getName());
+						if (null == uiReviewItem) {
+							return Status.CANCEL_STATUS;
+						}
+						final R4EUIFileContext uiFileContext = uiReviewItem.createFileContext(aBaseFileVersion,
+								aTargetFileVersion, null);
+						if (null == uiFileContext) {
+							uiReview.removeChildren(uiReviewItem, false);
+							return Status.CANCEL_STATUS;
+						}
+
+						final R4EUIAnomalyContainer uiAnomalyContainer = uiFileContext.getAnomalyContainerElement();
+						final R4EUIAnomalyBasic uiAnomaly = uiAnomalyContainer.createAnomalyFromDetached(
+								aTargetFileVersion, tempAnomaly, (R4EUITextPosition) aUIPosition);
+						R4EUIModelController.setJobInProgress(false);
+						UIUtils.setNavigatorViewFocus(uiAnomaly, AbstractTreeViewer.ALL_LEVELS);
+					} catch (ResourceHandlingException e) {
+						UIUtils.displayResourceErrorDialog(e);
+					} catch (OutOfSyncException e) {
+						UIUtils.displaySyncErrorDialog(e);
+					}
+					monitor.done();
+					return Status.OK_STATUS;
+				}
+			};
+			job.setUser(true);
+			job.schedule();
+		}
+	}
+}