blob: efed3e61569d808c6cde6f426022aecda80657d4 [file] [log] [blame]
package org.eclipse.team.internal.ccvs.core.resources;
/*
* (c) Copyright IBM Corp. 2000, 2002.
* All Rights Reserved.
*/
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.team.ccvs.core.*;
import org.eclipse.team.ccvs.core.CVSTag;
import org.eclipse.team.ccvs.core.ICVSRemoteResource;
import org.eclipse.team.ccvs.core.ICVSRepositoryLocation;
import org.eclipse.team.core.TeamException;
import org.eclipse.team.internal.ccvs.core.client.Checkout;
import org.eclipse.team.internal.ccvs.core.client.Command;
import org.eclipse.team.internal.ccvs.core.client.Session;
import org.eclipse.team.internal.ccvs.core.client.Update;
import org.eclipse.team.internal.ccvs.core.client.Command.LocalOption;
import org.eclipse.team.internal.ccvs.core.syncinfo.FolderSyncInfo;
/**
* @version 1.0
* @author
*/
public class RemoteModule extends RemoteFolder {
private String label;
private ICVSRemoteResource[] referencedModules;
private LocalOption[] localOptions;
private boolean expandable;
public static RemoteModule[] getRemoteModules(ICVSRepositoryLocation repository, CVSTag tag, IProgressMonitor monitor) throws TeamException {
RemoteModule[] modules;
Session s = new Session(repository, (ICVSFolder)CVSWorkspaceRoot.getCVSResourceFor(ResourcesPlugin.getWorkspace().getRoot()), false);
s.open(monitor);
try {
modules = Command.CHECKOUT.getRemoteModules(s, tag, monitor);
} finally {
s.close();
}
return modules;
}
/**
* Create a set of RemoteModules from the provided module definition strings returned from the server
*
* At the moment, we are very restrictive on the types of modules we support.
*/
public static RemoteModule[] createRemoteModules(String[] moduleDefinitionStrings, ICVSRepositoryLocation repository, CVSTag tag) {
Map modules = new HashMap();
Map referencedModulesTable = new HashMap();
Map moduleAliases = new HashMap();
List acceptableModules = new ArrayList();
// First pass: Create the remote module instances based on remote mapping
for (int i = 0; i < moduleDefinitionStrings.length; i++) {
// Read the module name
StringTokenizer tokenizer = new StringTokenizer(moduleDefinitionStrings[i]);
String moduleName = tokenizer.nextToken();
// Read the options associated with the module
List localOptionsList = new ArrayList();
String next = tokenizer.nextToken();
while (next.charAt(0) == '-') {
switch (next.charAt(1)) {
case 'a': // alias
localOptionsList.add(Checkout.ALIAS);
break;
case 'l': // don't recurse
localOptionsList.add(Checkout.DO_NOT_RECURSE);
break;
case 'd': // directory
localOptionsList.add(Checkout.makeDirectoryNameOption(tokenizer.nextToken()));
break;
case 'e':
case 'i':
case 'o':
case 't':
case 'u': // Ignore any programs
tokenizer.nextToken();
break;
case 's': // status
localOptionsList.add(Checkout.makeStatusOption(tokenizer.nextToken()));
break;
default: // unanticipated option. Ignore it and go on
}
next = tokenizer.nextToken();
}
LocalOption[] localOptions = (LocalOption[]) localOptionsList.toArray(new LocalOption[localOptionsList.size()]);
if (Checkout.ALIAS.isElementOf(localOptions)) {
if (localOptions.length > 1) {
// XXX This is an error condition that needs to be reported
}
// An alias expands to one or more modules or paths
List expansions = new ArrayList(10);
expansions.add(next);
while (tokenizer.hasMoreTokens())
expansions.add(tokenizer.nextToken());
moduleAliases.put(moduleName, (String[]) expansions.toArray(new String[expansions.size()]));
modules.put(moduleName, new RemoteModule(moduleName, null, repository, null, localOptions, tag, true));
} else {
// The module definition may have a leading directory which can be followed by some files
if (!(next.charAt(0) == '&')) {
String directory = next;
List files = new ArrayList();
while (tokenizer.hasMoreTokens() && (next.charAt(0) != '&')) {
next = tokenizer.nextToken() ;
if ((next.charAt(0) != '&'))
files.add(next);
}
RemoteModule remoteModule = new RemoteModule(moduleName, null, repository, new Path(directory), localOptions, tag, ! files.isEmpty());
modules.put(moduleName, remoteModule);
if ( ! files.isEmpty()) {
ICVSRemoteResource[] children = new ICVSRemoteResource[files.size()];
for (int j = 0; j < children.length; j++) {
children[j] = new RemoteFile(remoteModule, Update.STATE_NONE, (String)files.get(j), tag);
remoteModule.setChildren(children);
}
}
} else {
modules.put(moduleName, new RemoteModule(moduleName, null, repository, null, localOptions, tag, true));
}
// Record any referenced modules so that can be cross-referenced below
if (next.charAt(0) == '&') {
List children = new ArrayList(10);
children.add(next);
while (tokenizer.hasMoreTokens())
children.add(tokenizer.nextToken());
referencedModulesTable.put(moduleName, (String[])children.toArray(new String[children.size()]));
}
}
}
// Second pass: Cross reference aliases to modules
// XXX Aliases can reference other aliases which confuses the expansion!
Iterator iter = moduleAliases.keySet().iterator();
while (iter.hasNext()) {
String moduleName = (String)iter.next();
RemoteModule module = (RemoteModule)modules.get(moduleName);
String[] expansion = (String[])moduleAliases.get(moduleName);
List referencedFolders = new ArrayList();
boolean expandable = true;
for (int i = 0; i < expansion.length; i++) {
if (expansion[i].charAt(0) == '!') {
// XXX Unsupported for now
expandable = false;
} else {
IPath path = new Path(expansion[i]);
if (path.segmentCount() > 1) {
// XXX Unsupported for now
expandable = false;
} else {
RemoteModule child = (RemoteModule)modules.get(expansion[i]);
if (child == null) {
referencedFolders.add(new RemoteFolder(null, repository, path, tag));
} else {
// Need to check if the child is a module alias
if (child.isAlias()) {
// XXX Unsupported for now
expandable = false;
} else {
referencedFolders.add(child);
}
}
}
}
}
if (expandable) {
module.setChildren((ICVSRemoteResource[]) referencedFolders.toArray(new ICVSRemoteResource[referencedFolders.size()]));
} else {
module.setExpandable(false);
}
}
// Third pass: Cross reference remote modules where necessary
iter = modules.keySet().iterator();
while (iter.hasNext()) {
String moduleName = (String)iter.next();
String[] children = (String[])referencedModulesTable.get(moduleName);
if (children != null) {
RemoteModule module = (RemoteModule)modules.get(moduleName);
List referencedFolders = new ArrayList();
boolean expandable = true;
for (int i = 0; i < children.length; i++) {
RemoteModule child = (RemoteModule)modules.get(children[i].substring(1));
if (child.isAlias()) {
// Include alias children in-line
expandable = false;
// referencedFolders.addAll(Arrays.asList(child.getChildren()));
} else {
// XXX not expandable if child has local directory option (-d)
if (Command.findOption(child.getLocalOptions(), "-d") != null) {
expandable = false;
} else {
referencedFolders.add(child);
}
}
}
if (expandable) {
module.setReferencedModules((ICVSRemoteResource[]) referencedFolders.toArray(new ICVSRemoteResource[referencedFolders.size()]));
} else {
module.setExpandable(false);
}
}
}
return (RemoteModule[])modules.values().toArray(new RemoteModule[modules.size()]);
}
public RemoteModule(String label, RemoteFolder parent, ICVSRepositoryLocation repository, IPath repositoryRelativePath, LocalOption[] localOptions, CVSTag tag, boolean isStatic) {
super(parent,
label,
repository,
repositoryRelativePath == null ? new Path(FolderSyncInfo.VIRTUAL_DIRECTORY) : repositoryRelativePath,
tag,
isStatic);
this.localOptions = localOptions;
this.label = label;
this.expandable = true;
}
public LocalOption[] getLocalOptions() {
return localOptions;
}
/*
* Override of inherited getMembers in order to combine the physical members with any referenced modules
*/
public ICVSRemoteResource[] getMembers(CVSTag tagName, IProgressMonitor monitor) throws TeamException {
if ( ! expandable) return new ICVSRemoteResource[0];
ICVSRemoteResource[] physicalChildren;
if ( folderInfo.getIsStatic()) {
physicalChildren = getChildren();
} else {
physicalChildren = super.getMembers(tagName, monitor);
}
ICVSRemoteResource[] allChildren;
if (referencedModules != null && referencedModules.length > 0) {
if (physicalChildren == null) {
allChildren = referencedModules;
} else {
// Combine two sets of children
allChildren = new ICVSRemoteResource[physicalChildren.length + referencedModules.length];
for (int i = 0; i < physicalChildren.length; i++) {
allChildren[i] = physicalChildren[i];
}
for (int i = 0; i < referencedModules.length; i++) {
allChildren[i + physicalChildren.length] = referencedModules[i];
}
}
} else if (physicalChildren != null) {
allChildren = physicalChildren;
} else {
allChildren = new ICVSRemoteResource[0];
}
return allChildren;
}
/*
* Set the children to a static set of children
*/
protected void setChildren(ICVSRemoteResource[] children) {
super.setChildren(children);
if ( ! folderInfo.getIsStatic())
this.folderInfo = new FolderSyncInfo(folderInfo.getRepository(), folderInfo.getRoot(), folderInfo.getTag(), true);
}
private void setReferencedModules(ICVSRemoteResource[] referencedModules) {
this.referencedModules = referencedModules;
}
public boolean isAlias() {
return Checkout.ALIAS.isElementOf(localOptions);
}
/**
* @see ICVSRemoteFolder#isExpandable()
*/
public boolean isExpandable() {
return expandable;
}
private void setExpandable(boolean expandable) {
this.expandable = expandable;
}
}