org.eclipse.mylyn.reviews.r4e.ui.internal.utils.AnomalyUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.mylyn.reviews.r4e.ui.internal.utils.AnomalyUtils.java

Source

// $codepro.audit.disable com.instantiations.assist.eclipse.analysis.audit.rule.effectivejava.alwaysOverridetoString.alwaysOverrideToString, com.instantiations.assist.eclipse.analysis.deserializeabilitySecurity, com.instantiations.assist.eclipse.analysis.disallowReturnMutable, com.instantiations.assist.eclipse.analysis.enforceCloneableUsageSecurity
/*******************************************************************************
 * Copyright (c) 2012 Ericsson AB and others.
 * 
 * All rights reserved. This program and the accompanying materials are
 * made available under the terms of the Eclipse Public License v1.0 which
 * accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Description:
 * 
 * This class implements various utility methods used in Anomaly handling
 * 
 * Contributors:
 *   Sebastien Dubois - Created for Mylyn Review R4E project
 *   
 *******************************************************************************/

package org.eclipse.mylyn.reviews.r4e.ui.internal.utils;

import java.util.Date;
import java.util.List;

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.ITextSelection;
import org.eclipse.jface.viewers.AbstractTreeViewer;
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.IR4EUIModelElement;
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.R4EUIComment;
import org.eclipse.mylyn.reviews.r4e.ui.internal.model.R4EUIContent;
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.swt.widgets.Display;
import org.eclipse.ui.IEditorInput;

/**
 * This class implements various utility methods used in anomaly-related commands
 * 
 * @author Sebastien Dubois
 * @version $Revision: 1.0 $
 */
public class AnomalyUtils {

    // ------------------------------------------------------------------------
    // Constants
    // ------------------------------------------------------------------------

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

    /**
     * Field VERSION_STR. (value is ""Version: "")
     */
    private static final String VERSION_STR = "Version: "; //$NON-NLS-1$

    /**
     * Field QUESTION_TITLE. (value is ""R4E question"")
     */
    private static final String QUESTION_TITLE = "R4E question"; //$NON-NLS-1$

    /**
     * Field WORKSPACE_FILE_STR. (value is ""Workspace file: "")
     */
    private static final String WORKSPACE_FILE_STR = "Workspace file: "; //$NON-NLS-1$

    /**
     * Field FILE_VERSION_STR. (value is ""Selected file version to review: "")
     */
    private static final String FILE_VERSION_STR = "Selected file version to review: "; //$NON-NLS-1$

