📄 path.java
字号:
/* * 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 org.apache.jackrabbit.name;import javax.jcr.PathNotFoundException;import java.util.ArrayList;import java.util.Arrays;import java.util.LinkedList;import java.io.Serializable;/** * The <code>Path</code> utility class provides misc. methods to resolve and * nornalize JCR-style item paths. * <p/> * Each path consistnes of path elements and is immutable. It has the following * properties: * <p/> * <code>isAbsolute()</code>:<br> * A path is absolute if the first path element denotes the root element '/'. * <p/> * <code>isNormalized()</code>:<br> * A path is normalized if all '.' and '..' path elements are resolved as much * as possible. If the path is absolute it is normalized if it contains * no such elements. For example the path '../../a' is normalized where as * '../../b/../a/.' is not. Normalized paths never have '.' elements. * Absolute normalized paths have no and relative normalized paths have no or * only leading '..' elements. * <p/> * <code>isCanonical()</code>:<br> * A path is canonical if its absolute and normalized. * <p/> * <h2>String representations</h2> * <p/> * The JCR path format is specified by JSR 170 as follows: * <pre> * path ::= properpath ['/'] * properpath ::= abspath | relpath * abspath ::= '/' relpath * relpath ::= pathelement | relpath '/' pathelement * pathelement ::= name | name '[' number ']' | '..' | '.' * number ::= (* An integer > 0 *) * name ::= simplename | prefixedname * simplename ::= onecharsimplename | * twocharsimplename | * threeormorecharname * prefixedname ::= prefix ':' localname * localname ::= onecharlocalname | * twocharlocalname | * threeormorecharname * onecharsimplename ::= (* Any Unicode character except: * '.', '/', ':', '[', ']', '*', * ''', '"', '|' or any whitespace * character *) * twocharsimplename ::= '.' onecharsimplename | * onecharsimplename '.' | * onecharsimplename onecharsimplename * onecharlocalname ::= nonspace * twocharlocalname ::= nonspace nonspace * threeormorecharname ::= nonspace string nonspace * prefix ::= (* Any valid XML Name *) * string ::= char | string char * char ::= nonspace | ' ' * nonspace ::= (* Any Unicode character except: * '/', ':', '[', ']', '*', * ''', '"', '|' or any whitespace * character *) * </pre> */public final class Path implements Serializable { static final long serialVersionUID = 7272485577196962560L; /** * the 'root' element. i.e. '/' */ public static final PathElement ROOT_ELEMENT = new RootElement(); /** * the 'current' element. i.e. '.' */ public static final PathElement CURRENT_ELEMENT = new CurrentElement(); /** * the 'parent' element. i.e. '..' */ public static final PathElement PARENT_ELEMENT = new ParentElement(); /** * the root path */ public static final Path ROOT = new Path(new PathElement[]{ROOT_ELEMENT}, true); /** * Constant representing an undefined index value */ public static final int INDEX_UNDEFINED = 0; /** * Constant representing the default (initial) index value. */ public static final int INDEX_DEFAULT = 1; /** * Constant defining the depth of the root path */ public static final int ROOT_DEPTH = 0; /** * the elements of this path */ private final PathElement[] elements; /** * flag indicating if this path is normalized */ private final boolean normalized; /** * flag indicating if this path is absolute */ private final boolean absolute; /** * the cached hashcode of this path */ private transient int hash = 0; /** * the cached 'toString' of this path */ private transient String string; /** * Private constructor * * @param elements * @param isNormalized */ private Path(PathElement[] elements, boolean isNormalized) { if (elements == null || elements.length == 0) { throw new IllegalArgumentException("Empty paths are not allowed"); } this.elements = elements; this.absolute = elements[0].denotesRoot(); this.normalized = isNormalized; } //------------------------------------------------------< factory methods > /** * Creates a new <code>Path</code> from the given <code>jcrPath</code> * string. If <code>normalize</code> is <code>true</code>, the returned * path will be normalized (or canonicalized if absolute). * * @param jcrPath * @param resolver * @param normalize * @throws MalformedPathException * @deprecated Use PathFormat#parse(String, NamespaceResolver)} instead. */ public static Path create(String jcrPath, NamespaceResolver resolver, boolean normalize) throws MalformedPathException { Path path = PathFormat.parse(jcrPath, resolver); if (normalize) { return path.getNormalizedPath(); } else { return path; } } /** * Creates a new <code>Path</code> out of the given <code>parent</code> path * and a relative path string. If <code>canonicalize</code> is * <code>true</code>, the returned path will be canonicalized. * * @param parent * @param relJCRPath * @param resolver * @param canonicalize * @throws MalformedPathException * @deprecated Use {@link PathFormat#parse(Path, String, NamespaceResolver)} instead. */ public static Path create(Path parent, String relJCRPath, NamespaceResolver resolver, boolean canonicalize) throws MalformedPathException { Path path = PathFormat.parse(parent, relJCRPath, resolver); if (canonicalize) { return path.getCanonicalPath(); } else { return path; } } /** * Creates a new <code>Path</code> out of the given <code>parent<code> path * string and the given relative path string. If <code>normalize</code> is * <code>true</code>, the returned path will be normalized (or * canonicalized, if the parent path is absolute). * * @param parent * @param relPath * @param normalize * @throws MalformedPathException if <code>relPath</code> is absolute */ public static Path create(Path parent, Path relPath, boolean normalize) throws MalformedPathException { if (relPath.isAbsolute()) { throw new MalformedPathException("relPath is not a relative path"); } PathBuilder pb = new PathBuilder(parent); pb.addAll(relPath.getElements()); Path path = pb.getPath(); if (normalize) { return path.getNormalizedPath(); } else { return path; } } /** * Creates a new <code>Path</code> out of the given <code>parent<code> path * string and the give name. If <code>normalize</code> is <code>true</code>, * the returned path will be normalized (or canonicalized, if the parent * path is absolute). * * @param parent the parent path * @param name the name of the new path element. * @param normalize * @return the new path. */ public static Path create(Path parent, QName name, boolean normalize) throws MalformedPathException { PathBuilder pb = new PathBuilder(parent); pb.addLast(name); Path path = pb.getPath(); if (normalize) { return path.getNormalizedPath(); } else { return path; } } /** * Creates a new <code>Path</code> out of the given <code>parent<code> path * and the give name and index. * * @param parent the paren tpath. * @param name the name of the new path element. * @param index the index of the new path element. * @param normalize * @return the new path. */ public static Path create(Path parent, QName name, int index, boolean normalize) throws MalformedPathException { PathBuilder pb = new PathBuilder(parent); pb.addLast(name, index); Path path = pb.getPath(); if (normalize) { return path.getNormalizedPath(); } else { return path; } } /** * Creates a relative path based on a {@link QName} and an index. * * @param name single {@link QName} for this relative path. * @param index index of the sinlge name element. * @return the relative path created from <code>name</code>. * @throws IllegalArgumentException if <code>index</code> is negative. */ public static Path create(QName name, int index) throws IllegalArgumentException { if (index < Path.INDEX_UNDEFINED) { throw new IllegalArgumentException("index must not be negative: " + index); } PathElement elem; if (index < Path.INDEX_DEFAULT) { elem = PathElement.create(name); } else { elem = PathElement.create(name, index); } return new Path(new PathElement[]{elem}, !elem.denotesCurrent()); } //------------------------------------------------------< utility methods > /** * Checks if <code>jcrPath</code> is a valid JCR-style absolute or relative * path. * * @param jcrPath the path to be checked * @throws MalformedPathException If <code>jcrPath</code> is not a valid * JCR-style path. * @deprecated Use {@link PathFormat#checkFormat(String)} instead. */ public static void checkFormat(String jcrPath) throws MalformedPathException { PathFormat.checkFormat(jcrPath); } //-------------------------------------------------------< public methods > /** * Tests whether this path represents the root path, i.e. "/". * * @return true if this path represents the root path; false otherwise. */ public boolean denotesRoot() { return absolute && elements.length == 1; } /** * Tests whether this path is absolute, i.e. whether it starts with "/". * * @return true if this path is absolute; false otherwise. */ public boolean isAbsolute() { return absolute; } /** * Tests whether this path is canonical, i.e. whether it is absolute and * does not contain redundant elements such as "." and "..". * * @return true if this path is canonical; false otherwise. * @see #isAbsolute() */ public boolean isCanonical() { return absolute && normalized; } /** * Tests whether this path is normalized, i.e. whether it does not * contain redundant elements such as "." and "..". * <p/> * Note that a normalized path can still contain ".." elements if they are * not redundant, e.g. "../../a/b/c" would be a normalized relative path, * whereas "../a/../../a/b/c" wouldn't (although they're semantically * equivalent). * * @return true if this path is normalized; false otherwise. * @see #getNormalizedPath() */ public boolean isNormalized() { return normalized; } /** * Returns the normalized path representation of this path. This typically * involves removing/resolving redundant elements such as "." and ".." from * the path, e.g. "/a/./b/.." will be normalized to "/a", "../../a/b/c/.." * will be normalized to "../../a/b", and so on. * <p/> * If the normalized path results in an empty path (eg: 'a/..') or if an * absolute path is normalized that would result in a 'negative' path * (eg: /a/../../) a MalformedPathException is thrown. * * @return a normalized path representation of this path * @throws MalformedPathException if the path cannot be normalized. * @see #isNormalized() */ public Path getNormalizedPath() throws MalformedPathException { if (isNormalized()) { return this; } LinkedList queue = new LinkedList(); PathElement last = PARENT_ELEMENT; for (int i = 0; i < elements.length; i++) { PathElement elem = elements[i];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -