blob: d44f5ed0af580d7c86c793845fcc4522c9c74a6b [file] [log] [blame]
/*****************************************************************************
* Copyright (c) 2015 Atos.
*
*
* 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:
* Tristan faure (Atos) - tristan.faure@atos.net - Initial API and implementation
*
*****************************************************************************/
package org.eclipse.gendoc.script.services.impl;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
/**
* Implementation of Topological Sort
* @author
*
* @param <N>
*/
public class TopologicalSort {
public static <N> List<N> sort (Collection<? extends N> list, Edge<N> edgeRetriever) throws CycleException {
if (edgeRetriever == null || list == null){
throw new IllegalArgumentException();
}
List<N> result = new LinkedList<N>();
Set<? super N> markedNodes = new HashSet<N>();
Set<? super N> unmarkedNodes = new HashSet<N>((Collection<? extends N>) list);
Set<? super N> temporaryNodes= new HashSet<N>();
while (!unmarkedNodes.isEmpty()){
// select an unmarked node
Iterator<? super N> i = unmarkedNodes.iterator();
N node = (N) i.next();
i.remove();
visit(result, node, edgeRetriever, unmarkedNodes, markedNodes, temporaryNodes);
}
return result ;
}
private static <N> void visit (List<? super N> result, N node, Edge<N> edgeRetriever,Set<? super N> unmark, Set<? super N> markedNodes, Set<? super N> temporaryNodes) throws CycleException {
if (temporaryNodes.contains(node)){
//throw new CycleException(node);
return;
}
if (!markedNodes.contains(node)){
markTmp (node, unmark, unmark, temporaryNodes);
List<? super N> outgoings = edgeRetriever.from(node);
if (outgoings != null){
for (Object o : outgoings){
N m = (N) o ;
visit(result, m, edgeRetriever,unmark,markedNodes,temporaryNodes);
}
mark(node, unmark, markedNodes, temporaryNodes);
unmarkTmp(node, unmark, markedNodes, temporaryNodes);
result.add(0,node);
}
}
}
private static <N> void unmarkTmp (N node, Set<? super N> unmark, Set<? super N> markedNodes, Set<? super N> temporaryNodes) {
unmark.add(node);
markedNodes.add(node);
temporaryNodes.remove(node);
}
private static <N> void markTmp (N node, Set<? super N> unmark, Set<? super N> markedNodes, Set<? super N> temporaryNodes) {
unmark.remove(node);
markedNodes.remove(node);
temporaryNodes.add(node);
}
private static <N> void mark (N node, Set<? super N> unmark, Set<? super N> markedNodes, Set<? super N> temporaryNodes) {
unmark.remove(node);
temporaryNodes.remove(node);
markedNodes.add(node);
}
private static <N> void unmark (N node, Set<? super N> unmark, Set<? super N> markedNodes, Set<? super N> temporaryNodes) {
unmark.add(node);
temporaryNodes.remove(node);
markedNodes.remove(node);
}
private static <N> Set<? super N> getAllNoIncomingEdges (Collection<? extends N> list, Edge<N> edgeRetriever) {
Set<? super N> result = new HashSet<N>();
for (Object o : list){
N n = (N) o ;
List<? super N> edges = edgeRetriever.from(n);
if (edges == null || edges.isEmpty()){
result.add(n);
}
}
return result;
}
public interface Edge<N> {
public List<? super N> from (N n) ;
}
public static class CycleException extends Exception {
private static final long serialVersionUID = 1L;
private Object node;
public CycleException(Object node) {
this.node = node;
}
public Object getNode (){
return node;
}
}
}