FIXED - bug 283428: [DataBinding] ViewerSupport.bind() cannot be called multiple times
https://bugs.eclipse.org/bugs/show_bug.cgi?id=283428
diff --git a/bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/databinding/viewers/ViewerSupport.java b/bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/databinding/viewers/ViewerSupport.java
index b674b63..0a9d2f3 100644
--- a/bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/databinding/viewers/ViewerSupport.java
+++ b/bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/databinding/viewers/ViewerSupport.java
@@ -7,6 +7,7 @@
  *
  * Contributors:
  *     Matthew Hall - initial API and implementation (bug 260337)
+ *     Matthew Hall - bug 283428
  ******************************************************************************/
 
 package org.eclipse.jface.databinding.viewers;
@@ -61,11 +62,14 @@
 	public static void bind(StructuredViewer viewer, IObservableList input,
 			IValueProperty[] labelProperties) {
 		ObservableListContentProvider contentProvider = new ObservableListContentProvider();
+		if (viewer.getInput() != null)
+			viewer.setInput(null);
 		viewer.setContentProvider(contentProvider);
 		viewer.setLabelProvider(new ObservableMapLabelProvider(Properties
 				.observeEach(contentProvider.getKnownElements(),
 						labelProperties)));
-		viewer.setInput(input);
+		if (input != null)
+			viewer.setInput(input);
 	}
 
 	/**
@@ -99,11 +103,14 @@
 	public static void bind(StructuredViewer viewer, IObservableSet input,
 			IValueProperty[] labelProperties) {
 		ObservableSetContentProvider contentProvider = new ObservableSetContentProvider();
+		if (viewer.getInput() != null)
+			viewer.setInput(null);
 		viewer.setContentProvider(contentProvider);
 		viewer.setLabelProvider(new ObservableMapLabelProvider(Properties
 				.observeEach(contentProvider.getKnownElements(),
 						labelProperties)));
-		viewer.setInput(input);
+		if (input != null)
+			viewer.setInput(input);
 	}
 
 	/**
@@ -146,11 +153,14 @@
 		Realm realm = SWTObservables.getRealm(viewer.getControl().getDisplay());
 		ObservableListTreeContentProvider contentProvider = new ObservableListTreeContentProvider(
 				childrenProperty.listFactory(realm), null);
+		if (viewer.getInput() != null)
+			viewer.setInput(null);
 		viewer.setContentProvider(contentProvider);
 		viewer.setLabelProvider(new ObservableMapLabelProvider(Properties
 				.observeEach(contentProvider.getKnownElements(),
 						labelProperties)));
-		viewer.setInput(input);
+		if (input != null)
+			viewer.setInput(input);
 	}
 
 	/**
@@ -193,10 +203,13 @@
 		Realm realm = SWTObservables.getRealm(viewer.getControl().getDisplay());
 		ObservableSetTreeContentProvider contentProvider = new ObservableSetTreeContentProvider(
 				childrenProperty.setFactory(realm), null);
+		if (viewer.getInput() != null)
+			viewer.setInput(null);
 		viewer.setContentProvider(contentProvider);
 		viewer.setLabelProvider(new ObservableMapLabelProvider(Properties
 				.observeEach(contentProvider.getKnownElements(),
 						labelProperties)));
-		viewer.setInput(input);
+		if (input != null)
+			viewer.setInput(input);
 	}
 }
diff --git a/tests/org.eclipse.jface.tests.databinding/src/org/eclipse/jface/tests/databinding/BindingTestSuite.java b/tests/org.eclipse.jface.tests.databinding/src/org/eclipse/jface/tests/databinding/BindingTestSuite.java
index 98f0b94..91e74fc 100644
--- a/tests/org.eclipse.jface.tests.databinding/src/org/eclipse/jface/tests/databinding/BindingTestSuite.java
+++ b/tests/org.eclipse.jface.tests.databinding/src/org/eclipse/jface/tests/databinding/BindingTestSuite.java
@@ -16,7 +16,7 @@
  *                    237703, 237718, 222289, 247394, 233306, 247647, 254524,
  *                    246103, 249992, 256150, 256543, 262269, 175735, 262946,
  *                    255734, 263693, 169876, 266038, 268336, 270461, 271720,
- *                    283204, 281723
+ *                    283204, 281723, 283428
  *     Ovidio Mallo - bug 237163, bug 235195
  *******************************************************************************/
 package org.eclipse.jface.tests.databinding;
