1 /*
2 * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons-sandbox//xmlio/src/java/org/apache/commons/xmlio/in/SimplePath.java,v 1.1 2004/10/08 11:56:20 ozeigermann Exp $
3 * $Revision: 155476 $
4 * $Date: 2005-02-26 13:31:24 +0000 (Sat, 26 Feb 2005) $
5 *
6 * ====================================================================
7 *
8 * Copyright 2004 The Apache Software Foundation
9 *
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
13 *
14 * http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 *
22 */
23
24 package org.apache.commons.xmlio.in;
25
26 import java.util.Collection;
27 import java.util.Iterator;
28
29 /**
30 * <b>Rudimentary</b> representation of a path to an XML element.
31 * <br>
32 * Two paths match in two cases:
33 * <ol><li>If they are really equal in terms of the {@link #equals} method.
34 * <li>If the path to match to is relative, i.e. it has no leading '/' and it is the suffix of the matching path.
35 * </ol>
36 * <br>
37 * For example<br>
38 * <code>/root/tag</code> matches <code>/root/tag</code> and<br>
39 * <code>/root/tag</code> matches <code>tag</code>.
40 *
41 */
42 public class SimplePath {
43
44 protected final String path;
45 protected final Item[] pathList;
46
47 /** Strips off ending slash from a string if there is one. */
48 public final static String stripEndingSlash(String path) {
49 if (path != null && path.length() > 0 && path.charAt(path.length() - 1) == '/') {
50 return path.substring(0, path.length() - 1);
51 }
52 return path;
53 }
54
55 /** Creates a path object from a string describing it. The describing
56 * string uses '/' characters to seperate the paths parts.
57 */
58 public SimplePath(String path) {
59 this(path, null);
60 }
61
62 /** Creates a path object from a string describing it. The describing
63 * string uses '/' characters to seperate the paths parts.
64 */
65 public SimplePath(String path, Item[] pathList) {
66 this.path = stripEndingSlash(path);
67 this.pathList = pathList;
68 }
69
70 /** Copy ctor. */
71 public SimplePath(SimplePath path) {
72 this.path = stripEndingSlash(path.toString());
73 this.pathList = new Item[path.pathList.length];
74 System.arraycopy(path.pathList, 0, this.pathList, 0, path.pathList.length);
75 }
76
77 /**
78 * Checks if an item matches the last segment of this path.
79 */
80 public boolean matches(Item name) {
81 return (pathList != null && pathList.length > 0 && pathList[pathList.length - 1].equals(name));
82 }
83
84 /**
85 * Checks if the given array of items matches this path.
86 */
87 public boolean matches(Item[] path, boolean isRelative) {
88 if (pathList == null
89 || path == null
90 || path.length > pathList.length
91 || (!isRelative && path.length != pathList.length)) {
92 return false;
93 } else {
94 for (int i = path.length - 1; i >= 0; i--) {
95 if (!pathList[i].equals(path[i])) {
96 return false;
97 }
98 }
99 return true;
100 }
101 }
102
103 /**
104 * Checks if the given array of items matches this path from the root. The given path is to be considered relative.
105 * Useful to distinguish between something like /rootPath/valid/*\/valid and /rootPath/invalid/*\/valid. You will need two
106 * matches for this:
107 * <pre>
108 * matchesFromRoot(new Item[] { new Item("rootPath"), new Item("valid")})
109 * &&
110 * matches(new Item("valid"))
111 * </pre>
112 */
113 public boolean matchesFromRoot(Item[] path) {
114 if (pathList == null || path == null || path.length > pathList.length) {
115 return false;
116 } else {
117 for (int i = 0; i < path.length; i++) {
118 if (!pathList[i].equals(path[i])) {
119 return false;
120 }
121 }
122 return true;
123 }
124 }
125
126 /**
127 * Checks if the given array of items matches this path. The given path is to be considered relative.
128 */
129 public boolean matches(Item[] path) {
130 return matches(path, true);
131 }
132
133 /** Finds out if the the given path matches this one.
134 */
135 public boolean matches(SimplePath matchPath) {
136 return matches(matchPath.toString());
137 }
138
139 /** Finds out if the path represented by the given string matches this one.
140 * @see #matches(SimplePath)
141 */
142 public boolean matches(String matchPath) {
143 String matchString = stripEndingSlash(matchPath);
144
145 if (matchString != null && matchString.length() > 0 && matchString.charAt(0) != '/') {
146 // relative
147 return path.endsWith("/" + matchString);
148 } else {
149 // absolute
150 return path.equals(matchString);
151 }
152 }
153
154 /** Checks if this path matches any of the paths stored in
155 * <code>paths</code> collection. This means we iterate through
156 * <code>paths</code> and match every entry to this path.
157 */
158 public boolean matchsAny(Collection paths) {
159 for (Iterator it = paths.iterator(); it.hasNext();) {
160 SimplePath matchPath = (SimplePath) it.next();
161 if (matches(matchPath))
162 return true;
163 }
164 return false;
165 }
166
167 /** Checks if this path matches any of the paths stored in
168 * <code>paths</code> collection. This means we iterate through
169 * <code>paths</code> and match every entry to this path.
170 */
171 public boolean matchsAny(String[] paths) {
172 for (int i = 0; i < paths.length; i++) {
173 if (matches(paths[i]))
174 return true;
175 }
176 return false;
177 }
178
179 public String toString() {
180 return path;
181 }
182
183 public boolean equals(Object o) {
184 if (o instanceof String) {
185 return path.equals(o);
186 } else if (o instanceof SimplePath) {
187 return path.equals(((SimplePath) o).toString());
188 } else {
189 return false;
190 }
191 }
192
193 }