TreeNodePathIterator.java
01 /*
02  * Java Genetic Algorithm Library (jenetics-5.1.0).
03  * Copyright (c) 2007-2019 Franz Wilhelmstötter
04  *
05  * Licensed under the Apache License, Version 2.0 (the "License");
06  * you may not use this file except in compliance with the License.
07  * You may obtain a copy of the License at
08  *
09  *      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  * Author:
18  *    Franz Wilhelmstötter (franz.wilhelmstoetter@gmail.com)
19  */
20 package io.jenetics.ext.util;
21 
22 import static java.lang.String.format;
23 import static java.util.Objects.requireNonNull;
24 
25 import java.util.ArrayDeque;
26 import java.util.Deque;
27 import java.util.Iterator;
28 
29 /**
30  * Path (between nodes) iterator.
31  *
32  @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
33  @version 5.1
34  @since 3.9
35  */
36 final class TreeNodePathIterator<V, T extends Tree<V, T>>
37     implements Iterator<T>
38 {
39     private final Deque<T> _stack = new ArrayDeque<>();
40 
41     /**
42      * Create an iterator between two tree nodes.
43      *
44      @param ancestor the ancestor tree node
45      @param descendant the descendant tree node
46      @throws NullPointerException if one of the nodes is {@code null}
47      */
48     TreeNodePathIterator(
49         final Tree<?, ?> ancestor,
50         final T descendant
51     ) {
52         requireNonNull(ancestor);
53         _stack.push(requireNonNull(descendant));
54 
55         T current = descendant;
56         while (!current.identical(ancestor)) {
57             current = current.getParent().orElseThrow(() ->
58                 new IllegalArgumentException(format(
59                     "Node %s is not an ancestor of %s.",
60                     ancestor.getValue(), descendant.getValue()
61                 ))
62             );
63 
64             _stack.push(current);
65         }
66     }
67 
68     @Override
69     public boolean hasNext() {
70         return !_stack.isEmpty();
71     }
72 
73     @Override
74     public T next() {
75         return _stack.pop();
76     }
77 
78 }