/*******************************************************************************
* Copyright (c) 2007, 2015 Zend Technologies 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:
* Zend Technologies - initial API and implementation
*******************************************************************************/
package org.eclipse.php.refactoring.core.move;
import java.text.MessageFormat;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.core.ISourceModule;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.php.core.PHPToolkitUtil;
import org.eclipse.php.internal.core.filenetwork.FileNetworkUtility;
import org.eclipse.php.internal.core.filenetwork.ReferenceTree;
import org.eclipse.php.internal.core.filenetwork.ReferenceTree.Node;
import org.eclipse.php.internal.core.util.collections.BucketMap;
import org.eclipse.php.refactoring.core.PhpRefactoringCoreMessages;
import org.eclipse.php.refactoring.core.RefactoringPlugin;
public class MoveUtils {
private static final String phpunitFramework = "PHPUnit/Framework";
private MoveUtils() {
}
/**
* For a file that is being moved, get the string of an include statement in
* it and returns what the new include string should be based on the new
* location
*
* @param sourceFile
* @param destinationDirectoryPath
* @param value
* @param selectedResource
* @return the new include string
*/
public static String getMovedIncludedString(IFile sourceFile,
IPath destinationDirectoryPath, String value,
IResource[] selectedResource) {
if (!isRelativeAndExistingResource(sourceFile.getParent(), value)) {
return value;
}
IPath projectPath = sourceFile.getProject().getFullPath();
// moving in same project
if (projectPath.isPrefixOf(destinationDirectoryPath)) {
IPath destPath = destinationDirectoryPath;
String destFile = sourceFile.getName();
for (IResource resouce : selectedResource) {
if (resouce instanceof IFolder
&& resouce.getProjectRelativePath().isPrefixOf(
sourceFile.getProjectRelativePath())) {
// if the parent folder is moving, append the folder name to
// the fileName.
destFile = resouce.getName() + "/" + destFile; //$NON-NLS-1$
break;
}
}
// remove the fileName;
destPath = destPath.append(destFile).removeLastSegments(1);
IPath includingPath = new Path(value);
IPath destIncludedFilePath = sourceFile.getParent().getFullPath()
.append(value);
for (IResource resouce : selectedResource) {
if (resouce instanceof IFile
&& resouce.getFullPath().equals(destIncludedFilePath)) {
// if the parent folder is moving, append the folder name to
// the fileName.
destIncludedFilePath = destPath.append(resouce.getName());
break;
}
}
String fileName = includingPath.lastSegment();
for (IResource resouce : selectedResource) {
if (resouce instanceof IFolder
&& resouce.getProjectRelativePath().isPrefixOf(
includingPath)) {
destIncludedFilePath = destinationDirectoryPath.append(
resouce.getName()).append(fileName);
break;
}
}
return destIncludedFilePath.makeRelativeTo(destPath).toString();
} else {
return value;
}
}
private static boolean isRelativeAndExistingResource(IContainer container,
String value) {
if (container != null && value != null) {
if (!new Path(value).isAbsolute()) {
IResource resource = container.findMember(value);
return resource != null && resource.exists();
} else {
return false;
}
}
return false;
}
/**
* @param filePath
* @return directory path - the path not inlcuding file name
*/
public static IPath getDirectoryPath(IPath filePath) {
return filePath.removeLastSegments(1);
}
/**
* When a file is being moved, all the files that include it need to change
* their include statements to it based on the new location. This method
* gets the moved file, the current including file we are handling and the
* current include statement in it, and returns the new include statement
*
* @param selectedResource
*
*/
public static String getMovedIncludingString(IFile sourceFile,
IPath destinationDirectoryPath, IFile includingFile, String value,
IResource[] selectedResource) {
return getMovedIncludingString(sourceFile,
getDirectoryPath(sourceFile.getFullPath()),
destinationDirectoryPath, includingFile, value,
selectedResource);
}
public static String getMovedIncludingString(IFile sourceFile,
IPath oldDirectoryPath, IPath destinationDirectoryPath,
IFile includingFile, String value, IResource[] selectedResource) {
IPath projectPath = sourceFile.getProject().getFullPath();
boolean isInSaveProject = false;
if (includingFile.getProject() == sourceFile.getProject()) {
isInSaveProject = true;
}
// moving in same project
if (projectPath.isPrefixOf(destinationDirectoryPath)) {
IPath includePath = new Path(value);
String fileName = value;
if (includePath.segmentCount() > 1) {
fileName = includePath.lastSegment();
// includePath = includePath.removeLastSegments(1);
}
IPath includeFilePath = includingFile.getParent()
.getProjectRelativePath().append(includePath);
// Check if the parent folder is moving.
for (IResource resouce : selectedResource) {
if (resouce instanceof IFolder
&& ((resouce.getProjectRelativePath()
.isPrefixOf(includePath)) || resouce
.getProjectRelativePath().isPrefixOf(
includeFilePath))
) {
// if the parent folder is moving, append the folder name to
// the fileName.
fileName = resouce.getName() + "/" + fileName; //$NON-NLS-1$
break;
}
}
IPath path = destinationDirectoryPath.append(fileName);
IPath includingPath = includingFile.getParent().getFullPath();
// Check if the including file is moving.
for (IResource resouce : selectedResource) {
// the folder of including file is moving
if (resouce.getProjectRelativePath().isPrefixOf(includingPath)) {
// if the parent folder is moving, append the folder name to
// the fileName.
includePath = destinationDirectoryPath.append(includePath
.makeRelativeTo(resouce.getProjectRelativePath()));
break;
}
// the including file is moving
if (resouce.equals(includingFile)) {
// if the parent folder is moving, append the folder name to
// the fileName.
includePath = destinationDirectoryPath;
break;
}
}
if (value.startsWith("..") || value.startsWith(".")) { //$NON-NLS-1$ //$NON-NLS-2$
return path.makeRelativeTo(includingPath).toOSString()
.replaceAll("\\\\", "/"); //$NON-NLS-1$ //$NON-NLS-2$
} else {
if (isInSaveProject) {
return path.makeRelativeTo(includingPath).toOSString()
.replaceAll("\\\\", "/"); //$NON-NLS-1$ //$NON-NLS-2$
} else {
return path.makeRelativeTo(projectPath).toOSString()
.replaceAll("\\\\", "/"); //$NON-NLS-1$ //$NON-NLS-2$
}
}
// return path.makeRelativeTo(includingPath).toString();
} else {
IPath oldDirectory = oldDirectoryPath.removeFirstSegments(1);
String fileName = value;
IPath includePath = new Path(value);
if (includePath.segmentCount() > 1) {
fileName = includePath.lastSegment();
}
IPath path = destinationDirectoryPath.append(oldDirectory).append(
fileName);
IPath destPath = destinationDirectoryPath;
if (destPath.isPrefixOf(path)) {
if (value.startsWith("..") || value.startsWith(".")) { //$NON-NLS-1$ //$NON-NLS-2$
IPath includingPath = includingFile.getParent()
.getProjectRelativePath();
return path.makeRelativeTo(destPath.append(includingPath))
.toString().replaceAll("\\\\", "/"); //$NON-NLS-1$ //$NON-NLS-2$
} else {
return path.makeRelativeTo(destPath).toOSString()
.replaceAll("\\\\", "/"); //$NON-NLS-1$ //$NON-NLS-2$
}
}
return path.removeFirstSegments(1).toOSString();
}
}
/**
* Based on the user selection, recursively populates a set of all of the
* php files
*
* @param sourceResources
* @param phpFilesSet
*/
public static void getAllPHPFiles(IResource[] sourceResources,
Set<IFile> phpFilesSet) {
for (IResource current : sourceResources) {
if (current instanceof IFolder) {
IResource[] fldChildrens;
IFolder fld = (IFolder) current;
try {
fldChildrens = fld.members();
} catch (CoreException e) {
RefactoringPlugin
.logException(
"Failed getting folder children in move operation", e); //$NON-NLS-1$
continue;
}
getAllPHPFiles(fldChildrens, phpFilesSet);
} else if (current instanceof IFile) {
IFile file = (IFile) current;
if (PHPToolkitUtil.isPHPFile(file)) {
phpFilesSet.add(file);
}
}
}
}
public static RefactoringStatus checkMove(Collection<IFile> files,
IProject srcProject, IContainer destination) {
RefactoringStatus status = new RefactoringStatus();
// // collecting included files from source network
BucketMap<IFile, IFile> errors = new BucketMap<IFile, IFile>();
for (IFile file : files) {
Collection<Node> allIncludedNodes = getReferencedFiles(file);
if (allIncludedNodes == null) {
continue;
}
for (Node includedNode : allIncludedNodes) {
IFile includedFile = (IFile) includedNode.getFile()
.getResource();
if (!includedNode.getFile().getParent().getElementName()
.equals(phpunitFramework)
&& !files.contains(includedFile)
&& destination.findMember(includedFile
.getProjectRelativePath()) == null) {
errors.add(file, includedFile);
}
}
}
for (IFile node : errors.getKeys()) {
status.addWarning(MessageFormat.format(PhpRefactoringCoreMessages
.getString("MoveUtils.8"), node.getName())); //$NON-NLS-1$
for (IFile value : errors.get(node)) {
status.addWarning(MessageFormat.format(
PhpRefactoringCoreMessages.getString("MoveUtils.9"), node.getProjectRelativePath().toString(), value.getProjectRelativePath().toString())); //$NON-NLS-1$
}
}
//
// collecting including files from source network
errors = new BucketMap<IFile, IFile>();
for (IFile file : files) {
Collection<Node> allIncludingNodes = getReferencingFiles(file);
if (allIncludingNodes == null) {
continue;
}
for (Node includingNode : allIncludingNodes) {
IFile includingFile = (IFile) includingNode.getFile()
.getResource();
if (!files.contains(includingFile)) {
errors.add(file, includingFile);
}
}
}
for (IFile node : errors.getKeys()) {
status.addWarning(MessageFormat.format(PhpRefactoringCoreMessages
.getString("MoveUtils.10"), node.getName())); //$NON-NLS-1$
for (IFile includingNode : errors.get(node)) {
status.addWarning(MessageFormat.format(
PhpRefactoringCoreMessages.getString("MoveUtils.11"), node.getProjectRelativePath().toString(), includingNode.getProjectRelativePath().toString())); //$NON-NLS-1$
}
}
return status;
}
public static Collection<Node> getReferencingFiles(IFile file) {
ISourceModule sourceModule = DLTKCore.createSourceModuleFrom(file);
return getReferencingFiles(sourceModule);
}
public static Collection<Node> getReferencingFiles(
ISourceModule sourceModule) {
if (sourceModule != null) {
ReferenceTree tree = FileNetworkUtility.buildReferencingFilesTree(
sourceModule, null);
if (tree != null && tree.getRoot() != null) {
return tree.getRoot().getChildren();
}
}
return Collections.emptyList();
}
public static Collection<Node> getReferencedFiles(IFile file) {
ISourceModule sourceModule = DLTKCore.createSourceModuleFrom(file);
return getReferencedFiles(sourceModule);
}
public static Collection<Node> getReferencedFiles(ISourceModule sourceModule) {
if (sourceModule != null) {
ReferenceTree tree = FileNetworkUtility.buildReferencedFilesTree(
sourceModule, null);
if (tree != null && tree.getRoot() != null) {
return tree.getRoot().getChildren();
}
}
return Collections.emptyList();
}
}