blob: b3ebb773d7106fbe1271956e02c38cfb934172c0 [file] [log] [blame]
// $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) 2010, 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
*
* Contributors:
* Ericsson AB - initial API and implementation
*******************************************************************************/
package org.eclipse.mylyn.reviews.r4e.ui.internal.utils;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.compare.CompareConfiguration;
import org.eclipse.compare.ITypedElement;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IStorage;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.util.EList;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.ISourceRange;
import org.eclipse.jdt.core.ISourceReference;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.mylyn.reviews.frame.core.model.Location;
import org.eclipse.mylyn.reviews.frame.core.utils.Tracer;
import org.eclipse.mylyn.reviews.r4e.core.model.R4EAnomaly;
import org.eclipse.mylyn.reviews.r4e.core.model.R4EAnomalyTextPosition;
import org.eclipse.mylyn.reviews.r4e.core.model.R4EComment;
import org.eclipse.mylyn.reviews.r4e.core.model.R4ECommentType;
import org.eclipse.mylyn.reviews.r4e.core.model.R4EContent;
import org.eclipse.mylyn.reviews.r4e.core.model.R4EContextType;
import org.eclipse.mylyn.reviews.r4e.core.model.R4EFileVersion;
import org.eclipse.mylyn.reviews.r4e.core.model.R4EParticipant;
import org.eclipse.mylyn.reviews.r4e.core.model.R4EReview;
import org.eclipse.mylyn.reviews.r4e.core.model.R4EUser;
import org.eclipse.mylyn.reviews.r4e.core.model.R4EUserRole;
import org.eclipse.mylyn.reviews.r4e.core.model.RModelFactory;
import org.eclipse.mylyn.reviews.r4e.core.model.serial.impl.CompatibilityException;
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.IRFSRegistry;
import org.eclipse.mylyn.reviews.r4e.core.rfs.spi.RFSRegistryFactory;
import org.eclipse.mylyn.reviews.r4e.core.rfs.spi.ReviewsFileStorageException;
import org.eclipse.mylyn.reviews.r4e.core.utils.ResourceUtils;
import org.eclipse.mylyn.reviews.r4e.ui.R4EUIPlugin;
import org.eclipse.mylyn.reviews.r4e.ui.internal.editors.R4ECompareEditorInput;
import org.eclipse.mylyn.reviews.r4e.ui.internal.editors.R4EFileEditorInput;
import org.eclipse.mylyn.reviews.r4e.ui.internal.editors.R4EFileRevisionEditorInput;
import org.eclipse.mylyn.reviews.r4e.ui.internal.editors.R4EFileRevisionTypedElement;
import org.eclipse.mylyn.reviews.r4e.ui.internal.editors.R4EFileTypedElement;
import org.eclipse.mylyn.reviews.r4e.ui.internal.model.IR4EUIModelElement;
import org.eclipse.mylyn.reviews.r4e.ui.internal.model.R4EUIModelController;
import org.eclipse.mylyn.reviews.r4e.ui.internal.model.R4EUIPostponedAnomalyContainer;
import org.eclipse.mylyn.reviews.r4e.ui.internal.model.R4EUIPostponedContainer;
import org.eclipse.mylyn.reviews.r4e.ui.internal.model.R4EUIPostponedFile;
import org.eclipse.mylyn.reviews.r4e.ui.internal.model.R4EUIReviewBasic;
import org.eclipse.mylyn.reviews.r4e.ui.internal.model.R4EUITextPosition;
import org.eclipse.mylyn.versions.core.ChangeType;
import org.eclipse.mylyn.versions.core.ScmArtifact;
import org.eclipse.mylyn.versions.core.ScmCore;
import org.eclipse.mylyn.versions.core.spi.ScmConnector;
import org.eclipse.swt.widgets.Display;
import org.eclipse.team.core.history.IFileRevision;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IFileEditorInput;
/**
* This class implements various utility methods used in the context- sensitive commands
*
* @author Sebastien Dubois
* @version $Revision: 1.0 $
*/
public class CommandUtils {
// ------------------------------------------------------------------------
// Constants
// ------------------------------------------------------------------------
/**
* Field NO_SOURCE_CONTROL_ID_TEXT. (value is ""(Version not in Source Control)"")
*/
private static final String NO_SOURCE_CONTROL_ID_TEXT = "(Version not in Source Control)";
/**
* Field INVALID_PATH. (value is ""/dev/null"")
*/
private static final String INVALID_PATH = "/dev/null";
// ------------------------------------------------------------------------
// Methods
// ------------------------------------------------------------------------
/**
* Method getTargetFileURI.
*
* @param aInput
* - IEditorInput
* @return URI
* @throws URISyntaxException
* @throws CoreException
* @throws ReviewsFileStorageException
*/
public static R4EFileVersion getTargetFileData(IEditorInput aInput) throws CoreException,
ReviewsFileStorageException {
IFile editorFile = null; //The file we use in the current editor/workspace
if (aInput instanceof IFileEditorInput) {
editorFile = ((IFileEditorInput) aInput).getFile();
//Now we have the file in editor, we need to use the versions interface to see if we should copy it
//to the local repo and update model info
if (null == editorFile) {
return null;
}
return updateTargetFile(editorFile);
} else if (aInput instanceof R4ECompareEditorInput) {
//If we get here, this is because we are trying to act on the compare editor contents
//this means that the file we are acting on is already in the local repository
//in this case, we only need to provide the versionId of this file
final ITypedElement element = ((R4ECompareEditorInput) aInput).getLeftElement();
if (element instanceof R4EFileRevisionTypedElement) {
return ((R4EFileRevisionTypedElement) element).getFileVersion();
} else if (element instanceof R4EFileTypedElement) {
return ((R4EFileTypedElement) element).getFileVersion();
} else {
return null;
}
} else if (aInput instanceof R4EFileRevisionEditorInput) {
return ((R4EFileRevisionEditorInput) aInput).getFileVersion();
} else if (aInput instanceof R4EFileEditorInput) {
return ((R4EFileEditorInput) aInput).getFileVersion();
} else {
//Should never happen
throw new CoreException(new Status(IStatus.ERROR, R4EUIPlugin.PLUGIN_ID, IStatus.OK, "Invalid input "
+ ((null != aInput) ? aInput.getClass().toString() : ""), null));
}
}
/**
* Method updateTargetFile.
*
* @param aFile
* IFile
* @return IFile
* @throws CoreException
* @throws ReviewsFileStorageException
*/
public static R4EFileVersion updateTargetFile(IFile aFile) throws CoreException, ReviewsFileStorageException {
if (null == aFile) {
return null; //should never happen
}
String remoteID = null;
String localID = null;
// Get handle to local storage repository
final IRFSRegistry localRepository = RFSRegistryFactory.getRegistry(R4EUIModelController.getActiveReview()
.getReview());
if (null == localRepository) {
return null;
}
//Get Remote repository file info
final ScmConnector connector = ScmCore.getConnector(aFile.getProject());
if (null != connector) {
final ScmArtifact artifact = connector.getArtifact(aFile);
if ((null != artifact) && (null != artifact.getPath())) {
//File found in remote repo.
//Here we check if the file in the remote repository is different than the input file.
//We cannot use the artifact ID directly and we need to fetch and calculate that SHA of the remote file
//because we do not know which version control system is used.
//We need to do this comparison because the versions always return the latest file stored.
final IFileRevision fileRev = artifact.getFileRevision(null);
if (null != fileRev) {
final IStorage fileStore = fileRev.getStorage(null);
if (null != fileStore) {
remoteID = localRepository.blobIdFor(fileStore.getContents());
localID = localRepository.blobIdFor(aFile.getContents());
if ((null != remoteID) && remoteID.equals(localID)) {
//The files are the same. Copy from the remote repo
return copyRemoteFileToLocalRepository(localRepository, artifact);
}
}
}
//The files are different. This means the current user modified the file in his workspace
return copyWorkspaceFileToLocalRepository(localRepository, aFile);
}
}
//Else we copy the file that is in the current workspace
return copyWorkspaceFileToLocalRepository(localRepository, aFile);
}
/**
* Method getBaseFileURI.
*
* @param aInput
* - IEditorInput
* @return IFile
* @throws URISyntaxException
* @throws CoreException
* @throws ReviewsFileStorageException
*/
public static R4EFileVersion getBaseFileData(IEditorInput aInput) throws CoreException, ReviewsFileStorageException {
/* final IEditorInput input = PlatformUI.getWorkbench()
.getActiveWorkbenchWindow()
.getActivePage()
.getActiveEditor()
.getEditorInput(); // $codepro.audit.disable methodChainLength
*/ IFile editorFile = null; //The file we use in the current editor/workspace
if (aInput instanceof IFileEditorInput) {
editorFile = ((IFileEditorInput) aInput).getFile();
//Now we have the file in editor, we need to use the versions interface to see if we should copy it
//to the local repo and update model info
return updateBaseFile(editorFile);
} else if (aInput instanceof R4ECompareEditorInput) {
//If we get here, this is because we are trying to act on the compare editor contents
//We have three cases:
//1) The left file is an R4EFileTypedElement and had no version ID. This means that it is a modified file not yet in source control.
// In this case, the base file is the version that is in source control i.e. the right file version (if it is in source control).
//2) The left file is an R4EFileTypedElement and had a version ID. This means that it is file in source control in sync with the workspace.
// In this case, the base file for the new Resource Review item should be the same as the target file i.e. the left file version
//3) The left file is an R4EFileRevisionTypedElement. This means that it is a file in source control.
// In this case, the base file for the new Resource Review item should be the same as the target file i.e. the left file version
final ITypedElement leftElement = ((R4ECompareEditorInput) aInput).getLeftElement();
final ITypedElement rightElement = ((R4ECompareEditorInput) aInput).getRightElement();
if (leftElement instanceof R4EFileTypedElement && rightElement instanceof R4EFileRevisionTypedElement) {
if (((R4EFileTypedElement) leftElement).getFileVersion()
.getVersionID()
.equals(NO_SOURCE_CONTROL_ID_TEXT)) {
return ((R4EFileRevisionTypedElement) rightElement).getFileVersion();
} else {
return ((R4EFileTypedElement) leftElement).getFileVersion();
}
} else if (leftElement instanceof R4EFileRevisionTypedElement) {
return ((R4EFileRevisionTypedElement) leftElement).getFileVersion();
} else {
return null;
}
} else if (aInput instanceof R4EFileRevisionEditorInput) {
return ((R4EFileRevisionEditorInput) aInput).getFileVersion();
} else if (aInput instanceof R4EFileEditorInput) {
return ((R4EFileEditorInput) aInput).getFileVersion();
} else {
//Should never happen
throw new CoreException(new Status(IStatus.ERROR, R4EUIPlugin.PLUGIN_ID, IStatus.OK, "Invalid input "
+ ((null != aInput) ? aInput.getClass().toString() : ""), null));
}
}
/**
* Method updateBaseFile.
*
* @param aFile
* IFile
* @return IFile
* @throws CoreException
* @throws ReviewsFileStorageException
*/
public static R4EFileVersion updateBaseFile(IFile aFile) throws CoreException, ReviewsFileStorageException {
if (null == aFile) {
return null; //should never happen
}
//Get Remote repository file info
final ScmConnector connector = ScmCore.getConnector(aFile.getProject());
if (null != connector) {
final ScmArtifact artifact = connector.getArtifact(aFile);
if ((null != artifact) && (null != artifact.getId())) {
//File was modified, so we need to fetch the base file from the versions repository and copy it to our own local repository
final IRFSRegistry localRepository = RFSRegistryFactory.getRegistry(R4EUIModelController.getActiveReview()
.getReview());
return copyRemoteFileToLocalRepository(localRepository, artifact);
}
} //else file not in source control
//File was not modified, or No Version Control System or Remote File detected, so there is no base
return null;
}
/**
* Method copyRemoteFileToLocalRepository.
*
* @param aLocalRepository
* IRFSRegistry
* @param aArtifact
* ScmArtifact
* @return IFile
* @throws CoreException
* @throws ReviewsFileStorageException
*/
public static R4EFileVersion copyRemoteFileToLocalRepository(IRFSRegistry aLocalRepository, ScmArtifact aArtifact)
throws ReviewsFileStorageException, CoreException {
if ((null == aArtifact) || (null == aArtifact.getPath()) || aArtifact.getPath().equals(INVALID_PATH)) {
return null; //File not found in remote repository
}
final IFileRevision fileRev = aArtifact.getFileRevision(null);
if (null == fileRev) {
return null;
}
// Pull file from the version control system
InputStream iStream = null;
final IStorage fileStore = fileRev.getStorage(null);
if (null == fileStore) {
return null;
}
try {
iStream = fileStore.getContents();
} catch (CoreException e) {
R4EUIPlugin.Ftracer.traceInfo("Exception: " + e.toString() + " (" + e.getMessage() + ")");
return null;
}
//Create and Set value in temporary File version
final R4EFileVersion tmpFileVersion = RModelFactory.eINSTANCE.createR4EFileVersion();
if ((null != tmpFileVersion) && (null != aLocalRepository)) {
updateFileVersion(tmpFileVersion, aArtifact);
// Push a local copy to local review repository, and obtain the local id
tmpFileVersion.setLocalVersionID(aLocalRepository.registerReviewBlob(iStream));
if (null != iStream) {
try {
iStream.close();
} catch (IOException e) {
R4EUIPlugin.Ftracer.traceWarning("Exception while closing stream, " + e.toString());
}
}
}
return tmpFileVersion;
}
/**
* Method copyRemoteFileToLocalRepository.
*
* @param aLock
* ReentrantLock
* @param aLocalRepository
* IRFSRegistry
* @param aArtifact
* ScmArtifact
* @param aMainMonitor
* IProgressMonitor
* @param aSubMonitor
* IProgressMonitor
* @return IFile
* @throws CoreException
* @throws ReviewsFileStorageException
* @throws MainJobCancelledException
* @throws SubJobCancelledException
*/
public static R4EFileVersion copyRemoteFileToLocalRepository(ReentrantLock aLock, IRFSRegistry aLocalRepository,
ScmArtifact aArtifact, IProgressMonitor aMainMonitor) throws ReviewsFileStorageException, CoreException {
ReentrantLock lock = aLock;
if (null == lock) {
lock = new ReentrantLock();
}
//Check if Main Job or Sub Job was cancelled before fetching
if (aMainMonitor.isCanceled()) {
throw new CoreException(new Status(IStatus.CANCEL, R4EUIPlugin.PLUGIN_ID, IStatus.CANCEL,
R4EUIConstants.CANCEL_EXCEPTION_MSG, null));
}
if ((null == aArtifact) || (null == aArtifact.getPath()) || aArtifact.getPath().equals(INVALID_PATH)) {
return null; //File not found in remote repository
}
//Tracing benchmarks
Date fetchStart = null;
if (Tracer.isInfo()) {
fetchStart = new Date();
}
final IFileRevision fileRev = aArtifact.getFileRevision(null);
if (null == fileRev) {
return null;
}
// Pull file from the version control system
InputStream iStream = null;
final IStorage fileStore = fileRev.getStorage(null);
if (null == fileStore) {
return null;
}
try {
iStream = fileStore.getContents();
} catch (CoreException e) {
R4EUIPlugin.Ftracer.traceInfo("Exception: " + e.toString() + " (" + e.getMessage() + ")");
return null;
}
//Create and Set value in temporary File version
final R4EFileVersion tmpFileVersion = RModelFactory.eINSTANCE.createR4EFileVersion();
if ((null != tmpFileVersion) && (null != aLocalRepository)) {
updateFileVersion(tmpFileVersion, aArtifact);
//Check if Main Job or Sub Job was cancelled before pushing a local copy
if (aMainMonitor.isCanceled()) {
throw new CoreException(new Status(IStatus.CANCEL, R4EUIPlugin.PLUGIN_ID, IStatus.CANCEL,
R4EUIConstants.CANCEL_EXCEPTION_MSG, null));
}
//Tracing benchmarks
Date blobRegStart = null;
if (fetchStart != null) {
blobRegStart = new Date();
}
// Push a local copy to local review repository, and obtain the local id
lock.lock();
try {
tmpFileVersion.setLocalVersionID(aLocalRepository.registerReviewBlob(iStream));
} finally {
lock.unlock();
if (fetchStart != null) {
long downloadTime = blobRegStart.getTime() - fetchStart.getTime();
long uploadTime = (new Date()).getTime() - blobRegStart.getTime();
R4EUIPlugin.Ftracer.traceInfo("Registered blob for " + fileRev.getName() + " " + //$NON-NLS-1$//$NON-NLS-2$
aArtifact.getId() + ", fetch (ms): " + downloadTime + ", push (ms) " + uploadTime); //$NON-NLS-1$ //$NON-NLS-2$
}
if (null != iStream) {
try {
iStream.close();
} catch (IOException e) {
R4EUIPlugin.Ftracer.traceWarning("Exception while closing stream, " + e.toString());
}
}
}
}
return tmpFileVersion;
}
/**
* Method copyWorkspaceFileToLocalRepository.
*
* @param aLocalRepository
* IRFSRegistry
* @param aFile
* IFile
* @return IFile
* @throws CoreException
* @throws ReviewsFileStorageException
*/
public static R4EFileVersion copyWorkspaceFileToLocalRepository(IRFSRegistry aLocalRepository, IFile aFile)
throws CoreException, ReviewsFileStorageException {
R4EFileVersion tmpFileVersion = null;
if ((null != aLocalRepository) && (null != aFile)) {
//Create and Set value in temporary File version
tmpFileVersion = RModelFactory.eINSTANCE.createR4EFileVersion();
if ((null != tmpFileVersion)) {
updateFileVersion(tmpFileVersion, aFile);
// Push a local copy to local review repository, and obtain the local id
tmpFileVersion.setLocalVersionID(aLocalRepository.registerReviewBlob(aFile.getContents()));
tmpFileVersion.setVersionID(NO_SOURCE_CONTROL_ID_TEXT);
}
}
return tmpFileVersion;
}
/**
* Method getPosition.
*
* @param aSelection
* ITextSelection
* @return TextPosition
*/
public static R4EUITextPosition getPosition(ITextSelection aSelection) {
if (null == aSelection) {
return null;
}
return new R4EUITextPosition(aSelection.getOffset(), (aSelection).getLength(), (aSelection).getStartLine(),
(aSelection).getEndLine());
}
/**
* Method getPosition. Get position based on position in Document
*
* @param aOffset
* int
* @param aLength
* int
* @param aDoc
* IDocument
* @return R4EUITextPosition
*/
public static R4EUITextPosition getPosition(int aOffset, int aLength, IDocument aDoc) { // $codepro.audit.disable overloadedMethods
final R4EUITextPosition position = new R4EUITextPosition(aOffset, aLength, aDoc);
return position;
}
/**
* Method getPosition. Get position for generic workspace files
*
* @param aSelectedElement
* IFile
* @return TextPosition
* @throws CoreException
*/
public static R4EUITextPosition getPosition(IFile aSelectedElement) throws CoreException { // $codepro.audit.disable overloadedMethods
if (null == aSelectedElement) {
return null;
}
final R4EUITextPosition position = new R4EUITextPosition(R4EUIConstants.NO_OFFSET,
R4EUIConstants.INVALID_VALUE, aSelectedElement);
position.setName(aSelectedElement.getName());
return position;
}
/**
* Method getPosition. Get position for workspace java source files
*
* @param aSelectedElement
* ISourceReference
* @param aFile
* IFile
* @return TextPosition
* @throws CoreException
*/
public static R4EUITextPosition getPosition(ISourceReference aSelectedElement, IFile aFile) throws CoreException {
int offset = 0;
int length = 0;
String name = "";
if (null != aSelectedElement) {
final ISourceRange sourceRange = aSelectedElement.getSourceRange();
if (null != sourceRange) {
offset = sourceRange.getOffset();
length = sourceRange.getLength();
}
name = ((IJavaElement) aSelectedElement).getElementName();
}
final R4EUITextPosition position = new R4EUITextPosition(offset, length, aFile);
position.setName(name);
return position;
}
/**
* Method getPosition. Get position for workspace C and C++ source files
*
* @param aSelectedElement
* org.eclipse.cdt.core.model.ISourceReference
* @param aFile
* IFile
* @return TextPosition
* @throws CoreException
*/
public static R4EUITextPosition getPosition(org.eclipse.cdt.core.model.ISourceReference aSelectedElement,
IFile aFile) // $codepro.audit.disable overloadedMethods
throws CoreException {
int startPos = 0;
int length = 0;
int startLine = 0;
int endLine = 0;
String name = "";
if (null != aSelectedElement) {
final org.eclipse.cdt.core.model.ISourceRange sourceRange = aSelectedElement.getSourceRange();
if (null != sourceRange) {
startPos = sourceRange.getStartPos();
length = sourceRange.getLength();
startLine = sourceRange.getStartLine();
endLine = sourceRange.getEndLine();
}
name = ((org.eclipse.cdt.core.model.ICElement) aSelectedElement).getElementName();
}
final R4EUITextPosition position = new R4EUITextPosition(startPos, length, aFile);
position.setStartLine(startLine);
position.setEndLine(endLine);
position.setName(name);
return position;
}
/**
* Adapt change types from Mylyn Versions to R4E model
*
* @param aChangeType
* ChangeType
* @return R4EContextType
*/
public static R4EContextType adaptType(ChangeType aChangeType) {
R4EContextType dtype = null;
switch (aChangeType) {
case ADDED:
dtype = R4EContextType.R4E_ADDED;
break;
case DELETED:
dtype = R4EContextType.R4E_DELETED;
break;
case MODIFIED:
dtype = R4EContextType.R4E_MODIFIED;
break;
case REPLACED:
dtype = R4EContextType.R4E_REPLACED;
break;
default:
break;
}
return dtype;
}
/**
* Resolve and transfer values from ScmArtifact to R4EFileVersion
*
* @param aTargetFileVer
* R4EFileVersion
* @param aSourceFileVer
* R4EFileVersion
*/
public static void copyFileVersionData(R4EFileVersion aTargetFileVer, R4EFileVersion aSourceFileVer) {
if ((null != aTargetFileVer) && (null != aSourceFileVer)) {
aTargetFileVer.setName(aSourceFileVer.getName());
aTargetFileVer.setVersionID(aSourceFileVer.getVersionID());
aTargetFileVer.setRepositoryPath(aSourceFileVer.getRepositoryPath());
aTargetFileVer.setLocalVersionID(aSourceFileVer.getLocalVersionID());
aTargetFileVer.setPlatformURI(aSourceFileVer.getPlatformURI());
aTargetFileVer.setResource(aSourceFileVer.getResource());
}
}
/**
* Method updateFileVersion
*
* @param aTargetFileVer
* R4EFileVersion
* @param aScmArt
* ScmArtifact
* @throws CoreException
*/
public static void updateFileVersion(R4EFileVersion aTargetFileVer, ScmArtifact aScmArt) throws CoreException {
if ((null != aTargetFileVer) && (null != aScmArt)) {
aTargetFileVer.setName(aScmArt.getFileRevision(null).getName());
aTargetFileVer.setVersionID(aScmArt.getId());
final IFileRevision fileRev = aScmArt.getFileRevision(null);
if (null != fileRev) {
final IStorage fileStore = fileRev.getStorage(null);
if (null != fileStore) {
final IPath filePath = fileStore.getFullPath();
if (null != filePath) {
aTargetFileVer.setRepositoryPath(filePath.toPortableString());
}
}
}
final String fileRelPath = aScmArt.getProjectRelativePath();
if (null == fileRelPath) {
R4EUIPlugin.Ftracer.traceDebug("Invalid relative file path in scmArtifact with path: "
+ aScmArt.getPath());
}
final IProject project = ResourceUtils.getProject(aScmArt.getProjectName());
final IResource resource = ResourceUtils.findResource(project, fileRelPath);
aTargetFileVer.setPlatformURI(ResourceUtils.toPlatformURIStr(resource));
aTargetFileVer.setResource(resource);
final String projPlatformURI = ResourceUtils.toPlatformURIStr(project);
if (null == projPlatformURI) {
R4EUIPlugin.Ftracer.traceDebug("Unable to resolve the project: " + aScmArt.getProjectName()
+ " platform's URI, in scmArtifact with path: " + aScmArt.getPath());
}
}
}
/**
* Method updateFileVersion
*
* @param aTargetFileVer
* R4EFileVersion
* @param aSrcFile
* IFile
*/
public static void updateFileVersion(R4EFileVersion aTargetFileVer, IFile aSrcFile) {
if ((null != aTargetFileVer) && (null != aSrcFile)) {
aTargetFileVer.setName(aSrcFile.getName());
aTargetFileVer.setRepositoryPath(""); //No repositories for workspace files since they are not in source control
aTargetFileVer.setResource(aSrcFile);
aTargetFileVer.setPlatformURI(ResourceUtils.toPlatformURIStr(aSrcFile));
}
}
/**
* Method useWorkspaceResource.
*
* @param aVersion
* R4EFileVersion
* @return boolean
*/
public static boolean useWorkspaceResource(R4EFileVersion aVersion) {
// Get handle to local storage repository
try {
if (null != R4EUIModelController.getActiveReview()) {
final IRFSRegistry localRepository = RFSRegistryFactory.getRegistry(R4EUIModelController.getActiveReview()
.getReview());
if (null != localRepository) {
//If resource is available in the workspace, use it. Otherwise use the local repo version
if ((null != aVersion) && (null != aVersion.getResource())) {
final String workspaceFileId = localRepository.blobIdFor(((IFile) aVersion.getResource()).getContents());
final String repoFileId = aVersion.getLocalVersionID();
if ((null != workspaceFileId) && workspaceFileId.equals((repoFileId))) {
return true;
}
}
}
}
} catch (ReviewsFileStorageException e) {
R4EUIPlugin.Ftracer.traceWarning("Exception: " + e.toString() + " (" + e.getMessage() + ")");
} catch (CoreException e) {
R4EUIPlugin.Ftracer.traceWarning("Exception: " + e.toString() + " (" + e.getMessage() + ")");
}
return false;
}
/**
* Method createCompareEditorInput.
*
* @param aBaseFileVersion
* R4EFileVersion
* @param aTargetFileVersion
* R4EFileVersion
* @return R4ECompareEditorInput
*/
public static R4ECompareEditorInput createCompareEditorInput(R4EFileVersion aBaseFileVersion,
R4EFileVersion aTargetFileVersion) {
final CompareConfiguration config = new CompareConfiguration();
config.setRightEditable(false);
config.setProperty(CompareConfiguration.IGNORE_WHITESPACE, Boolean.valueOf(true));
//NOTE: We use the workspace file as input if it is in sync with the file to review,
// otherwise we use the file to review that is included in the review repository.
// Only workspace files are editable.
final R4EFileRevisionTypedElement ancestor = null; //Might be improved later
ITypedElement target = null;
if (null != aTargetFileVersion) {
if (CommandUtils.useWorkspaceResource(aTargetFileVersion)) {
target = new R4EFileTypedElement(aTargetFileVersion);
config.setLeftEditable(true);
} else {
target = new R4EFileRevisionTypedElement(aTargetFileVersion);
config.setLeftEditable(false);
}
}
ITypedElement base = null;
if (null != aBaseFileVersion) {
if (CommandUtils.useWorkspaceResource(aBaseFileVersion)) {
base = new R4EFileTypedElement(aBaseFileVersion);
config.setRightEditable(true);
} else {
base = new R4EFileRevisionTypedElement(aBaseFileVersion);
config.setRightEditable(false);
}
}
return new R4ECompareEditorInput(config, ancestor, target, base);
}
/**
* Method getAnomalyPosition.
*
* @param aAnomaly
* R4EAnomaly
* @return R4EAnomalyTextPosition
*/
public static R4EAnomalyTextPosition getAnomalyPosition(R4EAnomaly aAnomaly) {
if (null != aAnomaly) {
final EList<Location> location = aAnomaly.getLocation();
if ((null != location) && (location.size() > 0)) {
final R4EContent content = (R4EContent) location.get(0); //look at first location only
if (null != content) {
final R4EAnomalyTextPosition position = (R4EAnomalyTextPosition) content.getLocation();
return position;
}
}
}
return null;
}
/**
* Method getAnomalyParentFile.
*
* @param aAnomaly
* R4EAnomaly
* @return R4EFileVersion
*/
public static R4EFileVersion getAnomalyParentFile(R4EAnomaly aAnomaly) {
if (null != aAnomaly) {
final EList<Location> location = aAnomaly.getLocation();
if ((null != location) && (location.size() > 0)) {
final R4EContent content = (R4EContent) location.get(0); //look at first location only
if (null != content) {
final R4EAnomalyTextPosition position = (R4EAnomalyTextPosition) content.getLocation();
if (null != position) {
return position.getFile();
}
}
}
}
return null;
}
/**
* Method copyAnomalyData.
*
* @param aTargetAnomaly
* R4EAnomaly
* @param aSourceAnomaly
* R4EAnomaly
* @throws ResourceHandlingException
* @throws OutOfSyncException
*/
public static void copyAnomalyData(R4EAnomaly aTargetAnomaly, R4EAnomaly aSourceAnomaly)
throws ResourceHandlingException, OutOfSyncException {
if ((null != aTargetAnomaly) && (null != aSourceAnomaly)) {
final Long bookNum = R4EUIModelController.FResourceUpdater.checkOut(aTargetAnomaly,
R4EUIModelController.getReviewer());
//Data copied unconditionally
aTargetAnomaly.setCreatedOn(aSourceAnomaly.getCreatedOn());
aTargetAnomaly.setDecidedByID(aSourceAnomaly.getDecidedByID());
aTargetAnomaly.setFixedByID(aSourceAnomaly.getFixedByID());
aTargetAnomaly.setFollowUpByID(aSourceAnomaly.getFollowUpByID());
aTargetAnomaly.setState(aSourceAnomaly.getState());
aTargetAnomaly.setFixedInVersion(aSourceAnomaly.getFixedInVersion());
aTargetAnomaly.setNotAcceptedReason(aSourceAnomaly.getNotAcceptedReason());
//Data copied only if not set previously
if (null == aTargetAnomaly.getTitle() || ("").equals(aTargetAnomaly.getTitle())) {
aTargetAnomaly.setTitle(aSourceAnomaly.getTitle());
}
if (null == aTargetAnomaly.getDescription() || ("").equals(aTargetAnomaly.getDescription())) {
aTargetAnomaly.setDescription(aSourceAnomaly.getDescription());
}
if (null == aTargetAnomaly.getRank()) {
aTargetAnomaly.setRank(aSourceAnomaly.getRank());
}
if (null == aTargetAnomaly.getRuleID() && null != aSourceAnomaly.getRuleID()) {
aTargetAnomaly.setRuleID(aSourceAnomaly.getRuleID());
}
if (null != aSourceAnomaly.getType()) {
final R4ECommentType oldCommentType = (R4ECommentType) aSourceAnomaly.getType();
R4ECommentType commentType = (R4ECommentType) aTargetAnomaly.getType();
if (null != oldCommentType) {
if (null == commentType) {
commentType = RModelFactory.eINSTANCE.createR4ECommentType();
if (null != commentType) {
commentType.setType(oldCommentType.getType());
}
aTargetAnomaly.setType(commentType);
}
}
}
R4EUIModelController.FResourceUpdater.checkIn(bookNum);
}
}
/**
* Method showPostponedElements.
*
* @param aReview
* R4EUIReviewBasic
* @throws ResourceHandlingException
* @throws OutOfSyncException
* @throws CompatibilityException
*/
public static void showPostponedElements(R4EUIReviewBasic aReview) throws ResourceHandlingException,
OutOfSyncException, CompatibilityException {
if (null != aReview) {
final R4EUIPostponedContainer container = aReview.getPostponedContainer();
if (null != container) {
boolean containerEnabled = false;
for (IR4EUIModelElement element : container.getChildren()) {
if (null != element) {
if (element instanceof R4EUIPostponedFile) {
R4EUIPostponedFile postFile = (R4EUIPostponedFile) element;
for (IR4EUIModelElement anomaly : postFile.getChildren()) {
if ((null != anomaly) && !anomaly.isEnabled()) {
element.removeChildren(anomaly, false);
}
}
if (!element.hasChildren()) {
element.close();
} else {
containerEnabled = true; //At least one file contains postponed anomaly(ies)
}
} else if (element instanceof R4EUIPostponedAnomalyContainer) {
for (IR4EUIModelElement anomaly : element.getChildren()) {
if ((null != anomaly) && !anomaly.isEnabled()) {
element.removeChildren(anomaly, false);
}
}
if (!element.hasChildren()) {
element.close();
container.removeChildren(element, false);
} else {
containerEnabled = true; //At least one global postponed anomaly exists
}
}
}
}
if (!containerEnabled) {
container.close();
//aReview.removeChildren(container, false); TODO this is temporary
}
}
}
}
/**
* Method getOriginalAnomaly.
*
* @param aOriginalReview
* R4EReview
* @param aCurrentAnomaly
* R4EAnomaly
* @return R4EAnomaly
*/
public static R4EAnomaly getOriginalAnomaly(R4EReview aOriginalReview, R4EAnomaly aCurrentAnomaly) {
if ((null != aOriginalReview) && (null != aCurrentAnomaly)) {
//Loop through all anomalies and find the one whose R4EID is the same as the currently imported one
final String[] origIdTokens = aCurrentAnomaly.getInfoAtt()
.get(R4EUIConstants.POSTPONED_ATTR_ORIG_ANOMALY_ID)
.split(R4EUIConstants.SEPARATOR); //First token is user name, second token is sequence number
if (null != origIdTokens) {
final R4EUser origUser = aOriginalReview.getUsersMap().get(origIdTokens[0]);
if (null != origUser) {
for (R4EComment anomaly : origUser.getAddedComments()) {
if (anomaly instanceof R4EAnomaly) {
Integer id = Integer.valueOf(origIdTokens[1]);
if (null != id) {
if (id.intValue() == anomaly.getId().getSequenceID()) {
return (R4EAnomaly) anomaly;
}
}
}
}
}
}
}
return null;
}
/**
* Method buildOriginalAnomalyID.
*
* @param aOrigAnomaly
* R4EAnomaly
* @return String
*/
public static String buildOriginalAnomalyID(R4EAnomaly aOrigAnomaly) {
return aOrigAnomaly.getId().getUserID() + R4EUIConstants.SEPARATOR + aOrigAnomaly.getId().getSequenceID();
}
/**
* Method buildOriginalCommentID.
*
* @param aOrigComment
* R4EComment
* @return String
*/
public static String buildOriginalCommentID(R4EComment aOrigComment) {
return aOrigComment.getId().getUserID() + aOrigComment.getId().getSequenceID();
}
/**
* Method getParticipantForReview.
*
* @param aReview
* R4EReview
* @param aParticipantId
* String
* @return R4EParticipant
* @throws ResourceHandlingException
*/
public static R4EParticipant getParticipantForReview(R4EReview aReview, String aParticipantId)
throws ResourceHandlingException {
if (null == aReview) {
return null;
}
R4EParticipant participant = (R4EParticipant) aReview.getUsersMap().get(aParticipantId);
if (null == participant) {
//Add the participant
final List<R4EUserRole> role = new ArrayList<R4EUserRole>(1);
role.add(R4EUserRole.R4E_ROLE_REVIEWER);
participant = R4EUIModelController.FModelExt.createR4EParticipant(aReview, aParticipantId, role);
}
return participant;
}
/**
* Method isEmailValid.
*
* @param aEmailAddress
* String
* @return boolean
*/
public static boolean isEmailValid(String aEmailAddress) {
boolean result = false;
if (null != aEmailAddress) {
final Pattern pattern = Pattern.compile(
"^([\\w]((\\.(?!\\.))|[-!#\\$%'\\*\\+/=\\?\\^`\\{\\}\\|~\\w])*)(?<=[\\w])@(([\\w][-\\w]*[\\w]\\.)+[a-zA-Z]{2,6})$",
Pattern.CASE_INSENSITIVE);
if (null != pattern) {
final Matcher matcher = pattern.matcher(aEmailAddress);
if (null != matcher) {
result = matcher.matches();
}
}
//Validation of input failed
if (!result) {
final ErrorDialog dialog = new ErrorDialog(null, R4EUIConstants.DIALOG_TITLE_ERROR,
"Invalid format for Participant Email", new Status(IStatus.ERROR, R4EUIPlugin.PLUGIN_ID, 0,
aEmailAddress + " is invalid", null), IStatus.ERROR);
Display.getDefault().syncExec(new Runnable() {
public void run() {
if (null != dialog) {
dialog.open();
}
}
});
}
}
return result;
}
/**
* Method isSameFileVersion.
*
* @param aFile1
* R4EFileVersion
* @param aFile2
* R4EFileVersion
* @return boolean
*/
public static boolean isSameFileVersion(R4EFileVersion aFile1, R4EFileVersion aFile2) {
return (compareStrings(aFile1.getPlatformURI(), aFile2.getPlatformURI())
&& compareStrings(aFile1.getRepositoryPath(), aFile2.getRepositoryPath()) && compareStrings(
aFile1.getVersionID(), aFile2.getVersionID()));
}
/**
* Method compareStrings.
*
* @param aStr1
* String
* @param aStr2
* String
* @return boolean
*/
public static boolean compareStrings(String aStr1, String aStr2) {
return ((aStr1 == aStr2) || (aStr1 != null && aStr1.equals(aStr2)));
}
}