    /**
     * 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 ?"; //$NON-NLS-1$

    /**
     * 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."; //$NON-NLS-1$

    // ------------------------------------------------------------------------
    // Methods
    // ------------------------------------------------------------------------

    /**
     * Method addAnomalyFromText.
     * 
     * @param aSelection
     *            ITextSelection
     * @param aInput
     *            - IEditorInput
     */
    public static void addAnomalyFromText(ITextSelection aSelection, IEditorInput aInput, boolean aClone) {
        //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, aClone);
            } else {
                R4EUIPlugin.Ftracer.traceWarning("Trying to add review item to base file"); //$NON-NLS-1$
                final ErrorDialog dialog = new ErrorDialog(null, R4EUIConstants.DIALOG_TITLE_ERROR,
                        "Add Anomaly Error", new Status(IStatus.ERROR, R4EUIPlugin.PLUGIN_ID, 0, //$NON-NLS-1$
                                "No Target File present to Add Anomaly", null), //$NON-NLS-1$
                        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
     */
    public static void addAnomalyFromTree(Object aSelection, IProgressMonitor aMonitor, boolean aClone) {

        //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();
                } else {
                    //This should never happen
                    R4EUIPlugin.Ftracer.traceWarning("Invalid selection " + aSelection.getClass().toString() //$NON-NLS-1$
                            + ".  Ignoring"); //$NON-NLS-1$
                    return;
                }
                //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() //$NON-NLS-1$
                        + ".  Ignoring"); //$NON-NLS-1$
                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()); //$NON-NLS-1$
                addAnomaly(baseVersion, targetVersion, position, aClone);
                aMonitor.worked(1);
            } else {
                R4EUIPlugin.Ftracer.traceWarning("Trying to add review item to base file"); //$NON-NLS-1$
                final ErrorDialog dialog = new ErrorDialog(null, R4EUIConstants.DIALOG_TITLE_ERROR,
                        "Add Anomaly Error", new Status(IStatus.ERROR, R4EUIPlugin.PLUGIN_ID, 0, //$NON-NLS-1$
                                "No Target File present to Add Anomaly", null), //$NON-NLS-1$
                        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
     */
    public static void addAnomaly(R4EFileVersion aBaseFileVersion, final R4EFileVersion aTargetFileVersion,
            IR4EUIPosition aUIPosition, final boolean aClone) {

        R4EUIFileContext tempFileContext = null;
        //Find the latest commit for the selected target file
        //Check if the file element and/or anomaly already exist
        //If so, verify if the anomaly exist
        //If not, then add anomaly element to the target file
        //If anomaly element already exist, then add a new comment to it
        //for all other cases, create the parent elements as needed as well.
        //If the target file is not the same file version in any commit, 
        //Look for the file name (No version) exist in the workspace
        //If found, then ask the user to continue or cancel the adding of the anomaly
        final List<R4EUIReviewItem> reviewItems = R4EUIModelController.getActiveReview().getReviewItems();

        //Select the latest commit to store the anomaly
        Date date1 = null;
        Date datelatest = null;
        R4EUIAnomalyContainer anomalyContainer = null;
        R4EUIFileContext file = null;
        for (R4EUIReviewItem reviewItem : reviewItems) {
            R4EUIFileContext[] files = (R4EUIFileContext[]) reviewItem.getChildren();
            for (R4EUIFileContext selectedFile : files) {
                if (null != selectedFile.getFileContext().getTarget() && aTargetFileVersion.getLocalVersionID()
                        .equals(selectedFile.getFileContext().getTarget().getLocalVersionID())) {

                    //Initial setting
                    if (file == null && selectedFile.getAnomalyContainerElement() != null) {
                        //Set the anomaly container
                        file = selectedFile;
                        datelatest = reviewItem.getItem().getSubmitted();
                    }

                    //Set the date based on the current commit
                    date1 = reviewItem.getItem().getSubmitted();

                    if (date1 != null) { //Can be null for the review item as a resource
                        //Test for the latest commit up to now
                        if (datelatest == null || datelatest.before(date1)) {
                            datelatest = date1;
                            file = selectedFile;
                        }
                    }
                }
            }
        }

        if (null != file) {
            anomalyContainer = file.getAnomalyContainerElement();

            addAnomalyToExistingFileContext(file, anomalyContainer, aUIPosition, aClone);
            R4EUIPlugin.Ftracer.traceInfo("Added anomaly: Target = " //$NON-NLS-1$
                    + file.getFileContext().getTarget().getName()
                    + ((null != file.getFileContext().getBase()) ? "Base = " //$NON-NLS-1$
                            + file.getFileContext().getBase().getName() : "") //$NON-NLS-1$
                    + " Position = " //$NON-NLS-1$
                    + aUIPosition.toString());

            return; //We found the file so we are done here   
        } else {

            //Did not find the same file version, look for the same file with different version
            String targetPlatformURI = aTargetFileVersion.getPlatformURI();
            String targetPlatformPath = aTargetFileVersion.getRepositoryPath();

            //Look if the file exist in the workspace
            if (null != targetPlatformURI) {
                for (R4EUIReviewItem reviewItem : reviewItems) {
                    R4EUIFileContext[] files = (R4EUIFileContext[]) reviewItem.getChildren();
                    for (R4EUIFileContext searchFile : files) {
                        if (null != searchFile.getFileContext().getTarget()) {
                            //Test if we find the file in the workspace
                            String reviewPlatformURI = searchFile.getFileContext().getTarget().getPlatformURI();
                            String reviewPlatformPath = searchFile.getFileContext().getTarget().getRepositoryPath();
                            if (null != reviewPlatformURI) {
                                //Now we can compare the path
                                if (reviewPlatformURI.equals(targetPlatformURI)) {
                                    //Found the same file but not the same version
                                    tempFileContext = searchFile;
                                }
                            } else if (null != reviewPlatformPath) {
                                //Test the repository path
                                //Now we can compare the path
                                if (reviewPlatformPath.equals(targetPlatformPath)) {
                                    //Found the same file but not the same version
                                    tempFileContext = searchFile;
                                }
                            }
                        }
                    }
                }
            }

            //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 R4EUIFileContext dContext = tempFileContext;
                if (!UIUtils.TEST_MODE) {
                    Display.getDefault().syncExec(new Runnable() {
                        public void run() {
                            final MessageDialog dialog = displayDifferentFileVersionDialog(aTargetFileVersion,
                                    dContext);
                            result[0] = dialog.open();
                        }
                    });
                } else {
                    result[0] = Window.OK;
                }
                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, aClone);
            R4EUIPlugin.Ftracer.traceInfo("Added Anomaly: Target = " //$NON-NLS-1$
                    + aTargetFileVersion.getName() + "_" //$NON-NLS-1$
                    + aTargetFileVersion.getVersionID() + ((null != aBaseFileVersion)
                            ? "Base = " + aBaseFileVersion.getName() + "_" //$NON-NLS-1$//$NON-NLS-2$
                                    + aBaseFileVersion.getVersionID()
                            : "") //$NON-NLS-1$
                    + " Position = " + aUIPosition.toString()); //$NON-NLS-1$
        }

    }

    /**
     * Method displayDifferentFileVersionDialog.
     * 
     * @param aTargetFileVersion
     *            R4EFileVersion
     * @param aTempFileContext
     *            R4EUIFileContext
     * @return MessageDialog
     */
    private static 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 addAnomalyToExistingFileContext.
     * 
     * @param aTargetFile
     *            R4EUIFileContext
     * @param aContainer
     *            R4EUIAnomalyContainer
     * @param aUIPosition
     *            IR4EUIPosition
     * @param aClone
     *            - boolean
     */
    private static void addAnomalyToExistingFileContext(R4EUIFileContext aTargetFile,
            R4EUIAnomalyContainer aContainer, IR4EUIPosition aUIPosition, boolean aClone) {
        aContainer.createAnomaly(aTargetFile, (R4EUITextPosition) aUIPosition, aClone);
    }

    /**
     * Method addAnomalyToNewFileContext.
     * 
     * @param aBaseFileVersion
     *            R4EFileVersion
     * @param aTargetFileVersion
     *            R4EFileVersion
     * @param aUIPosition
     *            IR4EUIPosition
     */
    private static void addAnomalyToNewFileContext(final R4EFileVersion aBaseFileVersion,
            final R4EFileVersion aTargetFileVersion, final IR4EUIPosition aUIPosition, final boolean aClone) {

        final R4EAnomaly tempAnomaly = R4EUIAnomalyContainer.createDetachedAnomaly(aClone);

        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, false);
                        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();
        }
    }

    /**
     * Method isAnomalyExist.
     * 
     * @param aFile
     *            R4EUIFileContext
     * @param aNewUiAnomaly
     *            R4EUIAnomalyBasic
     * @return String - the name of the existing anomaly or null if none
     */
    public static String isAnomalyExist(R4EUIFileContext aFile, IR4EUIPosition aNewAnomalyPosition,
            String aNewAnomalyDescription) {
        //Check if the same anomaly as the one to be added already exists
        R4EUIAnomalyContainer anomalyContainer = aFile.getAnomalyContainerElement();
        R4EUIAnomalyBasic[] existingAnomalies = (R4EUIAnomalyBasic[]) anomalyContainer.getChildren();
        for (R4EUIAnomalyBasic uiAnomaly : existingAnomalies) {
            if (uiAnomaly.getPosition().isSameAs(aNewAnomalyPosition)
                    && uiAnomaly.getAnomaly().getDescription().equals(aNewAnomalyDescription)) {
                return aNewAnomalyDescription;
            }
        }
        return null;
    }

    /**
     * Method isCommentExist.
     * 
     * @param aAnomaly
     *            R4EUIAnomalyBasic
     * @param String
     *            aNewCommentDescription
     * @return String - the description of the existing comment or null if none
     */
    public static String isCommentExist(R4EUIAnomalyBasic aAnomaly, String aNewCommentDescription) {
        //Check if the same anomaly as the one to be added already exists
        IR4EUIModelElement[] existingUiComments = aAnomaly.getChildren();
        for (IR4EUIModelElement uiComment : existingUiComments) {
            if (((R4EUIComment) uiComment).getComment().getDescription().equals(aNewCommentDescription)) {
                return aNewCommentDescription;
            }
        }
        return null;
    }

    /**
     * Method cloneLinkedAnomaly.
     * 
     * @param aElement
     *            R4EUIContent
     * @throws OutOfSyncException
     * @throws ResourceHandlingException
     */
    public static void cloneLinkedAnomaly(R4EUIContent aTargetContent, R4EUIAnomalyBasic aSourceAnomaly)
            throws ResourceHandlingException, OutOfSyncException {
        final R4EUIFileContext fileContext = (R4EUIFileContext) aTargetContent.getParent().getParent();
        final R4EUIAnomalyContainer container = (fileContext.getAnomalyContainerElement());
        R4EUIAnomalyBasic newUiAnomaly = container.createAnomalyFromDetached(fileContext.getTargetFileVersion(),
                aSourceAnomaly.getAnomaly(), (R4EUITextPosition) aTargetContent.getPosition(), true);
        UIUtils.setNavigatorViewFocus(newUiAnomaly, AbstractTreeViewer.ALL_LEVELS);
    }
}