1 /* 2 * Copyright (C) 2007-2010 Júlio Vilmar Gesser. 3 * Copyright (C) 2011, 2013-2016 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 */ getParentNode()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 */ setParentNode(Node parentNode)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 */ getParentNodeForChildren()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 */ findAncestor(Class<N> type)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 */ findAncestor(Class<N> type, Predicate<N> predicate)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 */ isDescendantOf(Node ancestor)90 default boolean isDescendantOf(Node ancestor) { 91 return findAncestor(Node.class, n -> n == ancestor).isPresent(); 92 } 93 94 } 95