Sync with latest bnd code for testing purposes

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1354104 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/ClauseListConverter.java b/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/ClauseListConverter.java
new file mode 100644
index 0000000..130b60b
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/ClauseListConverter.java
@@ -0,0 +1,31 @@
+package aQute.bnd.build.model.conversions;
+
+import java.util.*;
+import java.util.Map.Entry;
+
+import aQute.lib.osgi.*;
+import aQute.libg.header.*;
+import aQute.libg.tuple.*;
+
+public class ClauseListConverter<R> implements Converter<List<R>,String> {
+
+	private final Converter< ? extends R, ? super Pair<String,Attrs>>	itemConverter;
+
+	public ClauseListConverter(Converter< ? extends R, ? super Pair<String,Attrs>> itemConverter) {
+		this.itemConverter = itemConverter;
+	}
+
+	public List<R> convert(String input) throws IllegalArgumentException {
+		List<R> result = new ArrayList<R>();
+
+		Parameters header = new Parameters(input);
+		for (Entry<String,Attrs> entry : header.entrySet()) {
+			String key = Processor.removeDuplicateMarker(entry.getKey());
+			Pair<String,Attrs> pair = Pair.newInstance(key, entry.getValue());
+			result.add(itemConverter.convert(pair));
+		}
+
+		return result;
+	}
+
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/CollectionFormatter.java b/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/CollectionFormatter.java
new file mode 100644
index 0000000..d9f345a
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/CollectionFormatter.java
@@ -0,0 +1,47 @@
+package aQute.bnd.build.model.conversions;
+
+import java.util.*;
+
+public class CollectionFormatter<T> implements Converter<String,Collection< ? extends T>> {
+
+	private final String						separator;
+	private final Converter<String, ? super T>	itemFormatter;
+	private final String						emptyOutput;
+
+	public CollectionFormatter(String separator) {
+		this(separator, (String) null);
+	}
+
+	public CollectionFormatter(String separator, String emptyOutput) {
+		this(separator, new DefaultFormatter(), emptyOutput);
+	}
+
+	public CollectionFormatter(String separator, Converter<String, ? super T> itemFormatter) {
+		this(separator, itemFormatter, null);
+	}
+
+	public CollectionFormatter(String separator, Converter<String, ? super T> itemFormatter, String emptyOutput) {
+		this.separator = separator;
+		this.itemFormatter = itemFormatter;
+		this.emptyOutput = emptyOutput;
+	}
+
+	public String convert(Collection< ? extends T> input) throws IllegalArgumentException {
+		String result = null;
+		if (input != null) {
+			if (input.isEmpty()) {
+				result = emptyOutput;
+			} else {
+				StringBuilder buffer = new StringBuilder();
+				for (Iterator< ? extends T> iter = input.iterator(); iter.hasNext();) {
+					T item = iter.next();
+					buffer.append(itemFormatter.convert(item));
+					if (iter.hasNext())
+						buffer.append(separator);
+				}
+				result = buffer.toString();
+			}
+		}
+		return result;
+	}
+}
\ No newline at end of file
diff --git a/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/Converter.java b/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/Converter.java
new file mode 100644
index 0000000..8513f52
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/Converter.java
@@ -0,0 +1,5 @@
+package aQute.bnd.build.model.conversions;
+
+public interface Converter<R, T> {
+	R convert(T input) throws IllegalArgumentException;
+}
\ No newline at end of file
diff --git a/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/DefaultBooleanFormatter.java b/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/DefaultBooleanFormatter.java
new file mode 100644
index 0000000..f188569
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/DefaultBooleanFormatter.java
@@ -0,0 +1,26 @@
+package aQute.bnd.build.model.conversions;
+
+/**
+ * Formatter for booleans with a default value; if the input value matches the
+ * default then it is formatted to <code>null</code>.
+ * 
+ * @author Neil Bartlett
+ */
+public class DefaultBooleanFormatter implements Converter<String,Boolean> {
+
+	private final boolean	defaultValue;
+
+	public DefaultBooleanFormatter(boolean defaultValue) {
+		this.defaultValue = defaultValue;
+	}
+
+	public String convert(Boolean input) throws IllegalArgumentException {
+		String result = null;
+
+		if (input != null && input.booleanValue() != defaultValue)
+			result = input.toString();
+
+		return result;
+	}
+
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/DefaultFormatter.java b/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/DefaultFormatter.java
new file mode 100644
index 0000000..a552c0d
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/DefaultFormatter.java
@@ -0,0 +1,9 @@
+package aQute.bnd.build.model.conversions;
+
+public class DefaultFormatter implements Converter<String,Object> {
+
+	public String convert(Object input) throws IllegalArgumentException {
+		return input == null ? null : input.toString();
+	}
+
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/EnumConverter.java b/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/EnumConverter.java
new file mode 100644
index 0000000..4c94d3b
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/EnumConverter.java
@@ -0,0 +1,27 @@
+package aQute.bnd.build.model.conversions;
+
+public class EnumConverter<E extends Enum<E>> implements Converter<E,String> {
+
+	private final Class<E>	enumType;
+	private final E			defaultValue;
+
+	public static <E extends Enum<E>> EnumConverter<E> create(Class<E> enumType) {
+		return new EnumConverter<E>(enumType, null);
+	}
+
+	public static <E extends Enum<E>> EnumConverter<E> create(Class<E> enumType, E defaultValue) {
+		return new EnumConverter<E>(enumType, defaultValue);
+	}
+
+	private EnumConverter(Class<E> enumType, E defaultValue) {
+		this.enumType = enumType;
+		this.defaultValue = defaultValue;
+	}
+
+	public E convert(String input) throws IllegalArgumentException {
+		if (input == null)
+			return defaultValue;
+		return Enum.valueOf(enumType, input);
+	}
+
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/EnumFormatter.java b/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/EnumFormatter.java
new file mode 100644
index 0000000..8500a25
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/EnumFormatter.java
@@ -0,0 +1,53 @@
+package aQute.bnd.build.model.conversions;
+
+/**
+ * Formats an enum type. Outputs {@code null} when the value of the enum is
+ * equal to a default value.
+ * 
+ * @param <E>
+ * @author Neil Bartlett
+ */
+public class EnumFormatter<E extends Enum<E>> implements Converter<String,E> {
+
+	private final E			defaultValue;
+
+	/**
+	 * Construct a new formatter with no default value, i.e. any non-null value
+	 * of the enum will print that value.
+	 * 
+	 * @param enumType
+	 *            The enum type.
+	 * @return
+	 */
+	public static <E extends Enum<E>> EnumFormatter<E> create(Class<E> enumType) {
+		return new EnumFormatter<E>(null);
+	}
+
+	/**
+	 * Construct a new formatter with the specified default value.
+	 * 
+	 * @param enumType
+	 *            The enum type.
+	 * @param defaultValue
+	 *            The default value, which will never be output.
+	 * @return
+	 */
+	public static <E extends Enum<E>> EnumFormatter<E> create(Class<E> enumType, E defaultValue) {
+		return new EnumFormatter<E>(defaultValue);
+	}
+
+	private EnumFormatter(E defaultValue) {
+		this.defaultValue = defaultValue;
+	}
+
+	public String convert(E input) throws IllegalArgumentException {
+		String result;
+		if (input == defaultValue || input == null)
+			result = null;
+		else {
+			result = input.toString();
+		}
+		return result;
+	}
+
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/HeaderClauseConverter.java b/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/HeaderClauseConverter.java
new file mode 100644
index 0000000..dfb3a5d
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/HeaderClauseConverter.java
@@ -0,0 +1,13 @@
+package aQute.bnd.build.model.conversions;
+
+import aQute.bnd.build.model.clauses.*;
+import aQute.libg.header.*;
+import aQute.libg.tuple.*;
+
+public class HeaderClauseConverter implements Converter<HeaderClause,Pair<String,Attrs>> {
+
+	public HeaderClause convert(Pair<String,Attrs> input) throws IllegalArgumentException {
+		return new HeaderClause(input.getFirst(), input.getSecond());
+	}
+
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/HeaderClauseFormatter.java b/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/HeaderClauseFormatter.java
new file mode 100644
index 0000000..f4161f5
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/HeaderClauseFormatter.java
@@ -0,0 +1,11 @@
+package aQute.bnd.build.model.conversions;
+
+import aQute.bnd.build.model.clauses.*;
+
+public class HeaderClauseFormatter implements Converter<String,HeaderClause> {
+	public String convert(HeaderClause input) throws IllegalArgumentException {
+		StringBuilder buffer = new StringBuilder();
+		input.formatTo(buffer);
+		return buffer.toString();
+	}
+}
\ No newline at end of file
diff --git a/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/HeaderClauseListConverter.java b/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/HeaderClauseListConverter.java
new file mode 100644
index 0000000..65d8471
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/HeaderClauseListConverter.java
@@ -0,0 +1,11 @@
+package aQute.bnd.build.model.conversions;
+
+import aQute.bnd.build.model.clauses.*;
+
+public class HeaderClauseListConverter extends ClauseListConverter<HeaderClause> {
+
+	public HeaderClauseListConverter() {
+		super(new HeaderClauseConverter());
+	}
+
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/MapFormatter.java b/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/MapFormatter.java
new file mode 100644
index 0000000..03d6f71
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/MapFormatter.java
@@ -0,0 +1,18 @@
+package aQute.bnd.build.model.conversions;
+
+import java.util.*;
+import java.util.Map.Entry;
+
+public class MapFormatter implements Converter<String,Map<String,String>> {
+
+	private CollectionFormatter<Entry<String,String>>	entrySetFormatter;
+
+	public MapFormatter(String listSeparator, Converter<String, ? super Entry<String,String>> entryFormatter,
+			String emptyOutput) {
+		entrySetFormatter = new CollectionFormatter<Entry<String,String>>(listSeparator, entryFormatter, emptyOutput);
+	}
+
+	public String convert(Map<String,String> input) throws IllegalArgumentException {
+		return entrySetFormatter.convert(input.entrySet());
+	}
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/NewlineEscapedStringFormatter.java b/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/NewlineEscapedStringFormatter.java
new file mode 100644
index 0000000..790cda0
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/NewlineEscapedStringFormatter.java
@@ -0,0 +1,33 @@
+package aQute.bnd.build.model.conversions;
+
+import aQute.bnd.build.model.*;
+
+public class NewlineEscapedStringFormatter implements Converter<String,String> {
+
+	public String convert(String input) throws IllegalArgumentException {
+		if (input == null)
+			return null;
+
+		// Shortcut the result for the majority of cases where there is no
+		// newline
+		if (input.indexOf('\n') == -1)
+			return input;
+
+		// Build a new string with newlines escaped
+		StringBuilder result = new StringBuilder();
+		int position = 0;
+		while (position < input.length()) {
+			int newlineIndex = input.indexOf('\n', position);
+			if (newlineIndex == -1) {
+				result.append(input.substring(position));
+				break;
+			}
+			result.append(input.substring(position, newlineIndex));
+			result.append(BndEditModel.LINE_SEPARATOR);
+			position = newlineIndex + 1;
+		}
+
+		return result.toString();
+	}
+
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/NoopConverter.java b/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/NoopConverter.java
new file mode 100644
index 0000000..7a9f39d
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/NoopConverter.java
@@ -0,0 +1,7 @@
+package aQute.bnd.build.model.conversions;
+
+public class NoopConverter<T> implements Converter<T,T> {
+	public T convert(T input) throws IllegalArgumentException {
+		return input;
+	}
+}
\ No newline at end of file
diff --git a/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/PropertiesConverter.java b/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/PropertiesConverter.java
new file mode 100644
index 0000000..a1ecf5f
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/PropertiesConverter.java
@@ -0,0 +1,13 @@
+package aQute.bnd.build.model.conversions;
+
+import java.util.*;
+
+import aQute.libg.header.*;
+
+public class PropertiesConverter implements Converter<Map<String,String>,String> {
+
+	public Map<String,String> convert(String input) throws IllegalArgumentException {
+		return OSGiHeader.parseProperties(input);
+	}
+
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/PropertiesEntryFormatter.java b/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/PropertiesEntryFormatter.java
new file mode 100644
index 0000000..b487190
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/PropertiesEntryFormatter.java
@@ -0,0 +1,26 @@
+package aQute.bnd.build.model.conversions;
+
+import java.util.Map.Entry;
+
+public class PropertiesEntryFormatter implements Converter<String,Entry<String,String>> {
+	public String convert(Entry<String,String> entry) {
+		StringBuilder buffer = new StringBuilder();
+
+		String name = entry.getKey();
+		buffer.append(name).append('=');
+
+		String value = entry.getValue();
+		if (value != null && value.length() > 0) {
+			int quotableIndex = value.indexOf(',');
+			if (quotableIndex == -1)
+				quotableIndex = value.indexOf('=');
+
+			if (quotableIndex >= 0) {
+				buffer.append('\'').append(value).append('\'');
+			} else {
+				buffer.append(value);
+			}
+		}
+		return buffer.toString();
+	}
+}
\ No newline at end of file
diff --git a/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/SimpleListConverter.java b/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/SimpleListConverter.java
new file mode 100644
index 0000000..2291be3
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/SimpleListConverter.java
@@ -0,0 +1,41 @@
+package aQute.bnd.build.model.conversions;
+
+import java.util.*;
+
+import aQute.lib.osgi.*;
+import aQute.libg.qtokens.*;
+
+public class SimpleListConverter<R> implements Converter<List<R>,String> {
+
+	private Converter< ? extends R, ? super String>	itemConverter;
+
+	public static <R> Converter<List<R>,String> create(Converter<R, ? super String> itemConverter) {
+		return new SimpleListConverter<R>(itemConverter);
+	}
+
+	public static Converter<List<String>,String> create() {
+		return new SimpleListConverter<String>(new NoopConverter<String>());
+	}
+
+	private SimpleListConverter(Converter< ? extends R, ? super String> itemConverter) {
+		this.itemConverter = itemConverter;
+	}
+
+	public List<R> convert(String input) throws IllegalArgumentException {
+		List<R> result = new ArrayList<R>();
+
+		if (Constants.EMPTY_HEADER.equalsIgnoreCase(input.trim()))
+			return result;
+
+		QuotedTokenizer qt = new QuotedTokenizer(input, ",");
+		String token = qt.nextToken();
+
+		while (token != null) {
+			result.add(itemConverter.convert(token.trim()));
+			token = qt.nextToken();
+		}
+
+		return result;
+	}
+
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/StringEntryConverter.java b/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/StringEntryConverter.java
new file mode 100644
index 0000000..c857ddc
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/StringEntryConverter.java
@@ -0,0 +1,11 @@
+package aQute.bnd.build.model.conversions;
+
+import java.util.Map.Entry;
+
+public class StringEntryConverter implements Converter<String,Entry<String, ? >> {
+
+	public String convert(Entry<String, ? > input) throws IllegalArgumentException {
+		return input.getKey();
+	}
+
+}
diff --git a/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/VersionedClauseConverter.java b/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/VersionedClauseConverter.java
new file mode 100644
index 0000000..5aead1c
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/VersionedClauseConverter.java
@@ -0,0 +1,11 @@
+package aQute.bnd.build.model.conversions;
+
+import aQute.bnd.build.model.clauses.*;
+import aQute.libg.header.*;
+import aQute.libg.tuple.*;
+
+public class VersionedClauseConverter implements Converter<VersionedClause,Pair<String,Attrs>> {
+	public VersionedClause convert(Pair<String,Attrs> input) throws IllegalArgumentException {
+		return new VersionedClause(input.getFirst(), input.getSecond());
+	}
+}
\ No newline at end of file
diff --git a/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/packageinfo b/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/packageinfo
new file mode 100644
index 0000000..55af8e5
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/bnd/build/model/conversions/packageinfo
@@ -0,0 +1 @@
+version 2
\ No newline at end of file