001: // Copyright (C) 2003,2004,2005 by Object Mentor, Inc. All rights reserved.
002: // Released under the terms of the GNU General Public License version 2 or later.
003: package fitnesse.wiki;
004:
005: import fitnesse.util.StringUtil;
006: import static fitnesse.wiki.WikiPagePath.Mode.*;
007:
008: import java.io.Serializable;
009: import java.util.*;
010:
011: public class WikiPagePath implements Comparable, Cloneable,
012: Serializable {
013: public enum Mode {
014: ABSOLUTE, SUB_PAGE, BACKWARD_SEARCH, RELATIVE
015: }
016:
017: private LinkedList<String> names = new LinkedList<String>();
018: private Mode mode = RELATIVE;
019:
020: public WikiPagePath() {
021: }
022:
023: public WikiPagePath(String[] names) {
024: for (int i = 0; i < names.length; i++)
025: addName(names[i]);
026: }
027:
028: protected Object clone() throws CloneNotSupportedException {
029: WikiPagePath clone = new WikiPagePath();
030: clone.names = (LinkedList<String>) names.clone();
031: clone.mode = mode;
032: return clone;
033: }
034:
035: public WikiPagePath copy() {
036: try {
037: return (WikiPagePath) clone();
038: } catch (CloneNotSupportedException e) {
039: return null;
040: }
041: }
042:
043: public WikiPagePath(WikiPage page) throws Exception {
044: PageCrawler crawler = page.getPageCrawler();
045: while (!crawler.isRoot(page)) {
046: names.addFirst(page.getName());
047: page = page.getParent();
048: }
049: }
050:
051: public WikiPagePath(WikiPagePath path) {
052: mode = path.mode;
053: for (WikiPagePath p = path; !p.isEmpty(); p = p.getRest())
054: addName(p.getFirst());
055: }
056:
057: private WikiPagePath(List<String> names) {
058: this .names = new LinkedList<String>(names);
059: }
060:
061: public String getFirst() {
062: return isEmpty() ? null : (String) names.get(0);
063: }
064:
065: public WikiPagePath addName(String name) {
066: names.add(name);
067: return this ;
068: }
069:
070: public WikiPagePath addNameToFront(String name) {
071: names.addFirst(name);
072: return this ;
073: }
074:
075: public WikiPagePath getRest() {
076: int size = names.size();
077: return (size <= 1) ? new WikiPagePath() : new WikiPagePath(
078: names.subList(1, size));
079: }
080:
081: public boolean isEmpty() {
082: return names.size() == 0;
083: }
084:
085: public String last() {
086: return (String) (names.size() == 0 ? null : names.get(names
087: .size() - 1));
088: }
089:
090: public List<String> getNames() {
091: return names;
092: }
093:
094: public String toString() {
095: String prefix = "";
096: if (mode == ABSOLUTE)
097: prefix = ".";
098: else if (mode == SUB_PAGE)
099: prefix = ">";
100: else if (mode == BACKWARD_SEARCH)
101: prefix = "<";
102: return "(" + prefix + StringUtil.join(names, ".") + ")";
103: }
104:
105: public void pop() {
106: if (names.size() > 0)
107: names.removeLast();
108: }
109:
110: public WikiPagePath append(WikiPagePath childPath) {
111: WikiPagePath newPath = new WikiPagePath(this );
112: for (WikiPagePath p = childPath; !p.isEmpty(); p = p.getRest())
113: newPath.addName(p.getFirst());
114: return newPath;
115: }
116:
117: public boolean isAbsolute() {
118: return (mode == ABSOLUTE);
119: }
120:
121: public void makeAbsolute() {
122: mode = ABSOLUTE;
123: }
124:
125: public int hashCode() {
126: return StringUtil.join(names, "").hashCode();
127: }
128:
129: public WikiPagePath relativePath() {
130: if (isAbsolute()) {
131: WikiPagePath relativePath = new WikiPagePath(this );
132: relativePath.setPathMode(RELATIVE);
133: return relativePath;
134: } else
135: return this ;
136: }
137:
138: public int compareTo(Object o) {
139: if (o instanceof WikiPagePath) {
140: WikiPagePath p = (WikiPagePath) o;
141: String compressedName = StringUtil.join(names, "");
142: String compressedArgumentName = StringUtil
143: .join(p.names, "");
144: return compressedName.compareTo(compressedArgumentName);
145: }
146: return 1; // we are greater because we are the right type.
147: }
148:
149: public boolean equals(Object o) {
150: if (o instanceof WikiPagePath) {
151: WikiPagePath that = (WikiPagePath) o;
152: return mode == that.mode && this .names.equals(that.names);
153: }
154: return false;
155: }
156:
157: public WikiPagePath parentPath() {
158: WikiPagePath parentPath = new WikiPagePath(this );
159: parentPath.pop();
160: return parentPath;
161: }
162:
163: public boolean startsWith(WikiPagePath that) {
164: if (that.names.size() > names.size())
165: return false;
166:
167: Iterator this Iterator = names.iterator();
168: for (String name : that.names) {
169: Object this Next = this Iterator.next();
170: if (!this Next.equals(name))
171: return false;
172: }
173: return true;
174: }
175:
176: public WikiPagePath withNameAdded(String name) {
177: WikiPagePath path = new WikiPagePath(this );
178: path.addName(name);
179: return path;
180: }
181:
182: public WikiPagePath subtractFromFront(WikiPagePath operand) {
183: WikiPagePath difference = new WikiPagePath(this );
184: if (difference.startsWith(operand)) {
185: difference.setPathMode(Mode.RELATIVE);
186: for (String name : operand.getNames()) {
187: if (name.equals(difference.getFirst()))
188: difference.names.removeFirst();
189: else
190: break;
191: }
192: }
193: return difference;
194: }
195:
196: public void setPathMode(Mode mode) {
197: this .mode = mode;
198: }
199:
200: public boolean isSubPagePath() {
201: return mode == SUB_PAGE;
202: }
203:
204: public boolean isBackwardSearchPath() {
205: return mode == BACKWARD_SEARCH;
206: }
207:
208: }
|