/******************************************************************************* * Copyright (c) 2009 Johannes Utzig. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Johannes Utzig - initial API and implementation *******************************************************************************/ package org.eclipse.buckminster.ui.dependency.visualizer.viewer.provider.internal; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.buckminster.core.metadata.model.BOMNode; /** * This helper class is used for shortest path calculation between two nodes. * * @author Johannes Utzig * */ public class ShortesPathCalculation { private static final Integer VERY_LARGE_NUMBER = Integer.valueOf(1000000000); /** * calculates the shortest path from the given root to the target node * * @param root * @param target * @return a list with the path segments */ public static List<BOMNode> calculatePath(BOMNode root, BOMNode target) { List<BOMNode> queue = new LinkedList<BOMNode>(); Set<BOMNode> nodes = new HashSet<BOMNode>(); LinkedList<BOMNode> orderedList = new LinkedList<BOMNode>(); queue.add(root); while (!queue.isEmpty()) { BOMNode head = queue.remove(0); if (!nodes.contains(head)) { nodes.add(head); orderedList.add(head); queue.addAll(head.getChildren()); } } List<BOMNode> path = internalCalulcation(orderedList, root, target); return path; } private static Map<BOMNode, Integer> initializeLengthMap(List<BOMNode> queue, BOMNode root) { Map<BOMNode, Integer> map = new HashMap<BOMNode, Integer>(); for (BOMNode bomNode : queue) { map.put(bomNode, VERY_LARGE_NUMBER); map.put(root, Integer.valueOf(0)); } return map; } private static List<BOMNode> internalCalulcation(List<BOMNode> queue, BOMNode root, BOMNode target) { Map<BOMNode, BOMNode> previous = new HashMap<BOMNode, BOMNode>(); Map<BOMNode, Integer> lengthMap = initializeLengthMap(queue, root); while (!queue.isEmpty()) { BOMNode head = queue.remove(0); List<BOMNode> outgoing = head.getChildren(); for (BOMNode current : outgoing) { int headLength = lengthMap.get(head).intValue(); int currentLength = lengthMap.get(current).intValue(); if (headLength + 1 < currentLength) { previous.put(current, head); lengthMap.put(current, Integer.valueOf(headLength + 1)); } } } List<BOMNode> path = new ArrayList<BOMNode>(previous.size()); while (previous.containsKey(target)) { path.add(target); target = previous.get(target); } path.add(target); return path; } }