/******************************************************************************* * Copyright (c) 2009, 2010 Fraunhofer IWU and others. * 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: * Fraunhofer IWU - initial API and implementation *******************************************************************************/ package net.enilink.composition.helpers; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; /** * Simple class that creates a topological ordering for a partial ordering given * by an {@link IPartialOrder}. * */ public class LinearExtension<T> { private static <T> void addSuccessorsToMinElements( IPartialOrder<T> partialOrder, T element, Map<T, Integer> predCount, List<T> minElements) { Collection<T> succs = partialOrder.getSuccessors(element); if (succs != null) { for (T succ : succs) { Integer inDegree = predCount.remove(succ); if (inDegree == null) { continue; } inDegree--; if (inDegree == 0) { minElements.add(succ); } else { predCount.put(succ, inDegree); } } } } public static <T> List<T> createLinearExtension( IPartialOrder<T> partialOrder) { return createLinearExtension(partialOrder, new ArrayList<T>()); } protected static <T> List<T> createLinearExtension( IPartialOrder<T> partialOrder, List<T> list) { // build mapping of in degrees for each node Map<T, Integer> predCount = new HashMap<T, Integer>(); List<T> minElements = new LinkedList<T>(); for (T element : partialOrder.getElements()) { predCount.put(element, 0); } for (T element : predCount.keySet()) { Collection<T> succs = partialOrder.getSuccessors(element); if (succs != null) { for (T succ : succs) { if (element.equals(succ)) { continue; } Integer p = predCount.get(succ); if (p == null) { // succ is not contained in // partialOrderProvider.getElements() continue; } else { p++; } predCount.put(succ, p); } } } for (Map.Entry<T, Integer> entry : predCount.entrySet()) { if (entry.getValue().intValue() == 0) { minElements.add(entry.getKey()); } } // create initial topological ordering while (!minElements.isEmpty()) { T firstElement = minElements.remove(0); T secondElement = null; if (minElements.isEmpty()) { // linearExt[j] = firstElement list.add(firstElement); } else { secondElement = minElements.remove(0); // linearExt[j - 1] = firstElement list.add(firstElement); // linearExt[j] = secondElement list.add(secondElement); } addSuccessorsToMinElements(partialOrder, firstElement, predCount, minElements); if (secondElement != null) { addSuccessorsToMinElements(partialOrder, secondElement, predCount, minElements); } } return list; } }