@@ -162,6 +162,7 @@
 import org.eclipse.jface.tests.databinding.viewers.ObservableMapLabelProviderTest;
 import org.eclipse.jface.tests.databinding.viewers.ObservableSetContentProviderTest;
 import org.eclipse.jface.tests.databinding.viewers.ObservableSetTreeContentProviderTest;
+import org.eclipse.jface.tests.databinding.viewers.ViewerSupportTest;
 import org.eclipse.jface.tests.databinding.viewers.ViewersObservablesTest;
 import org.eclipse.jface.tests.databinding.wizard.WizardPageSupportTest;
 import org.eclipse.jface.tests.examples.databinding.mask.internal.EditMaskLexerAndTokenTest;
@@ -404,6 +405,7 @@
 		addTestSuite(ObservableSetContentProviderTest.class);
 		addTestSuite(ObservableSetTreeContentProviderTest.class);
 		addTestSuite(ViewersObservablesTest.class);
+		addTestSuite(ViewerSupportTest.class);
 
 		// org.eclipse.jface.tests.databinding.wizard
 		addTestSuite(WizardPageSupportTest.class);
diff --git a/tests/org.eclipse.jface.tests.databinding/src/org/eclipse/jface/tests/databinding/viewers/ViewerSupportTest.java b/tests/org.eclipse.jface.tests.databinding/src/org/eclipse/jface/tests/databinding/viewers/ViewerSupportTest.java
new file mode 100644
index 0000000..97a7abd
--- /dev/null
+++ b/tests/org.eclipse.jface.tests.databinding/src/org/eclipse/jface/tests/databinding/viewers/ViewerSupportTest.java
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Matthew Hall and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Matthew Hall - initial API and implementation (bug 283428)
+ ******************************************************************************/
+
+package org.eclipse.jface.tests.databinding.viewers;
+
+import java.util.Arrays;
+import java.util.HashSet;
+
+import org.eclipse.core.databinding.beans.BeanProperties;
+import org.eclipse.core.databinding.observable.list.IObservableList;
+import org.eclipse.core.databinding.observable.list.WritableList;
+import org.eclipse.core.databinding.observable.set.IObservableSet;
+import org.eclipse.core.databinding.observable.set.WritableSet;
+import org.eclipse.core.databinding.property.list.IListProperty;
+import org.eclipse.core.databinding.property.set.ISetProperty;
+import org.eclipse.core.databinding.property.value.IValueProperty;
+import org.eclipse.core.databinding.util.ILogger;
+import org.eclipse.core.databinding.util.Policy;
+import org.eclipse.core.runtime.ISafeRunnable;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.tests.internal.databinding.beans.Bean;
+import org.eclipse.jface.databinding.viewers.ViewerSupport;
+import org.eclipse.jface.tests.databinding.AbstractSWTTestCase;
+import org.eclipse.jface.util.ISafeRunnableRunner;
+import org.eclipse.jface.util.SafeRunnable;
+import org.eclipse.jface.viewers.AbstractTableViewer;
+import org.eclipse.jface.viewers.AbstractTreeViewer;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TreeViewer;
+
+public class ViewerSupportTest extends AbstractSWTTestCase {
+	private ILogger oldLog;
+	private ISafeRunnableRunner oldRunner;
+
+	private AbstractTableViewer structuredViewer;
+	private AbstractTreeViewer treeViewer;
+
+	protected void setUp() throws Exception {
+		super.setUp();
+
+		oldLog = Policy.getLog();
+		Policy.setLog(new ILogger() {
+			public void log(IStatus status) {
+				if (status.getException() != null)
+					throw new RuntimeException(status.getException());
+				fail("Unexpected status: " + status);
+			}
+		});
+
+		oldRunner = SafeRunnable.getRunner();
+		SafeRunnable.setRunner(new ISafeRunnableRunner() {
+			public void run(ISafeRunnable code) {
+				try {
+					code.run();
+				} catch (Exception e) {
+					throw new RuntimeException(e);
+				}
+			}
+		});
+	}
+
+	protected void tearDown() throws Exception {
+		if (structuredViewer != null)
+			structuredViewer.getControl().dispose();
+		if (treeViewer != null)
+			treeViewer.getControl().dispose();
+
+		Policy.setLog(oldLog);
+
+		SafeRunnable.setRunner(oldRunner);
+
+		super.tearDown();
+	}
+
+	private StructuredViewer getStructuredViewer() {
+		if (structuredViewer == null) {
+			structuredViewer = new TableViewer(getShell());
+		}
+		return structuredViewer;
+	}
+
+	private AbstractTreeViewer getTreeViewer() {
+		if (treeViewer == null)
+			treeViewer = new TreeViewer(getShell());
+		return treeViewer;
+	}
+
+	public void testBindList_Twice() {
+		StructuredViewer viewer = getStructuredViewer();
+		IObservableList input0 = WritableList.withElementType(Bean.class);
+		IObservableList input1 = WritableList.withElementType(Bean.class);
+		input0.add(new Bean("element0"));
+		input1.add(new Bean("element1"));
+		IValueProperty labelProp = BeanProperties.value(Bean.class, "value");
+		ViewerSupport.bind(viewer, input0, labelProp);
+		ViewerSupport.bind(viewer, input1, labelProp);
+	}
+
+	public void testBindSet_Twice() {
+		StructuredViewer viewer = getStructuredViewer();
+		IObservableSet input0 = WritableSet.withElementType(Bean.class);
+		IObservableSet input1 = WritableSet.withElementType(Bean.class);
+		input0.add(new Bean("element0"));
+		input1.add(new Bean("element1"));
+		IValueProperty labelProp = BeanProperties.value(Bean.class, "value");
+		ViewerSupport.bind(viewer, input0, labelProp);
+		ViewerSupport.bind(viewer, input1, labelProp);
+	}
+
+	public void testBindListTree_Twice() {
+		AbstractTreeViewer viewer = getTreeViewer();
+		Bean input0 = new Bean(Arrays.asList(new Bean[] { new Bean("elem0"),
+				new Bean("elem1"), new Bean("elem2") }));
+		Bean input1 = new Bean(Arrays.asList(new Bean[] { new Bean("elem3"),
+				new Bean("elem4"), new Bean("elem5") }));
+		IValueProperty labelProp = BeanProperties.value(Bean.class, "value");
+		IListProperty childrenProp = BeanProperties.list(Bean.class, "list");
+		ViewerSupport.bind(viewer, input0, childrenProp, labelProp);
+		ViewerSupport.bind(viewer, input1, childrenProp, labelProp);
+	}
+
+	public void testBindSetTree_Twice() {
+		AbstractTreeViewer viewer = getTreeViewer();
+		Bean input0 = new Bean(new HashSet(Arrays.asList(new Bean[] {
+				new Bean("elem0"), new Bean("elem1"), new Bean("elem2") })));
+		Bean input1 = new Bean(new HashSet(Arrays.asList(new Bean[] {
+				new Bean("elem3"), new Bean("elem4"), new Bean("elem5") })));
+		IValueProperty labelProp = BeanProperties.value(Bean.class, "value");
+		ISetProperty childrenProp = BeanProperties.set(Bean.class, "set");
+		ViewerSupport.bind(viewer, input0, childrenProp, labelProp);
+		ViewerSupport.bind(viewer, input1, childrenProp, labelProp);
+	}
+}