All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bbottema.javareflection.util.graph.GraphHelper Maven / Gradle / Ivy

Go to download

Java Reflection provides a small package with nifty reflection features that will help with finding constructors, methods and value conversions

There is a newer version: 4.1.0
Show newest version
package org.bbottema.javareflection.util.graph;

import lombok.experimental.UtilityClass;
import org.jetbrains.annotations.NotNull;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Deque;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@UtilityClass
public final class GraphHelper {
	
	@SuppressWarnings("WeakerAccess")
	public static  boolean isPathPossible(Node startingPoint, Node destination) {
		return findPossiblePaths(startingPoint, destination, new ArrayDeque>(), new ArrayList>>(), true, 4);
	}
	
	@SuppressWarnings("WeakerAccess")
	public static  List>> findAllPathsAscending(Node startingPoint, Node destination) {
		List>> allPaths = new ArrayList<>();
		findPossiblePaths(startingPoint, destination, new ArrayDeque>(), allPaths, false, 4);
		Collections.sort(allPaths, NodePathComparator.INSTANCE()); // NodePathComparator needs the startingPoints included in the path
		removeStartingPoints(allPaths);
		return allPaths;
	}
	
	private static  void removeStartingPoints(List>> allPaths) {
		for (List> path : allPaths) {
			path.remove(0);
		}
	}
	
	@SuppressWarnings({"StatementWithEmptyBody"})
	private static  boolean findPossiblePaths(Node currentNode, Node destination, Deque> currentPath,
												 List>> possiblePathsSoFar, boolean returnOnFirstPathFound, int cutOffEdgeCount) {
		boolean foundAPath = false;
		
		if (!currentPath.contains(currentNode)) {
			currentPath.addLast(currentNode);
			
			if (currentNode.equals(destination)) {
				possiblePathsSoFar.add(new ArrayList<>(currentPath));
				foundAPath = true;
			} else if (currentPath.size() <= cutOffEdgeCount) {
				for (Node nextNode : currentNode.getToNodes().keySet()) {
					foundAPath |= findPossiblePaths(nextNode, destination, currentPath, possiblePathsSoFar, returnOnFirstPathFound, cutOffEdgeCount);
					if (foundAPath && returnOnFirstPathFound) {
						break;
					}
				}
			}
			currentPath.removeLast();
		} else {
			// cyclic path
		}
		
		return foundAPath;
	}
	
	@NotNull
	public static  Set> findReachableNodes(final Node fromNode) {
		Set> reachableNodes = new HashSet<>();
		findReachableNodes(fromNode, reachableNodes);
		reachableNodes.remove(fromNode); // in case of cyclic paths, remove fromNode
		return reachableNodes;
	}
	
	private static  void findReachableNodes(final Node currentNode, final Set> reachableNodesSoFar) {
		for (Node reachableNode : currentNode.getToNodes().keySet()) {
			if (reachableNodesSoFar.add(reachableNode)) {
				findReachableNodes(reachableNode, reachableNodesSoFar);
			}
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy