1 | /* |
---|---|
2 | * Copyright (C) 2007-2010 JĂșlio Vilmar Gesser. |
3 | * Copyright (C) 2011, 2013-2020 The JavaParser Team. |
4 | * |
5 | * This file is part of JavaParser. |
6 | * |
7 | * JavaParser can be used either under the terms of |
8 | * a) the GNU Lesser General Public License as published by |
9 | * the Free Software Foundation, either version 3 of the License, or |
10 | * (at your option) any later version. |
11 | * b) the terms of the Apache License |
12 | * |
13 | * You should have received a copy of both licenses in LICENCE.LGPL and |
14 | * LICENCE.APACHE. Please refer to those files for details. |
15 | * |
16 | * JavaParser is distributed in the hope that it will be useful, |
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
19 | * GNU Lesser General Public License for more details. |
20 | */ |
21 | |
22 | package com.github.javaparser; |
23 | |
24 | import com.github.javaparser.ast.Node; |
25 | import com.github.javaparser.ast.observer.Observable; |
26 | |
27 | import java.util.Optional; |
28 | import java.util.function.Predicate; |
29 | |
30 | /** |
31 | * An object that can have a parent node. |
32 | */ |
33 | public interface HasParentNode<T> extends Observable { |
34 | |
35 | /** |
36 | * Returns the parent node, or {@code Optional.empty} if no parent is set. |
37 | */ |
38 | Optional<Node> getParentNode(); |
39 | |
40 | /** |
41 | * Sets the parent node. |
42 | * |
43 | * @param parentNode the parent node, or {@code null} to set no parent. |
44 | * @return return {@code this} |
45 | */ |
46 | T setParentNode(Node parentNode); |
47 | |
48 | /** |
49 | * Returns the parent node from the perspective of the children of this node. |
50 | * <p> |
51 | * That is, this method returns {@code this} for everything except {@code NodeList}. A {@code NodeList} returns its |
52 | * parent node instead. This is because a {@code NodeList} sets the parent of all its children to its own parent |
53 | * node (see {@link com.github.javaparser.ast.NodeList} for details). |
54 | */ |
55 | Node getParentNodeForChildren(); |
56 | |
57 | /** |
58 | * Walks the parents of this node and returns the first node of type {@code type}, or {@code empty()} if none is |
59 | * found. The given type may also be an interface type, such as one of the {@code NodeWith...} interface types. |
60 | */ |
61 | default <N> Optional<N> findAncestor(Class<N> type) { |
62 | return findAncestor(type, x -> true); |
63 | } |
64 | |
65 | /** |
66 | * Walks the parents of this node and returns the first node of type {@code type} that matches {@code predicate}, or |
67 | * {@code empty()} if none is found. The given type may also be an interface type, such as one of the |
68 | * {@code NodeWith...} interface types. |
69 | */ |
70 | default <N> Optional<N> findAncestor(Class<N> type, Predicate<N> predicate) { |
71 | Optional<Node> possibleParent = getParentNode(); |
72 | while (possibleParent.isPresent()) { |
73 | Node parent = possibleParent.get(); |
74 | if (type.isAssignableFrom(parent.getClass()) && predicate.test(type.cast(parent))) { |
75 | return Optional.of(type.cast(parent)); |
76 | } |
77 | possibleParent = parent.getParentNode(); |
78 | } |
79 | return Optional.empty(); |
80 | } |
81 | |
82 | /** |
83 | * Determines whether this {@code HasParentNode} node is a descendant of the given node. A node is <i>not</i> a |
84 | * descendant of itself. |
85 | * |
86 | * @param ancestor the node for which to determine whether it has this node as an ancestor. |
87 | * @return {@code true} if this node is a descendant of the given node, and {@code false} otherwise. |
88 | * @see Node#isAncestorOf(Node) |
89 | */ |
90 | default boolean isDescendantOf(Node ancestor) { |
91 | return findAncestor(Node.class, n -> n == ancestor).isPresent(); |
92 | } |
93 | |
94 | } |
95 |
Members