1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package org.apache.commons.net.nntp;
19
20 /**
21 * A placeholder utility class, used for constructing a tree of Threadables Original implementation by Jamie Zawinski. See the Grendel source for more details
22 * <a href="http://lxr.mozilla.org/mozilla/source/grendel/sources/grendel/view/Threader.java#511">here</a> Threadable objects
23 */
24 class NntpThreadContainer {
25 Threadable threadable;
26 NntpThreadContainer parent;
27 // NntpThreadContainer prev;
28 NntpThreadContainer next;
29 NntpThreadContainer child;
30
31 /**
32 *
33 * @param target
34 * @return true if child is under self's tree. Detects circular references
35 */
36 boolean findChild(final NntpThreadContainer target) {
37 if (child == null) {
38 return false;
39 }
40 if (child == target) {
41 return true;
42 }
43 return child.findChild(target);
44 }
45
46 // Copy the NntpThreadContainer tree structure down into the underlying Threadable objects
47 // (Make the Threadable tree look like the NntpThreadContainer tree)
48 // TODO convert this to an iterative function - this can blow the stack
49 // with very large Threadable trees
50 void flush() {
51 if (parent != null && threadable == null) {
52 throw new IllegalStateException("no threadable in " + this.toString());
53 }
54
55 parent = null;
56
57 if (threadable != null) {
58 threadable.setChild(child == null ? null : child.threadable);
59 }
60
61 if (child != null) {
62 child.flush();
63 child = null;
64 }
65
66 if (threadable != null) {
67 threadable.setNext(next == null ? null : next.threadable);
68 }
69
70 if (next != null) {
71 next.flush();
72 next = null;
73 }
74
75 threadable = null;
76 }
77
78 /**
79 * Reverse the entire set of children
80 *
81 */
82 void reverseChildren() {
83 if (child != null) {
84 NntpThreadContainer kid, prev, rest;
85 for (prev = null, kid = child, rest = kid.next; kid != null; prev = kid, kid = rest, rest = rest == null ? null : rest.next) {
86 kid.next = prev;
87 }
88
89 child = prev;
90
91 // Do it for the kids
92 for (kid = child; kid != null; kid = kid.next) {
93 kid.reverseChildren();
94 }
95 }
96 }
97 }