001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018: package org.apache.tools.ant.types.resources;
019:
020: import java.util.Stack;
021: import java.util.TreeMap;
022: import java.util.Iterator;
023: import java.util.Collection;
024: import java.util.Comparator;
025: import java.util.Collections;
026: import java.util.AbstractCollection;
027: import java.util.NoSuchElementException;
028:
029: import org.apache.tools.ant.Project;
030: import org.apache.tools.ant.BuildException;
031: import org.apache.tools.ant.types.DataType;
032: import org.apache.tools.ant.types.ResourceCollection;
033: import org.apache.tools.ant.types.resources.comparators.ResourceComparator;
034: import org.apache.tools.ant.types.resources.comparators.DelegatedResourceComparator;
035:
036: /**
037: * ResourceCollection that sorts another ResourceCollection.
038: * @since Ant 1.7
039: */
040: public class Sort extends BaseResourceCollectionWrapper {
041:
042: //sorted bag impl. borrowed from commons-collections TreeBag:
043: private static class SortedBag extends AbstractCollection {
044: private class MutableInt {
045: private int value = 0;
046: }
047:
048: private class MyIterator implements Iterator {
049: private Iterator keyIter = t.keySet().iterator();
050: private Object current;
051: private int occurrence;
052:
053: public synchronized boolean hasNext() {
054: return occurrence > 0 || keyIter.hasNext();
055: }
056:
057: public synchronized Object next() {
058: if (!hasNext()) {
059: throw new NoSuchElementException();
060: }
061: if (occurrence == 0) {
062: current = keyIter.next();
063: occurrence = ((MutableInt) t.get(current)).value;
064: }
065: --occurrence;
066: return current;
067: }
068:
069: public void remove() {
070: throw new UnsupportedOperationException();
071: }
072: }
073:
074: private TreeMap t;
075: private int size;
076:
077: SortedBag(Comparator c) {
078: t = new TreeMap(c);
079: }
080:
081: public synchronized Iterator iterator() {
082: return new MyIterator();
083: }
084:
085: public synchronized boolean add(Object o) {
086: if (size < Integer.MAX_VALUE) {
087: ++size;
088: }
089: MutableInt m = (MutableInt) (t.get(o));
090: if (m == null) {
091: m = new MutableInt();
092: t.put(o, m);
093: }
094: m.value++;
095: return true;
096: }
097:
098: public synchronized int size() {
099: return size;
100: }
101: }
102:
103: private DelegatedResourceComparator comp = new DelegatedResourceComparator();
104:
105: /**
106: * Sort the contained elements.
107: * @return a Collection of Resources.
108: */
109: protected synchronized Collection getCollection() {
110: ResourceCollection rc = getResourceCollection();
111: Iterator iter = rc.iterator();
112: if (!(iter.hasNext())) {
113: return Collections.EMPTY_SET;
114: }
115: SortedBag b = new SortedBag(comp);
116: while (iter.hasNext()) {
117: b.add(iter.next());
118: }
119: return b;
120: }
121:
122: /**
123: * Add a ResourceComparator to this Sort ResourceCollection.
124: * If multiple ResourceComparators are added, they will be processed in LIFO order.
125: * @param c the ResourceComparator to add.
126: */
127: public synchronized void add(ResourceComparator c) {
128: if (isReference()) {
129: throw noChildrenAllowed();
130: }
131: comp.add(c);
132: FailFast.invalidate(this );
133: }
134:
135: /**
136: * Overrides the BaseResourceCollectionContainer version
137: * to recurse on nested ResourceComparators.
138: * @param stk the stack of data types to use (recursively).
139: * @param p the project to use to dereference the references.
140: * @throws BuildException on error.
141: */
142: protected synchronized void dieOnCircularReference(Stack stk,
143: Project p) throws BuildException {
144: if (isChecked()) {
145: return;
146: }
147: if (isReference()) {
148: super .dieOnCircularReference(stk, p);
149: } else {
150: DataType.invokeCircularReferenceCheck(comp, stk, p);
151: setChecked(true);
152: }
153: }
154:
155: }
|