Browse Source

Inherit from BaseResourceCollectionWrapper (not -Container);

improved sorting by hopefully reducing number of comparisons made.


git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@278500 13f79535-47bb-0310-9956-ffa450edef68
master
Matthew Jason Benson 20 years ago
parent
commit
c1a8cd521f
1 changed files with 97 additions and 27 deletions
  1. +97
    -27
      src/main/org/apache/tools/ant/types/resources/Sort.java

+ 97
- 27
src/main/org/apache/tools/ant/types/resources/Sort.java View File

@@ -18,10 +18,15 @@ package org.apache.tools.ant.types.resources;


import java.util.List; import java.util.List;
import java.util.Stack; import java.util.Stack;
import java.util.Vector;
import java.util.TreeMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Comparator;
import java.util.Collections; import java.util.Collections;
import java.util.AbstractCollection;
import java.util.NoSuchElementException;


import org.apache.tools.ant.Project; import org.apache.tools.ant.Project;
import org.apache.tools.ant.BuildException; import org.apache.tools.ant.BuildException;
@@ -33,49 +38,114 @@ import org.apache.tools.ant.types.resources.comparators.ResourceComparator;
* ResourceCollection that sorts another ResourceCollection. * ResourceCollection that sorts another ResourceCollection.
* @since Ant 1.7 * @since Ant 1.7
*/ */
public class Sort extends BaseResourceCollectionContainer {
private static final String ONE_NESTED_MESSAGE
= "Sorting is to be applied to exactly one nested resource collection.";
public class Sort extends BaseResourceCollectionWrapper {


private Stack compStack = new Stack();
private class MultiComparator implements Comparator {
private Vector v = null;
synchronized void add(ResourceComparator c) {
if (c == null) {
return;
}
v = (v == null) ? new Vector() : v;
v.add(c);
}
public synchronized int compare(Object o1, Object o2) {
int result = 0;
//if no nested, natural order:
if (v == null || v.size() == 0) {
result = ((Comparable) o1).compareTo((Comparable) o2);
} else {
for (Iterator i = v.iterator(); result == 0 && i.hasNext();) {
result = ((Comparator) i.next()).compare(o1, o2);
}
}
return result;
}
}

//sorted bag impl. borrowed from commons-collections TreeBag:
private class SortedBag extends AbstractCollection {
private class MutableInt {
int value = 0;
}
private class MyIterator implements Iterator {
private Iterator keyIter = t.keySet().iterator();
private Object current;
private int occurrence;
public synchronized boolean hasNext() {
return occurrence > 0 || keyIter.hasNext();
}
public synchronized Object next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
if (occurrence == 0) {
current = keyIter.next();
occurrence = ((MutableInt) t.get(current)).value;
}
--occurrence;
return current;
}
public void remove() {
throw new UnsupportedOperationException();
}
}
private TreeMap t;
private int size;

SortedBag(Comparator c) {
t = new TreeMap(c);
}
public synchronized Iterator iterator() {
return new MyIterator();
}
public synchronized boolean add(Object o) {
if (size < Integer.MAX_VALUE) {
++size;
}
MutableInt m = (MutableInt) (t.get(o));
if (m == null) {
m = new MutableInt();
t.put(o, m);
}
m.value++;
return true;
}
public synchronized int size() {
return size;
}
}

private MultiComparator comp = new MultiComparator();


/** /**
* Sort the contained elements. * Sort the contained elements.
* @return a Collection of Resources. * @return a Collection of Resources.
*/ */
protected Collection getCollection() {
List rcs = getResourceCollections();
if (rcs.size() != 1) {
throw new BuildException(ONE_NESTED_MESSAGE);
}
Iterator nested = ((ResourceCollection) (rcs.get(0))).iterator();
if (!(nested.hasNext())) {
protected synchronized Collection getCollection() {
ResourceCollection rc = getResourceCollection();
Iterator iter = rc.iterator();
if (!(iter.hasNext())) {
return Collections.EMPTY_SET; return Collections.EMPTY_SET;
} }
ArrayList al = new ArrayList();
while (nested.hasNext()) {
al.add(nested.next());
}
if (compStack.empty()) {
Collections.sort(al);
} else {
for (Stack s = (Stack) compStack.clone(); !s.empty();) {
Collections.sort(al, (ResourceComparator) s.pop());
}
SortedBag b = new SortedBag(comp);
while (iter.hasNext()) {
b.add(iter.next());
} }
return al;
return b;
} }


/** /**
* Add a ResourceComparator to this Sort ResourceCollection. * Add a ResourceComparator to this Sort ResourceCollection.
* If multiple ResourceComparator are added, they will be processed in LIFO order.
* If multiple ResourceComparators are added, they will be processed in LIFO order.
* @param c the ResourceComparator to add. * @param c the ResourceComparator to add.
*/ */
public void add(ResourceComparator c) {
public synchronized void add(ResourceComparator c) {
if (isReference()) { if (isReference()) {
throw noChildrenAllowed(); throw noChildrenAllowed();
} }
compStack.push(c);
comp.add(c);
FailFast.invalidate(this);
} }


/** /**
@@ -85,7 +155,7 @@ public class Sort extends BaseResourceCollectionContainer {
* @param p the project to use to dereference the references. * @param p the project to use to dereference the references.
* @throws BuildException on error. * @throws BuildException on error.
*/ */
protected void dieOnCircularReference(Stack stk, Project p)
protected synchronized void dieOnCircularReference(Stack stk, Project p)
throws BuildException { throws BuildException {
if (isChecked()) { if (isChecked()) {
return; return;
@@ -93,7 +163,7 @@ public class Sort extends BaseResourceCollectionContainer {
if (isReference()) { if (isReference()) {
super.dieOnCircularReference(stk, p); super.dieOnCircularReference(stk, p);
} else { } else {
for (Iterator i = compStack.iterator(); i.hasNext();) {
for (Iterator i = comp.v.iterator(); i.hasNext();) {
Object o = i.next(); Object o = i.next();
if (o instanceof DataType) { if (o instanceof DataType) {
stk.push(o); stk.push(o);


Loading…
Cancel
Save