TreeNode.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-4.0.0).
003  * Copyright (c) 2007-2017 Franz Wilhelmstötter
004  *
005  * Licensed under the Apache License, Version 2.0 (the "License");
006  * you may not use this file except in compliance with the License.
007  * You may obtain a copy of the License at
008  *
009  *      http://www.apache.org/licenses/LICENSE-2.0
010  *
011  * Unless required by applicable law or agreed to in writing, software
012  * distributed under the License is distributed on an "AS IS" BASIS,
013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014  * See the License for the specific language governing permissions and
015  * limitations under the License.
016  *
017  * Author:
018  *    Franz Wilhelmstötter (franz.wilhelmstoetter@gmail.com)
019  */
020 package io.jenetics.ext.util;
021 
022 import static java.lang.String.format;
023 import static java.util.Objects.requireNonNull;
024 
025 import java.io.Serializable;
026 import java.util.ArrayList;
027 import java.util.Iterator;
028 import java.util.List;
029 import java.util.Optional;
030 
031 import io.jenetics.util.Copyable;
032 
033 /**
034  * A general purpose node in a tree data-structure. The {@code TreeNode} is a
035  * mutable implementation of the {@link Tree} interface.
036  *
037  @param <T> the value type of the tree node
038  *
039  @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
040  @version 3.9
041  @since 3.9
042  */
043 public final class TreeNode<T>
044     implements
045         Tree<T, TreeNode<T>>,
046         Iterable<TreeNode<T>>,
047         Copyable<TreeNode<T>>,
048         Serializable
049 {
050     private static final long serialVersionUID = 1L;
051 
052     private T _value;
053     private TreeNode<T> _parent;
054     private List<TreeNode<T>> _children;
055 
056     /**
057      * Create a new tree node with no parent and children, but with the given
058      * user {@code value}.
059      *
060      @param value the user value of the new tree node
061      */
062     private TreeNode(final T value) {
063         _value = value;
064     }
065 
066 
067     /* *************************************************************************
068      * Basic operations
069      **************************************************************************/
070 
071     /**
072      * Sets the user object for this node.
073      *
074      @param value the node {@code value}
075      */
076     public void setValue(final T value) {
077         _value = value;
078     }
079 
080     /**
081      * Return the node value
082      *
083      @return the node value
084      */
085     @Override
086     public T getValue() {
087         return _value;
088     }
089 
090     /**
091      * Returns this node's parent if available.
092      *
093      @return the tree-node, or an empty value if this node has no parent
094      */
095     @Override
096     public Optional<TreeNode<T>> getParent() {
097         return Optional.ofNullable(_parent);
098     }
099 
100     /**
101      * Sets this node's parent, but does not change the parent's child array.
102      * This method is called from {@code insert()} and {@code remove()} to
103      * reassign a child's parent, and it should not be messaged from anywhere
104      * else.
105      *
106      @param parent this node's new parent
107      */
108     void setParent(final TreeNode<T> parent) {
109         _parent = parent;
110     }
111 
112     /**
113      * Returns the child at the specified index in this node's child array.
114      *
115      @param index   an index into this node's child array
116      @return the tree-node in this node's child array at the specified index
117      @throws ArrayIndexOutOfBoundsException  if the {@code index} is out of
118      *         bounds
119      */
120     @Override
121     public TreeNode<T> getChild(final int index) {
122         if (_children == null) {
123             throw new ArrayIndexOutOfBoundsException(format(
124                 "Child index is out of bounds: %s", index
125             ));
126         }
127 
128         return _children.get(index);
129     }
130 
131     @Override
132     public int childCount() {
133         return _children != null ? _children.size() 0;
134     }
135 
136     /**
137      * Return an iterator that traverses the subtree rooted at {@code this} node
138      * in pre-order. The first node returned by the iterator is {@code this}
139      * node.
140      <p>
141      * Modifying the tree by inserting, removing, or moving a node invalidates
142      * any iterator created before the modification.
143      *
144      @see #postorderIterator
145      @return an iterator for traversing the tree in pre-order
146      */
147     @Override
148     public Iterator<TreeNode<T>> iterator() {
149         return preorderIterator();
150     }
151 
152     /**
153      * Removes the {@code child} from its present parent (if it has one), sets
154      * the child's parent to this node, and then adds the child to this node's
155      * child array at index {@code index}. The new {@code child} must not be
156      * {@code null} and must not be an ancestor of {@code this} node.
157      *
158      @param index the index in the child array where this node is to be
159      *        inserted
160      @param child the sub-node to be inserted
161      @return {@code this} tree-node, for method chaining
162      @throws ArrayIndexOutOfBoundsException if {@code index} is out of bounds
163      @throws IllegalArgumentException if {@code child} is an ancestor of
164      *         {@code this} node
165      @throws NullPointerException if the given {@code child} is {@code null}
166      */
167     public TreeNode<T> insert(final int index, final TreeNode<T> child) {
168         requireNonNull(child);
169         if (isAncestor(child)) {
170             throw new IllegalArgumentException("The new child is an ancestor.");
171         }
172 
173         if (child._parent != null) {
174             child._parent.remove(child);
175         }
176 
177         child.setParent(this);
178         if (_children == null) {
179             _children = new ArrayList<>(2);
180         }
181         _children.add(index, child);
182 
183         TreeNode<T> parent = this;
184         while (parent != null) {
185             parent = parent._parent;
186         }
187 
188         return this;
189     }
190 
191     /**
192      * Removes the child at the specified index from this node's children and
193      * sets that node's parent to {@code null}. The child node to remove must be
194      * a {@code MutableTreeNode}.
195      *
196      @param index the index in this node's child array of the child to remove
197      @return {@code this} tree-node, for method chaining
198      @throws ArrayIndexOutOfBoundsException  if the {@code index} is out of
199      *         bounds
200      */
201     public TreeNode<T> remove(final int index) {
202         if (_children == null) {
203             throw new ArrayIndexOutOfBoundsException(format(
204                 "Child index is out of bounds: %s", index
205             ));
206         }
207 
208         final TreeNode<T> child = _children.remove(index);
209         assert child._parent == this;
210 
211         TreeNode<T> parent = this;
212         while (parent != null) {
213             parent = parent._parent;
214         }
215 
216         child.setParent(null);
217 
218         return this;
219     }
220 
221     /* *************************************************************************
222      * Derived operations
223      **************************************************************************/
224 
225     /**
226      * Detaches the subtree rooted at {@code this} node from the tree, giving
227      * {@code this} node a {@code null} parent. Does nothing if {@code this}
228      * node is the root of its tree.
229      *
230      @return {@code this}
231      */
232     public TreeNode<T> detach() {
233         if (_parent != null) {
234             _parent.remove(this);
235         }
236 
237         return this;
238     }
239 
240     /**
241      * Remove the {@code child} from {@code this} node's child array, giving it
242      * a {@code null} parent.
243      *
244      @param child the child of this node to remove
245      @throws NullPointerException if the given {@code child} is {@code null}
246      @throws IllegalArgumentException if the given {@code child} is not a
247      *         child of this node
248      */
249     public void remove(final TreeNode<T> child) {
250         requireNonNull(child);
251 
252         if (!isChild(child)) {
253             throw new IllegalArgumentException("The given child is not a child.");
254         }
255         remove(getIndex(child));
256     }
257 
258     /**
259      * Removes all children fo {@code this} node and setting their parents to
260      * {@code null}. If {@code this} node has no children, this method does
261      * nothing.
262      */
263     public void removeAllChildren() {
264         for (int i = 0; i < childCount(); ++i) {
265             remove(i);
266         }
267     }
268 
269     /**
270      * Remove the given {@code child} from its parent and makes it a child of
271      * this node by adding it to the end of this node's child array.
272      *
273      @param child the new child added to this node
274      @return {@code this} tree-node, for method chaining
275      @throws NullPointerException if the given {@code child} is {@code null}
276      */
277     public TreeNode<T> attach(final TreeNode<T> child) {
278         requireNonNull(child);
279 
280         if (child._parent == this) {
281             insert(childCount() 1, child);
282         else {
283             insert(childCount(), child);
284         }
285 
286         return this;
287     }
288 
289     /**
290      * Attaches the given {@code children} to {@code this} node.
291      *
292      @param children the children to attach to {@code this} node
293      @return {@code this} tree-node, for method chaining
294      @throws NullPointerException if the given {@code children} array is
295      *         {@code null}
296      */
297     @SafeVarargs
298     public final TreeNode<T> attach(final T... children) {
299         for (T child : children) {
300             attach(TreeNode.of(child));
301         }
302 
303         return this;
304     }
305 
306     /**
307      * Attaches the given {@code child} to {@code this} node.
308      *
309      @param child the child to attach to {@code this} node
310      @return {@code this} tree-node, for method chaining
311      */
312     public TreeNode<T> attach(final T child) {
313         return attach(TreeNode.of(child));
314     }
315 
316     @Override
317     public TreeNode<T> copy() {
318         return ofTree(this);
319     }
320 
321     @Override
322     public int hashCode() {
323         return Tree.hashCode(this);
324     }
325 
326     @Override
327     public boolean equals(final Object obj) {
328         return obj instanceof TreeNode<?> &&
329             Tree.equals(this, (TreeNode<?>)obj);
330     }
331 
332     @Override
333     public String toString() {
334         return Tree.toString(this);
335     }
336 
337 
338 
339     /* *************************************************************************
340      * Static factory methods.
341      **************************************************************************/
342 
343     /**
344      * Return a new {@code TreeNode} from the given source {@code tree}. The
345      * whole tree is copied.
346      *
347      @param tree the source tree the new tree-node is created from
348      @param <T> the tree value type
349      @return a new {@code TreeNode} from the given source {@code tree}
350      @throws NullPointerException if the source {@code tree} is {@code null}
351      */
352     public static <T> TreeNode<T> ofTree(final Tree<? extends T, ?> tree) {
353         final TreeNode<T> target = of(tree.getValue());
354         fill(tree, target);
355         return target;
356     }
357 
358     private static <T> void fill(
359         final Tree<? extends T, ?> source,
360         final TreeNode<T> target
361     ) {
362         source.childStream().forEachOrdered(child -> {
363             final TreeNode<T> targetChild = of(child.getValue());
364             target.attach(targetChild);
365             fill(child, targetChild);
366         });
367     }
368 
369     /**
370      * Return a new {@code TreeNode} with the given node {@code value}.
371      *
372      @param value the node value
373      @param <T> the tree-node type
374      @return a new tree-node
375      */
376     public static <T> TreeNode<T> of(final T value) {
377         return new TreeNode<>(value);
378     }
379 
380     /**
381      * Return a new {@code TreeNode} with a {@code null} tree value.
382      *
383      @param <T> the tree-node type
384      @return a new tree-node
385      */
386     public static <T> TreeNode<T> of() {
387         return new TreeNode<>(null);
388     }
389 
390 }