Use local copy of latest bndlib code for pre-release testing purposes

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1347815 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/bundleplugin/src/main/java/aQute/lib/collections/EnumerationIterator.java b/bundleplugin/src/main/java/aQute/lib/collections/EnumerationIterator.java
new file mode 100644
index 0000000..ec7aec6
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/lib/collections/EnumerationIterator.java
@@ -0,0 +1,42 @@
+package aQute.lib.collections;
+
+import java.util.*;
+
+/**
+ * Simple facade for enumerators so they can be used in for loops.
+ * 
+ * @param <T>
+ */
+public class EnumerationIterator<T> implements Iterable<T>, Iterator<T> {
+	
+	public static <T> EnumerationIterator<T> iterator(Enumeration<T> e) {
+		return new EnumerationIterator<T>(e);
+	}
+	
+	final Enumeration<T>	enumerator;
+	volatile boolean		done	= false;
+
+	public EnumerationIterator(Enumeration<T> e) {
+		enumerator = e;
+	}
+
+	public synchronized Iterator<T> iterator() {
+		if (done)
+			throw new IllegalStateException("Can only be used once");
+		done = true;
+		return this;
+
+	}
+
+	public boolean hasNext() {
+		return enumerator.hasMoreElements();
+	}
+
+	public T next() {
+		return enumerator.nextElement();
+	}
+
+	public void remove() {
+		throw new UnsupportedOperationException("Does not support removes");
+	}
+}
diff --git a/bundleplugin/src/main/java/aQute/lib/collections/ExtList.java b/bundleplugin/src/main/java/aQute/lib/collections/ExtList.java
new file mode 100644
index 0000000..4c4f558
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/lib/collections/ExtList.java
@@ -0,0 +1,31 @@
+package aQute.lib.collections;
+
+import java.util.*;
+
+public class ExtList<T> extends ArrayList<T> {
+	private static final long	serialVersionUID	= 1L;
+
+	public ExtList(T ... ts) {
+		super(ts.length);
+		for (T t : ts){
+			add(t);
+		}
+	}
+	
+	public String join() {
+		return join(",");
+	}
+
+	public String join(String del) {
+		StringBuilder sb = new StringBuilder();
+		String d= "";
+		for ( T t : this) {
+			sb.append(d);
+			d=del;
+			if ( t != null)
+				sb.append(t.toString());
+		}
+		return sb.toString();
+	}
+
+}
diff --git a/bundleplugin/src/main/java/aQute/lib/collections/IteratorList.java b/bundleplugin/src/main/java/aQute/lib/collections/IteratorList.java
new file mode 100644
index 0000000..cb96d16
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/lib/collections/IteratorList.java
@@ -0,0 +1,12 @@
+package aQute.lib.collections;
+
+import java.util.*;
+
+public class IteratorList<T> extends ArrayList<T> {
+	private static final long	serialVersionUID	= 1L;
+
+	public IteratorList(Iterator<T> i){
+		while(i.hasNext())
+			add(i.next());
+	}
+}
diff --git a/bundleplugin/src/main/java/aQute/lib/collections/LineCollection.java b/bundleplugin/src/main/java/aQute/lib/collections/LineCollection.java
new file mode 100644
index 0000000..a04ab36
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/lib/collections/LineCollection.java
@@ -0,0 +1,54 @@
+package aQute.lib.collections;
+
+import java.io.*;
+import java.util.*;
+
+public class LineCollection implements Iterator<String>, Closeable {
+	final BufferedReader	reader;
+	String					next;
+
+	public LineCollection(InputStream in) throws IOException {
+		this(new InputStreamReader(in, "UTF8"));
+	}
+
+	public LineCollection(File in) throws IOException {
+		this(new InputStreamReader( new FileInputStream(in),"UTF-8"));
+	}
+
+	public LineCollection(Reader reader) throws IOException {
+		this(new BufferedReader(reader));
+	}
+
+	public LineCollection(BufferedReader reader) throws IOException {
+		this.reader = reader;
+		next = reader.readLine();
+	}
+
+	public boolean hasNext() {
+		return next != null;
+	}
+
+	public String next() {
+		if (next == null)
+			throw new IllegalStateException("Iterator has finished");
+		try {
+			String result = next;
+			next = reader.readLine();
+			if (next == null)
+				reader.close();
+			return result;
+		} catch (Exception e) {
+			// ignore
+			return null;
+		}
+	}
+
+	public void remove() {
+		if (next == null)
+			throw new UnsupportedOperationException("Cannot remove");
+	}
+
+	public void close() throws IOException {
+		reader.close();
+	}
+}
diff --git a/bundleplugin/src/main/java/aQute/lib/collections/Logic.java b/bundleplugin/src/main/java/aQute/lib/collections/Logic.java
new file mode 100644
index 0000000..75322dd
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/lib/collections/Logic.java
@@ -0,0 +1,22 @@
+package aQute.lib.collections;
+
+import java.util.*;
+
+public class Logic {
+	
+	public static <T> Collection<T> retain( Collection<T> first, Collection<T> ... sets) {
+		Set<T> result = new HashSet<T>(first);
+		for ( Collection<T> set : sets ) {
+			result.retainAll(set);
+		}
+		return result;
+	}
+	
+	public static <T> Collection<T> remove( Collection<T> first, Collection<T> ... sets) {
+		Set<T> result = new HashSet<T>(first);
+		for ( Collection<T> set : sets ) {
+			result.removeAll(set);
+		}
+		return result;
+	}
+}
diff --git a/bundleplugin/src/main/java/aQute/lib/collections/MultiMap.java b/bundleplugin/src/main/java/aQute/lib/collections/MultiMap.java
new file mode 100644
index 0000000..fcf28ac
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/lib/collections/MultiMap.java
@@ -0,0 +1,155 @@
+package aQute.lib.collections;
+
+import java.util.*;
+
+public class MultiMap<K,V> extends HashMap<K,List<V>> {
+	private static final long	serialVersionUID	= 1L;
+	final boolean noduplicates;
+	final Class<?> keyClass;
+	final Class<?> valueClass;
+	
+	final Set<V> EMPTY = Collections.emptySet();
+	
+	public MultiMap() {
+		noduplicates = false;
+		keyClass = Object.class;
+		valueClass = Object.class;
+	}
+	
+	public MultiMap(Class<K> keyClass, Class<V> valueClass, boolean noduplicates ) {
+		this.noduplicates = noduplicates;		
+		this.keyClass = keyClass;
+		this.valueClass = valueClass;
+	}
+	
+	@SuppressWarnings("unchecked") public boolean add( K key, V value ) {
+		assert keyClass.isInstance(key);
+		assert valueClass.isInstance(value);
+		
+		List<V> set = get(key);
+		if ( set == null) {
+			set=new ArrayList<V>();
+			if ( valueClass != Object.class) {
+				set = Collections.checkedList(set, (Class<V>)valueClass);
+			}
+			put(key,set);
+		}else {
+			if (noduplicates) {
+				if ( set.contains(value))
+					return false;
+			}
+		}
+		return set.add(value);
+	}
+	
+	@SuppressWarnings("unchecked") public boolean addAll( K key, Collection<? extends V> value ) {
+		assert keyClass.isInstance(key);
+		List<V> set = get(key);
+		if ( set == null) {
+			set=new ArrayList<V>();
+			if ( valueClass != Object.class) {
+				set = Collections.checkedList(set, (Class<V>)valueClass);
+			}
+			put(key,set);
+		} else
+		if ( noduplicates) {
+			boolean r=false;
+			for ( V v : value) {
+				assert valueClass.isInstance(v);
+				if ( !set.contains(value))
+					r|=set.add(v);
+			}
+			return r;
+		}
+		return set.addAll(value);
+	}
+	
+	public boolean remove( K key, V value ) {
+		assert keyClass.isInstance(key);
+		assert valueClass.isInstance(value);
+		
+		List<V> set = get(key);
+		if ( set == null) {
+			return false;
+		}
+		boolean result = set.remove(value);
+		if ( set.isEmpty())
+			remove(key);
+		return result;
+	}
+	
+	public boolean removeAll( K key, Collection<V> value ) {
+		assert keyClass.isInstance(key);
+		List<V> set = get(key);
+		if ( set == null) {
+			return false;
+		}
+		boolean result = set.removeAll(value);
+		if ( set.isEmpty())
+			remove(key);
+		return result;
+	}
+	
+	public Iterator<V> iterate(K key) {
+		assert keyClass.isInstance(key);
+		List<V> set = get(key);
+		if ( set == null)
+			return EMPTY.iterator();
+		return set.iterator();
+	}
+	
+	public Iterator<V> all() {
+		return new Iterator<V>() {
+			Iterator<List<V>> master = values().iterator();
+			Iterator<V> current = null;
+			
+			public boolean hasNext() {
+				if ( current == null || !current.hasNext()) {
+					if ( master.hasNext()) {
+						current = master.next().iterator();
+						return current.hasNext();
+					}
+					return false;
+				}
+				return true;
+			}
+
+			public V next() {
+				return current.next();
+			}
+
+			public void remove() {
+				current.remove();
+			}
+			
+		};
+	}
+	
+	public Map<K,V> flatten() {
+		Map<K,V> map = new LinkedHashMap<K,V>();
+		for ( Map.Entry<K, List<V>> entry : entrySet()) {
+			List<V> v = entry.getValue();
+			if ( v == null || v.isEmpty())
+				continue;
+
+			map.put(entry.getKey(), v.get(0));
+		}
+		return map;
+	}
+	
+	public MultiMap<V,K> transpose() {
+		MultiMap<V,K> inverted = new MultiMap<V,K>();
+		for ( Map.Entry<K, List<V>> entry : entrySet()) {
+			K key = entry.getKey();
+			
+			List<V> value = entry.getValue();
+			if ( value == null)
+				continue;
+			
+			for ( V v : value)
+				inverted.add(v, key);
+		}
+		
+		return inverted;
+	}
+}
diff --git a/bundleplugin/src/main/java/aQute/lib/collections/SortedList.java b/bundleplugin/src/main/java/aQute/lib/collections/SortedList.java
new file mode 100644
index 0000000..220d875
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/lib/collections/SortedList.java
@@ -0,0 +1,423 @@
+package aQute.lib.collections;
+
+import java.util.*;
+
+/**
+ * An immutbale list that sorts objects by their natural order or through a
+ * comparator. It has convenient methods/constructors to create it from
+ * collections and iterators.
+ * 
+ * Why not maintain the lists in their sorted form? Well, TreeMaps are quite
+ * expensive ... I once profiled bnd and was shocked how much memory the Jar
+ * class took due to the TreeMaps. I could not easily change it unfortunately.
+ * The other reason is that Parameters uses a LinkedHashMap because the
+ * preferred order should be the declaration order. However, sometimes you need
+ * to sort the keys by name.
+ * 
+ * Last, and most important reason, is that sometimes you do not know what
+ * collection you have or it is not available in a sort ordering (MultiMap for
+ * example) ... I found myself sorting these things over and over again and
+ * decided to just make an immutable SortedList that is easy to slice and dice
+ * 
+ * @param <T>
+ */
+@SuppressWarnings("unchecked") public class SortedList<T> implements SortedSet<T>, List<T> {
+	static SortedList<?>		empty		= new SortedList<Object>();
+
+	final T[]					list;
+	final int					start;
+	final int					end;
+	final Comparator<T>			cmp;
+	Class<?>					type;
+	static Comparator<Object>	comparator	= //
+
+											new Comparator<Object>() {
+												public int compare(Object o1, Object o2) {
+
+													if (o1 == o2)
+														return 0;
+
+													if (o1.equals(o2))
+														return 0;
+
+													return ((Comparable<Object>) o1).compareTo(o2);
+												}
+											};
+
+	class It implements ListIterator<T> {
+		int	n;
+
+		private It(int n) {
+			this.n = n;
+		}
+
+		public boolean hasNext() {
+			return n < end;
+		}
+
+		public T next() throws NoSuchElementException {
+			if (!hasNext()) {
+				throw new NoSuchElementException("");
+			}
+			return list[n++];
+		}
+
+		public boolean hasPrevious() {
+			return n > start;
+		}
+
+		public T previous() {
+			return get(n - 1);
+		}
+
+		public int nextIndex() {
+			return (n + 1 - start);
+		}
+
+		public int previousIndex() {
+			return (n - 1) - start;
+		}
+
+		@Deprecated public void remove() {
+			throw new UnsupportedOperationException("Immutable");
+		}
+
+		@Deprecated public void set(T e) {
+			throw new UnsupportedOperationException("Immutable");
+		}
+
+		@Deprecated public void add(T e) {
+			throw new UnsupportedOperationException("Immutable");
+		}
+	}
+
+	public SortedList(Collection<? extends Comparable<?>> x) {
+		this((Collection<T>) x, 0, x.size(), (Comparator<T>) comparator);
+	}
+
+	public SortedList(Collection<T> x, Comparator<T> cmp) {
+		this(x, 0, x.size(), cmp);
+	}
+
+	@SuppressWarnings("cast")
+	public SortedList(T... x) {
+		this((T[]) x.clone(), 0, x.length, (Comparator<T>) comparator);
+	}
+
+	@SuppressWarnings("cast")
+	public SortedList(Comparator<T> cmp, T... x) {
+		this((T[]) x.clone(), 0, x.length, cmp);
+	}
+
+	private SortedList(SortedList<T> other, int start, int end) {
+		this.list = other.list;
+		this.cmp = other.cmp;
+		this.start = start;
+		this.end = end;
+	}
+
+	public SortedList(T[] x, int start, int end, Comparator<T> comparator2) {
+		if (start > end) {
+			int tmp = start;
+			start = end;
+			end = tmp;
+		}
+		if (start < 0 || start >= x.length)
+			throw new IllegalArgumentException("Start is not in list");
+
+		if (end < 0 || end > x.length)
+			throw new IllegalArgumentException("End is not in list");
+
+		this.list = x.clone();
+		Arrays.sort(this.list, start, end, comparator2);
+		this.start = start;
+		this.end = end;
+		this.cmp = comparator2;
+	}
+
+	public SortedList(Collection<? extends T> x, int start, int end, Comparator<T> cmp) {
+		if (start > end) {
+			int tmp = start;
+			start = end;
+			end = tmp;
+		}
+		if (start < 0 || start > x.size())
+			throw new IllegalArgumentException("Start is not in list");
+
+		if (end < 0 || end > x.size())
+			throw new IllegalArgumentException("End is not in list");
+
+		this.list = (T[]) x.toArray();
+		Arrays.sort(this.list, start, end, cmp);
+		this.start = start;
+		this.end = end;
+		this.cmp = cmp;
+	}
+
+	private SortedList() {
+		list = null;
+		start = 0;
+		end = 0;
+		cmp = null;
+	}
+
+	public int size() {
+		return end - start;
+	}
+
+	public boolean isEmpty() {
+		return start == end;
+	}
+
+	@SuppressWarnings("cast")
+	public boolean contains(Object o) {
+		assert type != null & type.isInstance(o);
+		return indexOf((T) o) >= 0;
+	}
+
+	public Iterator<T> iterator() {
+		return new It(start);
+	}
+
+	public Object[] toArray() {
+		return list.clone();
+	}
+
+	@SuppressWarnings("hiding") public <T> T[] toArray(T[] a) {
+		if (a == null || a.length < list.length) {
+			return (T[]) list.clone();
+		}
+		System.arraycopy(list, 0, a, 0, list.length);
+		return a;
+	}
+
+	public boolean add(T e) {
+		throw new UnsupportedOperationException("Immutable");
+	}
+
+	public boolean remove(Object o) {
+		throw new UnsupportedOperationException("Immutable");
+	}
+
+	public boolean containsAll(Collection<?> c) {
+		if (c.isEmpty())
+			return true;
+
+		if (isEmpty())
+			return false;
+
+		// TODO take advantage of sorted nature for this
+
+		for (Object el : c) {
+			if (!contains(el))
+				return false;
+		}
+		return false;
+	}
+
+	public boolean addAll(Collection<? extends T> c) {
+		throw new UnsupportedOperationException("Immutable");
+	}
+
+	public boolean retainAll(Collection<?> c) {
+		throw new UnsupportedOperationException("Immutable");
+	}
+
+	public boolean removeAll(Collection<?> c) {
+		throw new UnsupportedOperationException("Immutable");
+	}
+
+	public void clear() {
+		throw new UnsupportedOperationException("Immutable");
+	}
+
+	public Comparator<? super T> comparator() {
+		return cmp;
+	}
+
+	public boolean isSubSet() {
+		return start > 0 && end < list.length;
+	}
+
+	public SortedList<T> subSet(T fromElement, T toElement) {
+		int start = indexOf(fromElement);
+		int end = indexOf(toElement);
+		if (isSubSet() && (start < 0 || end < 0))
+			throw new IllegalArgumentException("This list is a subset");
+		if (start < 0)
+			start = 0;
+		if (end < 0)
+			end = list.length;
+
+		return subList(start, end);
+	}
+
+	public int indexOf(Object o) {
+		assert type != null && type.isInstance(o);
+
+		int n = Arrays.binarySearch(list, (T) o, cmp);
+		if (n >= start && n < end)
+			return n - start;
+
+		return -1;
+	}
+
+	public SortedList<T> headSet(T toElement) {
+		int i = indexOf(toElement);
+		if (i < 0) {
+			if (isSubSet())
+				throw new IllegalArgumentException("This list is a subset");
+			i = end;
+		}
+
+		if (i == end)
+			return this;
+
+		return subList(0, i);
+	}
+
+	public SortedSet<T> tailSet(T fromElement) {
+		int i = indexOf(fromElement);
+		if (i < 0) {
+			if (isSubSet())
+				throw new IllegalArgumentException("This list is a subset");
+			i = start;
+		}
+
+		return subList(i, end);
+	}
+
+	public T first() {
+		if (isEmpty())
+			throw new NoSuchElementException("first");
+		return get(0);
+	}
+
+	public T last() {
+		if (isEmpty())
+			throw new NoSuchElementException("last");
+		return get(end - 1);
+	}
+
+	@Deprecated public boolean addAll(int index, Collection<? extends T> c) {
+		throw new UnsupportedOperationException("Immutable");
+	}
+
+	public T get(int index) {
+		return list[index + start];
+	}
+
+	@Deprecated public T set(int index, T element) {
+		throw new UnsupportedOperationException("Immutable");
+	}
+
+	@Deprecated public void add(int index, T element) {
+		throw new UnsupportedOperationException("Immutable");
+	}
+
+	@Deprecated public T remove(int index) {
+		throw new UnsupportedOperationException("Immutable");
+	}
+
+	public int lastIndexOf(Object o) {
+		int n = indexOf(o);
+		if (n < 0)
+			return -1;
+
+		while (cmp.compare(list[n], (T) o) == 0)
+			n++;
+
+		return n;
+	}
+
+	public ListIterator<T> listIterator() {
+		return new It(start);
+	}
+
+	public ListIterator<T> listIterator(int index) {
+		return new It(index + start);
+	}
+
+	public SortedList<T> subList(int fromIndex, int toIndex) {
+		fromIndex += start;
+		toIndex += start;
+
+		if (toIndex < fromIndex) {
+			int tmp = toIndex;
+			toIndex = fromIndex;
+			fromIndex = tmp;
+		}
+
+		toIndex = Math.max(0, toIndex);
+		toIndex = Math.min(toIndex, end);
+		fromIndex = Math.max(0, fromIndex);
+		fromIndex = Math.min(fromIndex, end);
+		if (fromIndex == start && toIndex == end)
+			return this;
+
+		return new SortedList<T>(this, fromIndex, toIndex);
+	}
+
+	@Deprecated public boolean equals(Object other) {
+		return super.equals(other);
+	}
+
+	@Deprecated public int hashCode() {
+		return super.hashCode();
+	}
+
+	public boolean isEqual(SortedList<T> list) {
+		if (size() != list.size())
+			return false;
+
+		for (int as = start, bs = list.start, al = size(); as < al && bs < al; as++, bs++) {
+			if (comparator.compare(this.list[as], this.list[bs]) != 0)
+				return false;
+		}
+		return true;
+	}
+
+	public Class<?> getType() {
+		return type;
+	}
+
+	public void setType(Class<?> type) {
+		this.type = type;
+	}
+
+	public String toString() {
+		StringBuilder sb = new StringBuilder();
+		sb.append("[");
+		String del = "";
+		for (T s : list) {
+			sb.append(del);
+			sb.append(s);
+			del = ", ";
+		}
+
+		sb.append("]");
+		return sb.toString();
+	}
+
+	public boolean hasDuplicates() {
+		if (list.length < 2)
+			return false;
+
+		T prev = list[0];
+		for (int i = 1; i < list.length; i++) {
+			if (prev.equals(list[i]))
+				return true;
+		}
+		return false;
+	}
+
+	public static <T extends Comparable<?>> SortedList<T> fromIterator(Iterator<T> it) {
+		IteratorList<T> l = new IteratorList<T>(it);
+		return new SortedList<T>(l);
+	}
+
+	public static <T> SortedList<T> fromIterator(Iterator<T> it, Comparator<T> cmp) {
+		IteratorList<T> l = new IteratorList<T>(it);
+		return new SortedList<T>(l, cmp);
+	}
+}
diff --git a/bundleplugin/src/main/java/aQute/lib/collections/packageinfo b/bundleplugin/src/main/java/aQute/lib/collections/packageinfo
new file mode 100644
index 0000000..3987f9c
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/lib/collections/packageinfo
@@ -0,0 +1 @@
+version 1.1