Bug 311907 - Support conversion of @Preference types
diff --git a/bundles/org.eclipse.e4.core.di.extensions/src/org/eclipse/e4/core/di/internal/extensions/PreferencesObjectSupplier.java b/bundles/org.eclipse.e4.core.di.extensions/src/org/eclipse/e4/core/di/internal/extensions/PreferencesObjectSupplier.java
index 68f8615..caa1e07 100644
--- a/bundles/org.eclipse.e4.core.di.extensions/src/org/eclipse/e4/core/di/internal/extensions/PreferencesObjectSupplier.java
+++ b/bundles/org.eclipse.e4.core.di.extensions/src/org/eclipse/e4/core/di/internal/extensions/PreferencesObjectSupplier.java
@@ -10,6 +10,8 @@
  *******************************************************************************/
 package org.eclipse.e4.core.di.internal.extensions;
 
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -26,6 +28,9 @@
 import org.eclipse.e4.core.di.suppliers.IRequestor;
 import org.osgi.framework.FrameworkUtil;
 
+/**
+ * Note: we do not support byte arrays in preferences at this time.
+ */
 public class PreferencesObjectSupplier extends ExtendedObjectSupplier {
 
 	private Map<String, List<IRequestor>> listenerCache = new HashMap<String, List<IRequestor>>();
@@ -45,9 +50,48 @@
 
 		if (track)
 			addListener(nodePath, requestor);
-		// TBD add auto-conversion depending on the descriptor's desired type
-		Object result = getPreferencesService().getString(nodePath, key, null, null);
-		return result;
+
+		Class<?> descriptorsClass = getDesiredClass(descriptor.getDesiredType());
+		if (descriptorsClass.isPrimitive()) {
+			if (descriptorsClass.equals(boolean.class))
+				return getPreferencesService().getBoolean(nodePath, key, false, null);
+			else if (descriptorsClass.equals(int.class))
+				return getPreferencesService().getInt(nodePath, key, 0, null);
+			else if (descriptorsClass.equals(double.class))
+				return getPreferencesService().getDouble(nodePath, key, 0.0d, null);
+			else if (descriptorsClass.equals(float.class))
+				return getPreferencesService().getFloat(nodePath, key, 0.0f, null);
+			else if (descriptorsClass.equals(long.class))
+				return getPreferencesService().getLong(nodePath, key, 0L, null);
+		}
+
+		if (String.class.equals(descriptorsClass))
+			return getPreferencesService().getString(nodePath, key, null, null);
+		else if (Boolean.class.equals(descriptorsClass))
+			return getPreferencesService().getBoolean(nodePath, key, false, null);
+		else if (Boolean.class.equals(descriptorsClass))
+			return getPreferencesService().getBoolean(nodePath, key, false, null);
+		else if (Integer.class.equals(descriptorsClass))
+			return getPreferencesService().getInt(nodePath, key, 0, null);
+		else if (Double.class.equals(descriptorsClass))
+			return getPreferencesService().getDouble(nodePath, key, 0.0d, null);
+		else if (Float.class.equals(descriptorsClass))
+			return getPreferencesService().getFloat(nodePath, key, 0.0f, null);
+		else if (Long.class.equals(descriptorsClass))
+			return getPreferencesService().getLong(nodePath, key, 0L, null);
+
+		return getPreferencesService().getString(nodePath, key, null, null);
+	}
+
+	private Class<?> getDesiredClass(Type desiredType) {
+		if (desiredType instanceof Class<?>)
+			return (Class<?>) desiredType;
+		if (desiredType instanceof ParameterizedType) {
+			Type rawType = ((ParameterizedType) desiredType).getRawType();
+			if (rawType instanceof Class<?>)
+				return (Class<?>) rawType;
+		}
+		return null;
 	}
 
 	private String getKey(IObjectDescriptor descriptor) {
diff --git a/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/di/extensions/InjectionPreferencesTest.java b/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/di/extensions/InjectionPreferencesTest.java
index 8184bea..6695355 100644
--- a/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/di/extensions/InjectionPreferencesTest.java
+++ b/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/di/extensions/InjectionPreferencesTest.java
@@ -10,8 +10,6 @@
  ******************************************************************************/
 package org.eclipse.e4.core.internal.tests.di.extensions;
 
-import java.lang.reflect.InvocationTargetException;
-
 import javax.inject.Inject;
 
 import junit.framework.TestCase;
@@ -26,12 +24,21 @@
 import org.eclipse.e4.core.internal.tests.CoreTestsActivator;
 import org.osgi.service.prefs.BackingStoreException;
 
-// TBD add auto-conversion?
+/**
+ * Note: we do not support byte arrays at this time.
+ */
 public class InjectionPreferencesTest extends TestCase {
 	
 	static final private String TEST_PREFS_KEY = "testPreferencesQualifier";  
 	static final private String TEST_PREFS_NODE = "org.eclipse.e4.core.tests.ext";
 	
+	static final private String KEY_INT = "testPreferencesInt";
+	static final private String KEY_BOOL = "testPreferencesBoolean";
+	static final private String KEY_DOUBLE = "testPreferencesDouble";
+	static final private String KEY_FLOAT = "testPreferencesFloat";
+	static final private String KEY_LONG = "testPreferencesLong";
+//	static final private String KEY_BYTE_ARRAY = "testPreferencesByteArray";
+	
 	static class InjectTarget {
 		public int counter = 0;
 		public int counterNode = 0;
@@ -62,11 +69,66 @@
 		}
 	}
 	
-	public void testPreferencesQualifier() throws BackingStoreException, InvocationTargetException, InstantiationException {
+	static class InjectTargetPrimitive {
+		@Inject @Preference(KEY_INT)
+		public int intField;
+
+		@Inject @Preference(KEY_BOOL)
+		public boolean booleanField;
+
+		@Inject @Preference(KEY_DOUBLE)
+		public double doubleField;
+
+		@Inject @Preference(KEY_FLOAT)
+		public float floatField;
+
+		@Inject @Preference(KEY_LONG)
+		public long longField;
+
+//		@Inject @Preference(KEY_BYTE_ARRAY)
+//		public byte[] byteArrayField;
+		
+		public int intArg;
+		public boolean booleanArg;
+		
+		@Inject
+		public void set(@Preference(KEY_INT) int intArg, @Preference(KEY_BOOL) boolean booleanArg) {
+			this.intArg = intArg;
+			this.booleanArg = booleanArg;
+		}
+	}
+
+	static class InjectTargetConversion {
+		@Inject @Preference(KEY_INT)
+		public Integer intField;
+
+		@Inject @Preference(KEY_BOOL)
+		public Boolean booleanField;
+
+		@Inject @Preference(KEY_DOUBLE)
+		public Double doubleField;
+
+		@Inject @Preference(KEY_FLOAT)
+		public Float floatField;
+
+		@Inject @Preference(KEY_LONG)
+		public Long longField;
+
+		public Integer intArg;
+		public Boolean booleanArg;
+		
+		@Inject
+		public void set(@Preference(KEY_INT) Integer intArg, @Preference(KEY_BOOL) Boolean booleanArg) {
+			this.intArg = intArg;
+			this.booleanArg = booleanArg;
+		}
+	}
+	
+	public void testPreferencesQualifier() throws BackingStoreException {
 		setPreference(TEST_PREFS_KEY, "abc");
 		setPreference(TEST_PREFS_KEY, TEST_PREFS_NODE, "123");
 		IEclipseContext context = EclipseContextFactory.create();
-		InjectTarget target = (InjectTarget) ContextInjectionFactory.make(InjectTarget.class, context);
+		InjectTarget target = ContextInjectionFactory.make(InjectTarget.class, context);
 		// default node
 		assertEquals(1, target.counter);
 		assertEquals("abc", target.pref);
@@ -94,6 +156,81 @@
 		assertEquals("xyz", target.prefOptional2);
 	}
 	
+	public void testBaseTypeConversion() throws BackingStoreException {
+		// setup preferences
+		String nodePath = CoreTestsActivator.getDefault().getBundleContext().getBundle().getSymbolicName();
+		IEclipsePreferences node = new InstanceScope().getNode(nodePath);
+		node.putInt(KEY_INT, 12);
+		node.putBoolean(KEY_BOOL, true);
+		node.putDouble(KEY_DOUBLE, 12.35345345345d);
+		node.putFloat(KEY_FLOAT, 5.13f);
+		node.putLong(KEY_LONG, 131232343453453L);
+//		node.putByteArray(KEY_BYTE_ARRAY, new byte[] { 12, 34, 45, 67});
+		node.flush();
+		
+		IEclipseContext context = EclipseContextFactory.create();
+		InjectTargetPrimitive target = ContextInjectionFactory.make(InjectTargetPrimitive.class, context);
+		
+		assertEquals(12, target.intField);
+		assertEquals(true, target.booleanField);
+		assertEquals(12.35345345345d, target.doubleField);
+		assertEquals(5.13f, target.floatField);
+		assertEquals(131232343453453L, target.longField);
+//		assertNotNull(target.byteArrayField);
+//		assertEquals(4, target.byteArrayField.length);
+//		assertEquals(12, target.byteArrayField[0]);
+//		assertEquals(34, target.byteArrayField[1]);
+//		assertEquals(45, target.byteArrayField[2]);
+//		assertEquals(67, target.byteArrayField[3]);
+		
+		assertEquals(12, target.intArg);
+		assertEquals(true, target.booleanArg);
+		
+		// change
+		node.putInt(KEY_INT, 777);
+		node.putBoolean(KEY_BOOL, false);
+		
+		assertEquals(777, target.intField);
+		assertEquals(false, target.booleanField);
+		
+		assertEquals(777, target.intArg);
+		assertEquals(false, target.booleanArg);
+	}
+	
+	public void testAutoConversion() throws BackingStoreException {
+		// setup preferences
+		String nodePath = CoreTestsActivator.getDefault().getBundleContext().getBundle().getSymbolicName();
+		IEclipsePreferences node = new InstanceScope().getNode(nodePath);
+		node.putInt(KEY_INT, 12);
+		node.putBoolean(KEY_BOOL, true);
+		node.putDouble(KEY_DOUBLE, 12.35345345345d);
+		node.putFloat(KEY_FLOAT, 5.13f);
+		node.putLong(KEY_LONG, 131232343453453L);
+		node.flush();
+		
+		IEclipseContext context = EclipseContextFactory.create();
+		InjectTargetConversion target = ContextInjectionFactory.make(InjectTargetConversion.class, context);
+		
+		assertEquals(new Integer(12), target.intField);
+		assertEquals(new Boolean(true), target.booleanField);
+		assertEquals(new Double(12.35345345345d), target.doubleField);
+		assertEquals(new Float(5.13f), target.floatField);
+		assertEquals(new Long(131232343453453L), target.longField);
+		
+		assertEquals(new Integer(12), target.intArg);
+		assertEquals(new Boolean(true), target.booleanArg);
+		
+		// change
+		node.putInt(KEY_INT, 777);
+		node.putBoolean(KEY_BOOL, false);
+		
+		assertEquals(new Integer(777), target.intField);
+		assertEquals(new Boolean(false), target.booleanField);
+		
+		assertEquals(new Integer(777), target.intArg);
+		assertEquals(new Boolean(false), target.booleanArg);
+	}
+
 	private void setPreference(String key, String value) throws BackingStoreException {
 		String nodePath = CoreTestsActivator.getDefault().getBundleContext().getBundle().getSymbolicName();
 		IEclipsePreferences node = new InstanceScope().getNode(nodePath);