1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package de.fu_berlin.ties.util;
23
24 import org.apache.commons.lang.builder.ToStringBuilder;
25
26 /***
27 * An entry in a doubly linked list. Useful when you cannot use the
28 * {@link java.util.List} implementations, e.g. because you need direct
29 * references to list entries. This class only stores a reference to the
30 * previous and next entry for list management -- you must extend it so store
31 * any useful data.
32 *
33 * @author Christian Siefkes
34 * @version $Revision: 1.6 $, $Date: 2006/10/21 16:04:27 $, $Author: siefkes $
35 */
36 public class ListEntry {
37
38 /***
39 * Reference to the previous element in this list; <code>null</code> if this
40 * is the first element of a list.
41 */
42 private ListEntry previous = null;
43
44 /***
45 * Reference to the next element in this list; <code>null</code> if this
46 * is the final element of a list.
47 */
48 private ListEntry next = null;
49
50 /***
51 * Creates a new instance, without setting references to surrounding
52 * entries.
53 */
54 public ListEntry() {
55 this(null, null);
56 }
57
58 /***
59 * Creates a new instance.
60 *
61 * @param prevEntry a reference to the previous entry, must not yet have
62 * a next element; or <code>null</code> if this is the first entry in a list
63 * @param nextEntry a reference to the next entry, must not yet have
64 * a next element; or <code>null</code> if this is the final entry in a list
65 * @throws IllegalArgumentException if <code>prevEntry</code> already has
66 * a next element ({@link #hasNext()} == <code>true</code>) or if
67 * <code>nextEntry</code> already has a previous element
68 * ({@link #hasPrevious()} == <code>true</code>)
69 */
70 public ListEntry(final ListEntry prevEntry, final ListEntry nextEntry)
71 throws IllegalArgumentException {
72 super();
73
74 if (prevEntry != null) {
75 if (prevEntry.hasNext()) {
76 throw new IllegalArgumentException(
77 "Previous entry already has a next element!");
78 }
79 previous = prevEntry;
80 prevEntry.next = this;
81 }
82
83 if (nextEntry != null) {
84 if (nextEntry.hasPrevious()) {
85 throw new IllegalArgumentException(
86 "Next entry already has a previous element!");
87 }
88 next = nextEntry;
89 nextEntry.previous = this;
90 }
91 }
92
93 /***
94 * Returns <code>true</code> if there is a next element. (In other words,
95 * returns <code>true</code> if {@link #next()} would return an element
96 * rather than <code>null</code>.)
97 *
98 * @return <code>true</code> iff the list has more elements
99 */
100 public boolean hasNext() {
101 return (next != null);
102 }
103
104 /***
105 * Returns <code>true</code> if there is a previous element. (In other
106 * words, returns <code>true</code> if {@link #previous()} would return an
107 * element rather than <code>null</code>.)
108 *
109 * @return <code>true</code> iff the list has more elements
110 */
111 public boolean hasPrevious() {
112 return (previous != null);
113 }
114
115 /***
116 * Inserts a new element after the current one, adjusting the list structure
117 * accordingly. The new entry must not yet have a previous element (i.e.,
118 * calling {@link #hasPrevious()} must return <code>false</code>).
119 * The {@link #next()} element of either this entry or the new
120 * entry must be <code>null</code>.
121 * Inserting <code>null</code> elements is not allowed.
122 *
123 * @param newEntry the new list entry to insert
124 * @throws IllegalArgumentException if <code>newEntry</code> already has a
125 * previous element ({@link #hasPrevious()} == <code>true</code>) or
126 * both this entry and <code>newEntry</code> have a {@link #next()}
127 * element
128 * @throws NullPointerException if <code>newEntry</code> is
129 * <code>null</code>
130 */
131 public void insertAfter(final ListEntry newEntry)
132 throws IllegalArgumentException, NullPointerException {
133 if (newEntry.hasPrevious()) {
134 throw new IllegalArgumentException(
135 "Second entry already has a previous element!");
136 }
137 if (hasNext() && newEntry.hasNext()) {
138 throw new IllegalArgumentException(
139 "Both entries have a next element!");
140 }
141
142
143 if (next != null) {
144 next.previous = newEntry;
145 newEntry.next = next;
146 }
147 newEntry.previous = this;
148 next = newEntry;
149 }
150
151 /***
152 * Inserts a new element before the current one, adjusting the list
153 * structure accordingly. If this entry has a {@link #previous()} element,
154 * the {@link #next()} element of either the new entry or the
155 * {@link #previous()} element must be <code>null</code>; otherwise the
156 * {@link #next()} element of either this entry or the new entry must be
157 * <code>null</code>.
158 * Inserting <code>null</code> elements is not allowed.
159 *
160 * @param newEntry the new list entry to insert
161 * @throws IllegalArgumentException if the conditions stated above are
162 * violated
163 * @throws NullPointerException if <code>newEntry</code> is
164 * <code>null</code>
165 */
166 public void insertBefore(final ListEntry newEntry)
167 throws IllegalArgumentException, NullPointerException {
168 if (previous != null) {
169 previous.insertAfter(newEntry);
170 } else {
171 newEntry.insertAfter(this);
172 }
173 }
174
175 /***
176 * Returns the next element in the list, if any.
177 *
178 * @return the next element in the list, or <code>null</code> if there is
179 * no next element
180 */
181 public ListEntry next() {
182 return next;
183 }
184
185 /***
186 * Returns the previous element in the list, if any.
187 *
188 * @return the previous element in the list, or <code>null</code> if there
189 * is no previous element
190 */
191 public ListEntry previous() {
192 return previous;
193 }
194
195 /***
196 * Removes this entry from this list. The list structure
197 * is adjusted accordingly. Afterwards this entry won't be part of a
198 * list, i.e. both {@link #hasPrevious()} and {@link #hasNext()} will
199 * return <code>false</code>.
200 */
201 public void remove() {
202
203 if (next != null) {
204 next.previous = previous;
205 }
206 if (previous != null) {
207 previous.next = next;
208 }
209 next = null;
210 previous = null;
211 }
212
213 /***
214 * Returns a string representation of this object.
215 *
216 * @return a textual representation
217 */
218 public String toString() {
219 return new ToStringBuilder(this).
220 append("has previous", hasPrevious()).
221 append("has next", hasNext()).
222 toString();
223 }
224
225 }