package com.revolsys.io; import java.util.LinkedList; import java.util.List; import com.revolsys.util.Property; public class PathName implements Comparable<PathName>, CharSequence { public static final PathName ROOT = new PathName("/"); public static PathName newPathName(final Object path) { if (path instanceof PathName) { return (PathName)path; } else if (Property.hasValue(path)) { String pathString = path.toString(); pathString = PathUtil.clean(pathString); if ("/".equals(pathString)) { return ROOT; } else if (Property.hasValue(pathString)) { return new PathName(pathString); } } return null; } private final String name; private PathName parent; private final String path; private final String upperPath; protected PathName(final String path) { this.path = path; this.upperPath = path.toUpperCase(); this.name = PathUtil.getName(path); } @Override public char charAt(final int index) { return this.path.charAt(index); } @Override public int compareTo(final PathName pathName) { return getUpperPath().compareTo(pathName.getUpperPath()); } @Override public boolean equals(final Object object) { if (object == null) { return false; } else if (object == this) { return true; } else { final String upperPath = getUpperPath(); String upperPath2; if (object instanceof PathName) { final PathName path = (PathName)object; upperPath2 = path.getUpperPath(); } else { upperPath2 = object.toString().toUpperCase(); } return upperPath.equals(upperPath2); } } /** * If this path is an ancestor of the other path return the path that is a direct child of this path. * Returns null if this path is not an ancestor of the current path. * * @param path The path to test. * @return True if this path is an ancestor of the other path. */ public PathName getChild(PathName path) { if (path != null) { for (PathName parentPath = path.getParent(); parentPath != null; parentPath = parentPath .getParent()) { if (equals(parentPath)) { return path; } path = parentPath; } } return null; } public List<String> getElements() { final LinkedList<String> elements = new LinkedList<>(); PathName currentPath = this; for (PathName parentPath = getParent(); parentPath != null; parentPath = parentPath .getParent()) { elements.addFirst(currentPath.getName()); currentPath = parentPath; } return elements; } public String getName() { return this.name; } public PathName getParent() { if (this.parent == null && this.path.length() > 1) { final String parentPath = getParentPath(); this.parent = newPathName(parentPath); } return this.parent; } public String getParentPath() { if (this.path == null) { return null; } else if (this.path.length() > 1) { final int index = this.path.lastIndexOf('/'); if (index == 0) { return "/"; } else { return this.path.substring(0, index); } } else { return null; } } public String getPath() { return this.path; } public List<PathName> getPaths() { final LinkedList<PathName> elements = new LinkedList<>(); elements.add(this); for (PathName parentPath = getParent(); parentPath != null; parentPath = parentPath .getParent()) { elements.addFirst(parentPath); } return elements; } public String getUpperPath() { return this.upperPath; } @Override public int hashCode() { return getUpperPath().hashCode(); } /** * Test if that this path is an ancestor of the other path. * * @param path The path to test. * @return True if this path is an ancestor of the other path. */ public boolean isAncestorOf(final PathName path) { if (path != null) { for (PathName parentPath = path.getParent(); parentPath != null; parentPath = parentPath .getParent()) { if (equals(parentPath)) { return true; } } } return false; } /** * Test if that this path is a child of the other path. * * @param path The path to test. * @return True if this path is a child of the other path. */ public boolean isChildOf(final PathName path) { if (path != null) { final PathName parent = getParent(); return path.equals(parent); } return false; } /** * Test if that this path is an descendant of the other path. * * @param path The path to test. * @return True if this path is an descendant of the other path. */ public boolean isDescendantOf(final PathName path) { if (path != null) { for (PathName parentPath = getParent(); parentPath != null; parentPath = parentPath .getParent()) { if (path.equals(parentPath)) { return true; } } } return false; } /** * Test if that this path is the parent of the other path. * * @param path The path to test. * @return True if this path is the parent of the other path. */ public boolean isParentOf(final PathName path) { if (path != null) { final PathName otherParent = path.getParent(); return equals(otherParent); } return false; } /** * Test if that this path is a sibling of the other path. * * @param path The path to test. * @return True if this path is a sibling of the other path. */ public boolean isSiblingOf(final PathName path) { if (path != null) { final PathName parent1 = getParent(); final PathName parent2 = path.getParent(); return parent1.equals(parent2); } return false; } @Override public int length() { return this.path.length(); } public PathName newChild(final String name) { final String childPath = getPath() + "/" + name; return newPathName(childPath); } @Override public CharSequence subSequence(final int start, final int end) { return this.path.subSequence(start, end); } @Override public String toString() { return this.path; } }