1/* 2 * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package jdk.javadoc.internal.doclets.toolkit.util; 27 28import javax.lang.model.element.PackageElement; 29import javax.lang.model.element.TypeElement; 30 31/** 32 * Abstraction for immutable relative paths. 33 * Paths always use '/' as a separator, and never begin or end with '/'. 34 * 35 * <p><b>This is NOT part of any supported API. 36 * If you write code that depends on this, you do so at your own risk. 37 * This code and its internal interfaces are subject to change or 38 * deletion without notice.</b> 39 */ 40public class DocPath { 41 private final String path; 42 43 /** The empty path. */ 44 public static final DocPath empty = new DocPath(""); 45 46 /** The empty path. */ 47 public static final DocPath parent = new DocPath(".."); 48 49 /** 50 * Create a path from a string. 51 */ 52 public static DocPath create(String p) { 53 return (p == null) || p.isEmpty() ? empty : new DocPath(p); 54 } 55 56 /** 57 * Return the path for a class. 58 * For example, if the class is java.lang.Object, 59 * the path is java/lang/Object.html. 60 */ 61 public static DocPath forClass(Utils utils, TypeElement typeElement) { 62 return (typeElement == null) 63 ? empty 64 : forPackage(utils.containingPackage(typeElement)).resolve(forName(utils, typeElement)); 65 } 66 67 /** 68 * Return the path for the simple name of the class. 69 * For example, if the class is java.lang.Object, 70 * the path is Object.html. 71 */ 72 public static DocPath forName(Utils utils, TypeElement typeElement) { 73 return (typeElement == null) ? empty : new DocPath(utils.getSimpleName(typeElement) + ".html"); 74 } 75 76 /** 77 * Return the path for the package of a class. 78 * For example, if the class is java.lang.Object, 79 * the path is java/lang. 80 */ 81 public static DocPath forPackage(Utils utils, TypeElement typeElement) { 82 return (typeElement == null) ? empty : forPackage(utils.containingPackage(typeElement)); 83 } 84 85 /** 86 * Return the path for a package. 87 * For example, if the package is java.lang, 88 * the path is java/lang. 89 */ 90 public static DocPath forPackage(PackageElement pkgElement) { 91 return pkgElement == null || pkgElement.isUnnamed() 92 ? empty 93 : DocPath.create(pkgElement.getQualifiedName().toString().replace('.', '/')); 94 } 95 96 /** 97 * Return the inverse path for a package. 98 * For example, if the package is java.lang, 99 * the inverse path is ../... 100 */ 101 public static DocPath forRoot(PackageElement pkgElement) { 102 String name = (pkgElement == null || pkgElement.isUnnamed()) 103 ? "" 104 : pkgElement.getQualifiedName().toString(); 105 return new DocPath(name.replace('.', '/').replaceAll("[^/]+", "..")); 106 } 107 108 /** 109 * Return the relative path from one package to another. 110 */ 111 public static DocPath relativePath(PackageElement from, PackageElement to) { 112 return forRoot(from).resolve(forPackage(to)); 113 } 114 115 protected DocPath(String p) { 116 path = (p.endsWith("/") ? p.substring(0, p.length() - 1) : p); 117 } 118 119 /** {@inheritDoc} */ 120 @Override 121 public boolean equals(Object other) { 122 return (other instanceof DocPath) && path.equals(((DocPath)other).path); 123 } 124 125 /** {@inheritDoc} */ 126 @Override 127 public int hashCode() { 128 return path.hashCode(); 129 } 130 131 public DocPath basename() { 132 int sep = path.lastIndexOf("/"); 133 return (sep == -1) ? this : new DocPath(path.substring(sep + 1)); 134 } 135 136 public DocPath parent() { 137 int sep = path.lastIndexOf("/"); 138 return (sep == -1) ? empty : new DocPath(path.substring(0, sep)); 139 } 140 141 /** 142 * Return the path formed by appending the specified string to the current path. 143 */ 144 public DocPath resolve(String p) { 145 if (p == null || p.isEmpty()) 146 return this; 147 if (path.isEmpty()) 148 return new DocPath(p); 149 return new DocPath(path + "/" + p); 150 } 151 152 /** 153 * Return the path by appending the specified path to the current path. 154 */ 155 public DocPath resolve(DocPath p) { 156 if (p == null || p.isEmpty()) 157 return this; 158 if (path.isEmpty()) 159 return p; 160 return new DocPath(path + "/" + p.getPath()); 161 } 162 163 /** 164 * Return the inverse path for this path. 165 * For example, if the path is a/b/c, the inverse path is ../../.. 166 */ 167 public DocPath invert() { 168 return new DocPath(path.replaceAll("[^/]+", "..")); 169 } 170 171 /** 172 * Return true if this path is empty. 173 */ 174 public boolean isEmpty() { 175 return path.isEmpty(); 176 } 177 178 public DocLink fragment(String fragment) { 179 return new DocLink(path, null, fragment); 180 } 181 182 public DocLink query(String query) { 183 return new DocLink(path, query, null); 184 } 185 186 /** 187 * Return this path as a string. 188 */ 189 // This is provided instead of using toString() to help catch 190 // unintended use of toString() in string concatenation sequences. 191 public String getPath() { 192 return path; 193 } 194} 195