001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.reef.tang.util.walk; 020 021import org.apache.reef.tang.types.Traversable; 022 023/** 024 * Generic graph traversal. 025 */ 026public final class Walk { 027 028 /** 029 * This is a utility class that has only static methods - do not instantiate. 030 * 031 * @throws IllegalAccessException always. 032 */ 033 private Walk() throws IllegalAccessException { 034 throw new IllegalAccessException("Do not instantiate this class."); 035 } 036 037 /** 038 * Traverse the configuration (sub)tree in preorder, starting from the given node. 039 * FIXME: handle loopy graphs correctly! 040 * 041 * @param nodeVisitor node visitor. Can be null. 042 * @param edgeVisitor edge visitor. Can be null. 043 * @param node current node of the configuration tree. 044 * @return true if all nodes has been walked, false if visitor stopped early. 045 */ 046 public static <T extends Traversable<T>> boolean preorder( 047 final NodeVisitor<T> nodeVisitor, final EdgeVisitor<T> edgeVisitor, final T node) { 048 if (nodeVisitor != null && nodeVisitor.visit(node)) { 049 if (edgeVisitor != null) { 050 for (final T child : node.getChildren()) { 051 if (!(edgeVisitor.visit(node, child) 052 && preorder(nodeVisitor, edgeVisitor, child))) { 053 return false; 054 } 055 } 056 } else { 057 for (final T child : node.getChildren()) { 058 if (!preorder(nodeVisitor, null, child)) { 059 return false; 060 } 061 } 062 } 063 } 064 return true; 065 } 066}