/* *******************************************************************
* Copyright (c) 1999-2001 Xerox Corporation,
* 2002 Palo Alto Research Center, Incorporated (PARC).
* 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:
* Xerox/PARC initial implementation
* ******************************************************************/
package org.aspectj.util;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
This class implements a partial order
It includes routines for doing a topo-sort
/**
* This class implements a partial order
*
* It includes routines for doing a topo-sort
*/
public class PartialOrder {
All classes that want to be part of a partial order must implement PartialOrder.PartialComparable.
/**
* All classes that want to be part of a partial order must implement PartialOrder.PartialComparable.
*/
public static interface PartialComparable {
@returns
- +1 if this is greater than other
- -1 if this is less than other
- 0 if this is not comparable to other
Note: returning 0 from this method doesn't mean the same thing as returning 0 from
java.util.Comparable.compareTo()
/**
* @returns <ul>
* <li>+1 if this is greater than other</li>
* <li>-1 if this is less than other</li>
* <li>0 if this is not comparable to other</li>
* </ul>
*
* <b> Note: returning 0 from this method doesn't mean the same thing as returning 0 from
* java.util.Comparable.compareTo()</b>
*/
public int compareTo(Object other);
This method can provide a deterministic ordering for elements that are strictly not comparable. If you have no need for
this, this method can just return 0 whenever called.
/**
* This method can provide a deterministic ordering for elements that are strictly not comparable. If you have no need for
* this, this method can just return 0 whenever called.
*/
public int fallbackCompareTo(Object other);
}
private static class SortObject<T extends PartialComparable> {
T object;
List<SortObject<T>> smallerObjects = new LinkedList<SortObject<T>>();
List<SortObject<T>> biggerObjects = new LinkedList<SortObject<T>>();
public SortObject(T o) {
object = o;
}
boolean hasNoSmallerObjects() {
return smallerObjects.size() == 0;
}
boolean removeSmallerObject(SortObject<T> o) {
smallerObjects.remove(o);
return hasNoSmallerObjects();
}
void addDirectedLinks(SortObject<T> other) {
int cmp = object.compareTo(other.object);
if (cmp == 0) {
return;
}
if (cmp > 0) {
this.smallerObjects.add(other);
other.biggerObjects.add(this);
} else {
this.biggerObjects.add(other);
other.smallerObjects.add(this);
}
}
public String toString() {
return object.toString(); // +smallerObjects+biggerObjects;
}
}
private static <T extends PartialComparable> void addNewPartialComparable(List<SortObject<T>> graph, T o) {
SortObject<T> so = new SortObject<T>(o);
for (Iterator<SortObject<T>> i = graph.iterator(); i.hasNext();) {
SortObject<T> other = i.next();
so.addDirectedLinks(other);
}
graph.add(so);
}
private static <T extends PartialComparable> void removeFromGraph(List<SortObject<T>> graph, SortObject<T> o) {
for (Iterator<SortObject<T>> i = graph.iterator(); i.hasNext();) {
SortObject<T> other = i.next();
if (o == other) {
i.remove();
}
// ??? could use this to build up a new queue of objects with no
// ??? smaller ones
other.removeSmallerObject(o);
}
}
Params: - objects – must all implement PartialComparable
@returns the same members as objects, but sorted according to their partial order. returns null if the objects are cyclical
/**
* @param objects must all implement PartialComparable
*
* @returns the same members as objects, but sorted according to their partial order. returns null if the objects are cyclical
*
*/
public static <T extends PartialComparable> List<T> sort(List<T> objects) {
// lists of size 0 or 1 don't need any sorting
if (objects.size() < 2) {
return objects;
}
// ??? we might want to optimize a few other cases of small size
// ??? I don't like creating this data structure, but it does give good
// ??? separation of concerns.
List<SortObject<T>> sortList = new LinkedList<SortObject<T>>();
for (Iterator<T> i = objects.iterator(); i.hasNext();) {
addNewPartialComparable(sortList, i.next());
}
// System.out.println(sortList);
// now we have built our directed graph
// use a simple sort algorithm from here
// can increase efficiency later
// List ret = new ArrayList(objects.size());
final int N = objects.size();
for (int index = 0; index < N; index++) {
// System.out.println(sortList);
// System.out.println("-->" + ret);
SortObject<T> leastWithNoSmallers = null;
for (SortObject<T> so: sortList) {
if (so.hasNoSmallerObjects()) {
if (leastWithNoSmallers == null || so.object.fallbackCompareTo(leastWithNoSmallers.object) < 0) {
leastWithNoSmallers = so;
}
}
}
if (leastWithNoSmallers == null) {
return null;
}
removeFromGraph(sortList, leastWithNoSmallers);
objects.set(index, leastWithNoSmallers.object);
}
return objects;
}
/* a minimal testing harness
/***********************************************************************************
* /* a minimal testing harness
***********************************************************************************/
static class Token implements PartialComparable {
private String s;
Token(String s) {
this.s = s;
}
public int compareTo(Object other) {
Token t = (Token) other;
int cmp = s.charAt(0) - t.s.charAt(0);
if (cmp == 1) {
return 1;
}
if (cmp == -1) {
return -1;
}
return 0;
}
public int fallbackCompareTo(Object other) {
return -s.compareTo(((Token) other).s);
}
public String toString() {
return s;
}
}
public static void main(String[] args) {
List<Token> l = new ArrayList<Token>();
l.add(new Token("a1"));
l.add(new Token("c2"));
l.add(new Token("b3"));
l.add(new Token("f4"));
l.add(new Token("e5"));
l.add(new Token("d6"));
l.add(new Token("c7"));
l.add(new Token("b8"));
l.add(new Token("z"));
l.add(new Token("x"));
l.add(new Token("f9"));
l.add(new Token("e10"));
l.add(new Token("a11"));
l.add(new Token("d12"));
l.add(new Token("b13"));
l.add(new Token("c14"));
System.out.println(l);
sort(l);
System.out.println(l);
}
}