/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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 com.aliyun.odps.volume; /** * Volume分区下文件和目录的路径. * 仅用于表示volume partition下的文件和目录, 根目录表示相应的volume partition目录. */ public class Path implements Comparable { /** * The directory separator, a slash. */ public static final String SEPARATOR = "/"; private static final String CUR_DIR = "/"; /** * this is always an absolute path */ private String path; /** * Resolve a child path against a parent path. */ public Path(String parent, String child) { this(new Path(parent), new Path(child)); } /** * Resolve a child path against a parent path. */ public Path(Path parent, String child) { this(parent, new Path(child)); } /** * Resolve a child path against a parent path. */ public Path(String parent, Path child) { this(new Path(parent), child); } /** * Resolve a child path against a parent path. */ public Path(Path parent, Path child) { // XXX child may be absolute just as hadoop Path & java.net.URI if (child.isAbsolute()) { path = child.path; } StringBuilder sb = new StringBuilder(parent.path.length() + 1 + child.path.length()); sb.append(parent.path); if (!parent.path.equals("/")) { sb.append("/"); } sb.append(child); path = sb.toString(); } private static boolean isAbsolutePath(String path) { return path.startsWith(SEPARATOR); } private void checkPathArg(String path) throws IllegalArgumentException { // disallow construction of a Path from an empty string if (path == null) { throw new IllegalArgumentException( "Can not create a Path from a null string"); } if (path.length() == 0) { throw new IllegalArgumentException( "Can not create a Path from an empty string"); } } /** * Construct a path from a String. Path strings are URIs, but with * unescaped elements and some additional normalization. */ public Path(String pathString) throws IllegalArgumentException { checkPathArg(pathString); path = normalizePath(pathString); } /** * Normalize a path string to use non-duplicated forward slashes as * the path separator and remove any trailing path separators. * * @return Normalized path string. */ private static String normalizePath(String path) { // Remove double forward slashes. path = path.replaceAll("//", "/"); // trim trailing slash from non-root path int minLength = 1; if (path.length() > minLength && path.endsWith("/")) { path = path.substring(0, path.length() - 1); } return path; } /** * Return the number of elements in this path. */ public int depth() { int depth = 0; int slash = path.length() == 1 && path.charAt(0) == '/' ? -1 : 0; while (slash != -1) { depth++; slash = path.indexOf(SEPARATOR, slash + 1); } return depth; } public boolean isAbsolute() { return isAbsolutePath(path); } /** * @return true if and only if this path represents the root of a file system */ public boolean isRoot() { return getParent() == null; } /** * Returns the final component of this path. */ public String getName() { int slash = path.lastIndexOf(SEPARATOR); return path.substring(slash + 1); } /** * Returns the parent of a path or null if at root. */ public Path getParent() { int lastSlash = path.lastIndexOf('/'); int start = 0; if ((path.length() == start) || // empty path (lastSlash == start && path.length() == start + 1)) { // at root return null; } String parent; if (lastSlash == -1) { parent = CUR_DIR; } else { int end = 0; parent = path.substring(0, lastSlash == end ? end + 1 : lastSlash); } return new Path(parent); } /** * Adds a suffix to the final name in the path. */ public Path suffix(String suffix) { return new Path(getParent(), getName() + suffix); } @Override public String toString() { return path; } @Override public boolean equals(Object o) { if (!(o instanceof Path)) { return false; } Path that = (Path) o; return this.path.equals(that.path); } @Override public int hashCode() { return path.hashCode(); } @Override public int compareTo(Object o) { Path that = (Path) o; return this.path.compareTo(that.path); } }