// Copyright 2012 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package collide.client.filetree;
import com.google.collide.client.util.PathUtil;
import com.google.collide.dto.DirInfo;
import com.google.collide.dto.Mutation;
import com.google.collide.dto.TreeNodeInfo;
import com.google.collide.dto.client.DtoClientImpls.DirInfoImpl;
import com.google.collide.dto.client.DtoClientImpls.MutationImpl;
import com.google.collide.dto.client.DtoClientImpls.TreeNodeInfoImpl;
import com.google.collide.json.shared.JsonArray;
/**
* Utility methods for file tree.
*
*/
public class FileTreeUtils {
private FileTreeUtils() {
}
/**
* Allocates a name String that is guaranteed not to exist in the children of
* the specified DirInfo.
*
* @param parentDir the directory we will be scanning.
* @param seedName the initial name we want to try to use.
*/
static String allocateName(DirInfo parentDir, String seedName) {
if (parentDir == null) {
return seedName;
}
String uniqueName = ensureUniqueChildName(parentDir.getSubDirectories(), seedName);
return ensureUniqueChildName(parentDir.getFiles(), uniqueName);
}
private static String ensureUniqueChildName(
JsonArray<? extends TreeNodeInfo> children, String seedName) {
String uniqueName = null;
boolean foundUnique = false;
int retryNumber = 0;
while (!foundUnique) {
// Generate a name to try.
uniqueName = (retryNumber > 0) ? generateName(seedName, retryNumber) : seedName;
// Test the name.
foundUnique = isNameUnique(children, null, uniqueName);
retryNumber++;
}
return uniqueName;
}
private static String generateName(String name, int retryNumber) {
int dotIndex = name.indexOf('.');
dotIndex = (dotIndex == -1) ? name.length() : dotIndex;
String base = name.substring(0, dotIndex);
// This will either be the extension including the '.', or the empty String
// if dotIndex is == to the size of the String.
String extension = name.substring(dotIndex, name.length());
return base + "(" + retryNumber + ")" + extension;
}
/**
* Test if there is a sibling node (file or directory) with specified name.
*
* <p>
* Specified node (whose siblings are checked) itself is not checked.
*/
static boolean hasNoPeerWithName(FileTreeNode nodeToCheck, String name) {
DirInfoImpl parentDir = nodeToCheck.getParent().cast();
return isNameUnique(parentDir.getSubDirectories(), nodeToCheck, name) && isNameUnique(
parentDir.getFiles(), nodeToCheck, name);
}
private static boolean isNameUnique(
JsonArray<? extends TreeNodeInfo> children, FileTreeNode nodeToCheck, String name) {
for (int i = 0, n = children.size(); i < n; i++) {
FileTreeNode child = (FileTreeNode) children.get(i);
if (child != nodeToCheck && name.equals(child.getName())) {
// Whoops. We collided.
return false;
}
}
return true;
}
static Mutation makeMutation(Mutation.Type mutatonType, PathUtil oldPath, PathUtil newPath,
boolean isDirectory, String resourceId) {
// We make a placeholder for the new node solely to install information
// about whether or not this is a directory.
TreeNodeInfoImpl placeHolderNode = TreeNodeInfoImpl.make().setNodeType(
isDirectory ? TreeNodeInfo.DIR_TYPE
: TreeNodeInfo.FILE_TYPE).setFileEditSessionKey(resourceId);
return MutationImpl.make()
.setMutationType(mutatonType)
.setNewNodeInfo(placeHolderNode)
.setOldPath(oldPath == null ? null : oldPath.getPathString())
.setNewPath(newPath == null ? null : newPath.getPathString());
}
}