1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.common.util.tree;
17
18 import static com.google.common.base.Optional.absent;
19 import static com.google.common.base.Preconditions.checkArgument;
20 import static com.google.common.collect.Lists.newArrayList;
21 import static org.kuali.common.util.base.Precondition.checkNotNull;
22
23 import java.util.List;
24
25 import com.google.common.base.Optional;
26 import com.google.common.collect.ImmutableList;
27
28 public class MutableNode<T> extends AbstractNode<T> {
29
30 protected Optional<MutableNode<T>> mutableParent = absent();
31 protected List<MutableNode<T>> mutableChildren = newArrayList();
32 protected T element;
33
34 public static <T> MutableNode<T> of(T element) {
35 return new MutableNode<T>(element);
36 }
37
38 public static <T> MutableNode<T> copyOf(Node<T> node) {
39 MutableNode<T> mutable = new MutableNode<T>(node.getElement());
40 for (Node<T> child : node.getChildren()) {
41 mutable.add(copyOf(child));
42 }
43 return mutable;
44 }
45
46 protected MutableNode() {
47 }
48
49 public MutableNode(T element) {
50 setElement(element);
51 }
52
53 public void setElement(T element) {
54 checkNotNull(element, "element");
55 this.element = element;
56 }
57
58 @Override
59 public T getElement() {
60 return element;
61 }
62
63 @Override
64 public Optional<Node<T>> getParent() {
65 return Optional.<Node<T>> fromNullable(getMutableParent().orNull());
66 }
67
68 public Optional<MutableNode<T>> getMutableParent() {
69 return mutableParent;
70 }
71
72 protected void setMutableParent(Optional<MutableNode<T>> parent) {
73 this.mutableParent = parent;
74 }
75
76 protected void setParent(MutableNode<T> parent) {
77 setMutableParent(Optional.of(checkNotNull(parent, "parent")));
78 }
79
80
81
82
83 @Override
84 public List<Node<T>> getChildren() {
85 List<Node<T>> list = newArrayList();
86 for (Node<T> child : mutableChildren) {
87 list.add(child);
88 }
89 return ImmutableList.copyOf(list);
90 }
91
92 public void remove(MutableNode<T> child) {
93 boolean parent = isParent(checkNotNull(child, "child"));
94 checkArgument(parent, "remove can only be invoked with a current child of this node");
95 remove(mutableChildren.indexOf(child));
96 }
97
98 public void remove(int index) {
99 MutableNode<T> child = mutableChildren.get(index);
100 mutableChildren.remove(index);
101 child.setMutableParent(Optional.<MutableNode<T>> absent());
102 }
103
104 public void add(List<MutableNode<T>> children) {
105 for (MutableNode<T> child : checkNotNull(children, "children")) {
106 add(child);
107 }
108 }
109
110 public void add(MutableNode<T> child1, MutableNode<T> child2) {
111 add(ImmutableList.of(child1, child2));
112 }
113
114 public void add(MutableNode<T> child1, MutableNode<T> child2, MutableNode<T> child3) {
115 add(ImmutableList.of(child1, child2, child3));
116 }
117
118 public void add(MutableNode<T> child1, MutableNode<T> child2, MutableNode<T> child3, MutableNode<T> child4) {
119 add(ImmutableList.of(child1, child2, child3, child4));
120 }
121
122 public void add(MutableNode<T> child1, MutableNode<T> child2, MutableNode<T> child3, MutableNode<T> child4, MutableNode<T> child5) {
123 add(ImmutableList.of(child1, child2, child3, child4, child5));
124 }
125
126 public void add(MutableNode<T> child) {
127 checkNotNull(child, "child");
128 add(mutableChildren.size(), child);
129 }
130
131 public void add(int index, MutableNode<T> child) {
132
133 checkNotNull(child, "child");
134
135
136
137 int actualIndex = isChild(child) ? mutableChildren.size() - 1 : mutableChildren.size();
138
139
140 checkArgument(!isAncestor(child), "cannot be an ancestor of 'child'");
141
142
143
144 if (child.getMutableParent().isPresent()) {
145 child.getMutableParent().get().remove(child);
146 }
147
148
149 child.setParent(this);
150
151
152 mutableChildren.add(actualIndex, child);
153 }
154
155 public void removeAllChildren() {
156 for (int i = 0; i < mutableChildren.size(); i++) {
157 remove(i);
158 }
159 }
160
161
162
163
164 public void removeFromParent() {
165 Optional<MutableNode<T>> parent = getMutableParent();
166 if (parent.isPresent()) {
167 parent.get().remove(this);
168 }
169 }
170 }