source: trunk/EventBenchCore/src/de/ugoe/cs/eventbench/models/TrieNode.java @ 106

Last change on this file since 106 was 106, checked in by sherbold, 13 years ago
  • code documentation
File size: 7.0 KB
Line 
1package de.ugoe.cs.eventbench.models;
2
3import java.io.Serializable;
4import java.security.InvalidParameterException;
5import java.util.Collection;
6import java.util.LinkedList;
7import java.util.List;
8
9import de.ugoe.cs.eventbench.models.Trie.Edge;
10import de.ugoe.cs.eventbench.models.Trie.TrieVertex;
11import de.ugoe.cs.util.StringTools;
12import edu.uci.ics.jung.graph.DelegateTree;
13import edu.uci.ics.jung.graph.Tree;
14
15/**
16 * <p>
17 * This class implements a node of a trie. Each node is associated with a symbol
18 * and has a counter. The counter marks the number of occurences of the sequence
19 * defined by the path from the root of the trie to this node.
20 * </p>
21 *
22 * @author Steffen Herbold
23 *
24 * @param <T>
25 *            Type of the symbols that are stored in the trie.
26 * @see Trie
27 */
28class TrieNode<T> implements Serializable {
29
30        /**
31         * <p>
32         * Id for object serialization.
33         * </p>
34         */
35        private static final long serialVersionUID = 1L;
36
37        /**
38         * <p>
39         * Counter for the number of occurences of the sequence.
40         * </p>
41         */
42        private int count;
43
44        /**
45         * <p>
46         * Symbol associated with the node.
47         * </p>
48         */
49        private final T symbol;
50
51        /**
52         * <p>
53         * Child nodes of this node. If the node is a leaf this collection is empty.
54         * </p>
55         */
56        private Collection<TrieNode<T>> children;
57
58        /**
59         * <p>
60         * Constructor. Creates a new TrieNode without a symbol associated.<br>
61         * <b>This constructor should only be used to create the root node of the
62         * trie!</b>
63         * </p>
64         */
65        TrieNode() {
66                this.symbol = null;
67                count = 0;
68                children = new LinkedList<TrieNode<T>>();
69        }
70
71        /**
72         * <p>
73         * Constructor. Creates a new TrieNode. The symbol must not be null.
74         * </p>
75         *
76         * @param symbol
77         *            symbol associated with the trie node
78         */
79        public TrieNode(T symbol) {
80                if (symbol == null) {
81                        throw new InvalidParameterException(
82                                        "symbol must not be null. null is reserved for root node!");
83                }
84                this.symbol = symbol;
85                count = 0;
86                children = new LinkedList<TrieNode<T>>();
87        }
88
89        /**
90         * <p>
91         * Adds a given subsequence to the trie and increases the counters
92         * accordingly.
93         * </p>
94         *
95         * @param subsequence
96         *            subsequence whose counters are increased
97         * @see Trie#add(List)
98         */
99        public void add(List<T> subsequence) {
100                if (!subsequence.isEmpty()) {
101                        if (!symbol.equals(subsequence.get(0))) { // should be guaranteed by
102                                                                                                                // the
103                                                                                                                // recursion/TrieRoot!
104                                throw new AssertionError("Invalid trie operation!");
105                        }
106                        count++;
107                        subsequence.remove(0);
108                        if (!subsequence.isEmpty()) {
109                                T nextSymbol = subsequence.get(0);
110                                getChildCreate(nextSymbol).add(subsequence);
111                        }
112                }
113        }
114
115        /**
116         * <p>
117         * Returns the symbol associated with the node.
118         * </p>
119         *
120         * @return symbol associated with the node
121         */
122        public T getSymbol() {
123                return symbol;
124        }
125
126        /**
127         * <p>
128         * Returns the number of occurences of the sequence represented by the node.
129         * </p>
130         *
131         * @return number of occurences of the sequence represented by the node
132         */
133        public int getCount() {
134                return count;
135        }
136
137        /**
138         * <p>
139         * Returns the child of the node associated with the given symbol or creates
140         * it if it does not exist yet.
141         * </p>
142         *
143         * @param symbol
144         *            symbol whose node is required
145         * @return node associated with the symbol
146         * @see Trie#getChildCreate(Object)
147         */
148        protected TrieNode<T> getChildCreate(T symbol) {
149                TrieNode<T> node = getChild(symbol);
150                if (node == null) {
151                        node = new TrieNode<T>(symbol);
152                        children.add(node);
153                }
154                return node;
155        }
156
157        /**
158         * <p>
159         * Returns the child of the node associated with the given symbol or null if
160         * it does not exist.
161         * </p>
162         *
163         * @param symbol
164         *            symbol whose node is required
165         * @return node associated with the symbol; null if no such node exists
166         * @see Trie#getChild(Object)
167         */
168        protected TrieNode<T> getChild(T symbol) {
169                for (TrieNode<T> child : children) {
170                        if (child.getSymbol().equals(symbol)) {
171                                return child;
172                        }
173                }
174                return null;
175        }
176
177        /**
178         * <p>
179         * Searches the sub-trie of this trie node for a given sequence and returns
180         * the node associated with the sequence or null if no such node is found.
181         * </p>
182         *
183         * @param sequence
184         *            sequence that is searched for
185         * @return node associated with the sequence
186         * @see Trie#find(List)
187         */
188        public TrieNode<T> find(List<T> subsequence) {
189                TrieNode<T> result = null;
190                if (subsequence.isEmpty()) {
191                        result = this;
192                } else {
193                        TrieNode<T> node = getChild(subsequence.get(0));
194                        if (node != null) {
195                                subsequence.remove(0);
196                                result = node.find(subsequence);
197                        }
198                }
199                return result;
200        }
201
202        /**
203         * <p>
204         * Returns a collection of all symbols that follow a this node, i.e., the
205         * symbols associated with the children of this node.
206         * </p>
207         *
208         * @return symbols follow this node
209         * @see TrieNode#getFollowingSymbols()
210         */
211        public Collection<T> getFollowingSymbols() {
212                Collection<T> followingSymbols = new LinkedList<T>();
213                for (TrieNode<T> child : children) {
214                        followingSymbols.add(child.getSymbol());
215                }
216                return followingSymbols;
217        }
218
219        /**
220         * <p>
221         * The string representation of a node is {@code symbol.toString()#count}
222         * </p>
223         *
224         * @see java.lang.Object#toString()
225         */
226        @Override
227        public String toString() {
228                String str = symbol.toString() + " #" + count;
229                if (!children.isEmpty()) {
230                        str += StringTools.ENDLINE + children.toString();
231                }
232                return str;
233        }
234
235        /**
236         * <p>
237         * Generates a {@link Tree} represenation of the trie.
238         * </p>
239         *
240         * @param parent
241         *            parent vertex in the generated tree
242         * @param graph
243         *            complete tree
244         */
245        void getGraph(TrieVertex parent, DelegateTree<TrieVertex, Edge> graph) {
246                TrieVertex currentVertex;
247                if (symbol == null) {
248                        currentVertex = new TrieVertex("root");
249                        graph.addVertex(currentVertex);
250                } else {
251                        currentVertex = new TrieVertex(getSymbol().toString() + "#"
252                                        + getCount());
253                        graph.addChild(new Edge(), parent, currentVertex);
254                }
255                for (TrieNode<T> node : children) {
256                        node.getGraph(currentVertex, graph);
257                }
258        }
259
260        /**
261         * <p>
262         * Appends the current node to the dot representation of the trie.
263         * </p>
264         *
265         * @param stringBuilder
266         *            {@link StringBuilder} to which the dot representation is
267         *            appended
268         */
269        void appendDotRepresentation(StringBuilder stringBuilder) {
270                String thisSaneId;
271                if (symbol == null) {
272                        thisSaneId = "root";
273                } else {
274                        thisSaneId = symbol.toString().replace("\"", "\\\"")
275                                        .replaceAll("[\r\n]", "")
276                                        + "#" + count;
277                }
278                stringBuilder.append(" " + hashCode() + " [label=\"" + thisSaneId
279                                + "\"];" + StringTools.ENDLINE);
280                for (TrieNode<T> childNode : children) {
281                        stringBuilder.append(" " + hashCode() + " -> "
282                                        + childNode.hashCode() + ";" + StringTools.ENDLINE);
283                }
284                for (TrieNode<T> childNode : children) {
285                        childNode.appendDotRepresentation(stringBuilder);
286                }
287        }
288}
Note: See TracBrowser for help on using the repository browser.