blob: e47b9765b45f6b1c981c7d4e6c199f3945d020c4 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2007 IBM Corporation 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.ui.internal.ide.undo;
import java.net.URI;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.ui.ide.undo.ResourceDescription;
/**
* ContainerDescription is a lightweight description that describes a container
* to be created.
*
* This class is not intended to be instantiated or used by clients.
*
* @since 3.3
*
*/
public abstract class ContainerDescription extends AbstractResourceDescription {
String name;
URI location;
String defaultCharSet;
AbstractResourceDescription[] members;
/**
* Create a container description from the specified container handle that
* can be used to create the container. The returned ContainerDescription
* should represent any non-existing parents in addition to the specified
* container.
*
* @param container
* the handle of the container to be described
* @return a container description describing the container and any
* non-existing parents.
*/
public static ContainerDescription fromContainer(IContainer container) {
IPath fullPath = container.getFullPath();
ContainerDescription firstCreatedParent = null;
ContainerDescription currentContainerDescription = null;
// Does the container exist already? If so, then the parent exists and
// we use the normal creation constructor.
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
IContainer currentContainer = (IContainer) root.findMember(fullPath);
if (currentContainer != null) {
return (ContainerDescription) ResourceDescription
.fromResource(container);
}
// Create container descriptions for any uncreated parents in the given
// path.
currentContainer = root;
for (int i = 0; i < fullPath.segmentCount(); i++) {
String currentSegment = fullPath.segment(i);
IResource resource = currentContainer.findMember(currentSegment);
if (resource != null) {
// parent already exists, no need to create a description for it
currentContainer = (IContainer) resource;
} else {
if (i == 0) {
// parent does not exist and it is a project
firstCreatedParent = new ProjectDescription(root
.getProject(currentSegment));
currentContainerDescription = firstCreatedParent;
} else {
IFolder folderHandle = currentContainer.getFolder(new Path(
currentSegment));
ContainerDescription currentFolder = new FolderDescription(
folderHandle);
currentContainer = folderHandle;
if (currentContainerDescription != null) {
currentContainerDescription.addMember(currentFolder);
}
currentContainerDescription = currentFolder;
if (firstCreatedParent == null) {
firstCreatedParent = currentFolder;
}
}
}
}
return firstCreatedParent;
}
/**
* Create a ContainerDescription with no state.
*/
public ContainerDescription() {
}
/**
* Create a ContainerDescription from the specified container handle.
* Typically used when the container handle represents a resource that
* actually exists, although it will not fail if the resource is
* non-existent.
*
* @param container
* the container to be described
*/
public ContainerDescription(IContainer container) {
super(container);
this.name = container.getName();
if (container.isLinked()) {
this.location = container.getLocationURI();
}
try {
if (container.isAccessible()) {
defaultCharSet = container.getDefaultCharset(false);
IResource[] resourceMembers = container.members();
members = new AbstractResourceDescription[resourceMembers.length];
for (int i = 0; i < resourceMembers.length; i++) {
members[i] = (AbstractResourceDescription) ResourceDescription
.fromResource(resourceMembers[i]);
}
}
} catch (CoreException e) {
// Eat this exception because it only occurs when the resource
// does not exist and we have already checked this.
// We do not want to throw exceptions on the simple constructor, as
// no one has actually tried to do anything yet.
}
}
/**
* Create any child resources known by this container description.
*
* @param parentHandle
* the handle of the created parent
* @param monitor
* the progress monitor to be used
* @param ticks
* the number of ticks allocated for creating children
* @throws CoreException
*/
protected void createChildResources(IContainer parentHandle,
IProgressMonitor monitor, int ticks) throws CoreException {
// restore any children
if (members != null && members.length > 0) {
for (int i = 0; i < members.length; i++) {
members[i].parent = parentHandle;
members[i].createResource(new SubProgressMonitor(monitor, ticks
/ members.length));
}
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.internal.ide.undo.ResourceDescription#recordStateFromHistory(org.eclipse.core.resources.IResource,
* org.eclipse.core.runtime.IProgressMonitor)
*/
public void recordStateFromHistory(IResource resource,
IProgressMonitor monitor) throws CoreException {
monitor.beginTask(
UndoMessages.FolderDescription_SavingUndoInfoProgress, 100);
if (members != null) {
for (int i = 0; i < members.length; i++) {
if (members[i] instanceof FileDescription) {
IPath path = resource.getFullPath().append(
((FileDescription) members[i]).name);
IFile fileHandle = resource.getWorkspace().getRoot().getFile(
path);
members[i].recordStateFromHistory(fileHandle,
new SubProgressMonitor(monitor, 100 / members.length));
} else if (members[i] instanceof FolderDescription) {
IPath path = resource.getFullPath().append(
((FolderDescription) members[i]).name);
IFolder folderHandle = resource.getWorkspace().getRoot()
.getFolder(path);
members[i].recordStateFromHistory(folderHandle,
new SubProgressMonitor(monitor, 100 / members.length));
}
}
}
monitor.done();
}
/**
* Return the name of the container described by this ContainerDescription.
*
* @return the name of the container.
*/
public String getName() {
return name;
}
/**
* Return the first folder found that has no child folders.
*
* @return the container description for the first child in the receiver
* that is a leaf, or this container if there are no children.
*/
public ContainerDescription getFirstLeafFolder() {
// If there are no members, this is a leaf
if (members == null || members.length == 0) {
return this;
}
// Traverse the members and find the first potential leaf
for (int i = 0; i < members.length; i++) {
if (members[i] instanceof ContainerDescription) {
return ((ContainerDescription) members[i]).getFirstLeafFolder();
}
}
// No child folders were found, this is a leaf
return this;
}
/**
* Add the specified resource description as a member of this resource
* description
*
* @param member
* the resource description considered a member of this
* container.
*/
public void addMember(AbstractResourceDescription member) {
if (members == null) {
members = new AbstractResourceDescription[] { member };
} else {
AbstractResourceDescription[] expandedMembers = new AbstractResourceDescription[members.length + 1];
System.arraycopy(members, 0, expandedMembers, 0, members.length);
expandedMembers[members.length] = member;
members = expandedMembers;
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.internal.ide.undo.ResourceDescription#restoreResourceAttributes(org.eclipse.core.resources.IResource)
*/
protected void restoreResourceAttributes(IResource resource)
throws CoreException {
super.restoreResourceAttributes(resource);
Assert.isLegal(resource instanceof IContainer);
IContainer container = (IContainer) resource;
if (defaultCharSet != null) {
container.setDefaultCharset(defaultCharSet, null);
}
}
/**
* Set the location to which this container is linked.
*
* @param location
* the location URI, or <code>null</code> if there is no link
*/
public void setLocation(URI location) {
this.location = location;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.internal.ide.undo.ResourceDescription#verifyExistence(boolean)
*/
public boolean verifyExistence(boolean checkMembers) {
boolean existence = super.verifyExistence(checkMembers);
if (existence) {
if (checkMembers) {
// restore any children
if (members != null && members.length > 0) {
for (int i = 0; i < members.length; i++) {
if (!members[i].verifyExistence(checkMembers)) {
return false;
}
}
}
}
return true;
}
return false;
}
}