Bug 581508 - FilterRowDataProvider should support
ContextualDisplayConverter

Signed-off-by: Dirk Fauth <dirk.fauth@googlemail.com>

Change-Id: I3fb9863e4434a240923317bd05392e9ab90ed23d
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/filterrow/FilterRowDataProvider.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/filterrow/FilterRowDataProvider.java
index 9aa76a7..6eb8382 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/filterrow/FilterRowDataProvider.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/filterrow/FilterRowDataProvider.java
@@ -25,6 +25,7 @@
 import org.eclipse.nebula.widgets.nattable.data.convert.IDisplayConverter;
 import org.eclipse.nebula.widgets.nattable.filterrow.event.FilterAppliedEvent;
 import org.eclipse.nebula.widgets.nattable.layer.ILayer;
+import org.eclipse.nebula.widgets.nattable.layer.cell.LayerCell;
 import org.eclipse.nebula.widgets.nattable.persistence.IPersistable;
 import org.eclipse.nebula.widgets.nattable.style.DisplayMode;
 import org.eclipse.nebula.widgets.nattable.util.ObjectUtils;
@@ -217,7 +218,7 @@
                     DisplayMode.NORMAL,
                     FilterRowDataLayer.FILTER_ROW_COLUMN_LABEL_PREFIX + columnIndex);
 
-            String filterText = getFilterStringRepresentation(this.filterIndexToObjectMap.get(columnIndex), converter);
+            String filterText = getFilterStringRepresentation(columnIndex, converter);
             filterText = filterText.replace("|", PIPE_REPLACEMENT); //$NON-NLS-1$
             filterTextByIndex.put(columnIndex, filterText);
         }
@@ -248,7 +249,7 @@
 
                 String filterText = filterTextByIndex.get(columnIndex);
                 filterText = filterText.replace(PIPE_REPLACEMENT, "|"); //$NON-NLS-1$
-                this.filterIndexToObjectMap.put(columnIndex, getFilterFromString(filterText, converter));
+                this.filterIndexToObjectMap.put(columnIndex, getFilterFromString(columnIndex, filterText, converter));
             }
         } catch (Exception e) {
             LOG.error("Error while restoring filter row text!", e); //$NON-NLS-1$
@@ -267,16 +268,18 @@
      * encapsulated to be handled here, we need to take care of such states here
      * also.
      *
-     * @param filterValue
-     *            The filter value object that is used for filtering.
+     * @param columnIndex
+     *            The column index of the filter value object that is used for
+     *            filtering.
      * @param converter
      *            The converter that is used to convert the filter value, which
      *            is necessary to support filtering of custom types.
      * @return The String representation of the filter value.
      */
-    private String getFilterStringRepresentation(Object filterValue, IDisplayConverter converter) {
+    private String getFilterStringRepresentation(int columnIndex, IDisplayConverter converter) {
         // in case the filter value is a collection of values, we need to create
         // a special string representation
+        Object filterValue = this.filterIndexToObjectMap.get(columnIndex);
         if (filterValue instanceof Collection) {
             String collectionSpec = FILTER_COLLECTION_PREFIX + filterValue.getClass().getName() + ")"; //$NON-NLS-1$
             StringBuilder builder = new StringBuilder(collectionSpec);
@@ -284,7 +287,10 @@
             Collection<?> filterCollection = (Collection<?>) filterValue;
             for (Iterator<?> iterator = filterCollection.iterator(); iterator.hasNext();) {
                 Object filterObject = iterator.next();
-                String displayValue = (String) converter.canonicalToDisplayValue(filterObject);
+                String displayValue = (String) converter.canonicalToDisplayValue(
+                        new LayerCell(null, columnIndex, 0),
+                        this.configRegistry,
+                        filterObject);
                 displayValue = displayValue.replace(IPersistable.VALUE_SEPARATOR, COMMA_REPLACEMENT);
                 builder.append(displayValue);
                 if (iterator.hasNext()) {
@@ -295,7 +301,10 @@
             builder.append("]"); //$NON-NLS-1$
             return builder.toString();
         }
-        return (String) converter.canonicalToDisplayValue(filterValue);
+        return (String) converter.canonicalToDisplayValue(
+                new LayerCell(null, columnIndex, 0),
+                this.configRegistry,
+                filterValue);
     }
 
     /**
@@ -306,6 +315,8 @@
      * persistence is encapsulated to be handled here, we need to take care of
      * such states here also.
      *
+     * @param columnIndex
+     *            The column index for which the the applied filter was saved.
      * @param filterText
      *            The String representation of the applied saved filter.
      * @param converter
@@ -323,7 +334,7 @@
      * @throws IllegalArgumentException
      */
     @SuppressWarnings({ "rawtypes", "unchecked" })
-    private Object getFilterFromString(String filterText, IDisplayConverter converter)
+    private Object getFilterFromString(int columnIndex, String filterText, IDisplayConverter converter)
             throws InstantiationException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException {
 
         if (filterText.startsWith(FILTER_COLLECTION_PREFIX)) {
@@ -337,12 +348,18 @@
             String[] filterSplit = filterText.split(IPersistable.VALUE_SEPARATOR);
             for (String filterString : filterSplit) {
                 filterString = filterString.replace(COMMA_REPLACEMENT, IPersistable.VALUE_SEPARATOR);
-                filterCollection.add(converter.displayToCanonicalValue(filterString));
+                filterCollection.add(converter.displayToCanonicalValue(
+                        new LayerCell(null, columnIndex, 0),
+                        this.configRegistry,
+                        filterString));
             }
 
             return filterCollection;
         }
-        return converter.displayToCanonicalValue(filterText);
+        return converter.displayToCanonicalValue(
+                new LayerCell(null, columnIndex, 0),
+                this.configRegistry,
+                filterText);
     }
 
     /**
diff --git a/org.eclipse.nebula.widgets.nattable.extension.glazedlists.test/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/filterrow/FilterRowDataProviderTest.java b/org.eclipse.nebula.widgets.nattable.extension.glazedlists.test/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/filterrow/FilterRowDataProviderTest.java
index 8cb0dd1..bc82a8d 100644
--- a/org.eclipse.nebula.widgets.nattable.extension.glazedlists.test/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/filterrow/FilterRowDataProviderTest.java
+++ b/org.eclipse.nebula.widgets.nattable.extension.glazedlists.test/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/filterrow/FilterRowDataProviderTest.java
@@ -21,9 +21,12 @@
 import java.util.Collection;
 import java.util.Properties;
 
+import org.eclipse.nebula.widgets.nattable.config.CellConfigAttributes;
 import org.eclipse.nebula.widgets.nattable.config.ConfigRegistry;
 import org.eclipse.nebula.widgets.nattable.config.DefaultNatTableStyleConfiguration;
+import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry;
 import org.eclipse.nebula.widgets.nattable.data.ReflectiveColumnPropertyAccessor;
+import org.eclipse.nebula.widgets.nattable.data.convert.ContextualDisplayConverter;
 import org.eclipse.nebula.widgets.nattable.data.convert.DefaultDoubleDisplayConverter;
 import org.eclipse.nebula.widgets.nattable.dataset.fixture.data.RowDataFixture;
 import org.eclipse.nebula.widgets.nattable.dataset.fixture.data.RowDataListFixture;
@@ -35,6 +38,7 @@
 import org.eclipse.nebula.widgets.nattable.filterrow.config.DefaultFilterRowConfiguration;
 import org.eclipse.nebula.widgets.nattable.filterrow.config.FilterRowConfigAttributes;
 import org.eclipse.nebula.widgets.nattable.filterrow.event.FilterAppliedEvent;
+import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell;
 import org.eclipse.nebula.widgets.nattable.persistence.IPersistable;
 import org.eclipse.nebula.widgets.nattable.style.DisplayMode;
 import org.junit.jupiter.api.BeforeEach;
@@ -71,7 +75,7 @@
     }
 
     @Test
-    public void setDataValue() {
+    public void shouldSetDataValue() {
         assertNull(this.dataProvider.getDataValue(1, 1));
 
         this.dataProvider.setDataValue(1, 1, "testValue");
@@ -79,7 +83,7 @@
     }
 
     @Test
-    public void settingTextValueAppliesTextFilter() {
+    public void shouldApplyTextFilterOnSettingTextValue() {
         // original size
         assertEquals(13, this.filterList.size());
 
@@ -96,7 +100,7 @@
     }
 
     @Test
-    public void settingThresholdValuesUpdatedFilter() {
+    public void shouldUpdateFilterOnSettingThresholdValues() {
         // Since we are triggering object comparison, we must provide the right
         // type
         this.configRegistry.registerConfigAttribute(
@@ -120,7 +124,7 @@
     }
 
     @Test
-    public void settingAValueFiresUpdateEvent() {
+    public void shouldFireUpdateEventOnSettingAValue() {
         final LayerListenerFixture listener = new LayerListenerFixture();
         this.columnHeaderLayer.addLayerListener(listener);
         this.dataProvider.setDataValue(3, 1, "testValue");
@@ -130,7 +134,7 @@
     }
 
     @Test
-    public void clearingFilterFiresUpdateEvent() {
+    public void shouldFireUpdateEventOnClearingFilter() {
         final LayerListenerFixture listener = new LayerListenerFixture();
         this.columnHeaderLayer.addLayerListener(listener);
 
@@ -153,7 +157,7 @@
     }
 
     @Test
-    public void loadingStateFiresUpdateEvent() {
+    public void shouldFireUpdateEventOnLoadingState() {
         final LayerListenerFixture listener = new LayerListenerFixture();
         this.columnHeaderLayer.addLayerListener(listener);
 
@@ -167,7 +171,7 @@
     }
 
     @Test
-    public void persistence() {
+    public void shouldSaveState() {
         this.dataProvider.setDataValue(1, 1, "testValue");
         this.dataProvider.setDataValue(2, 1, "testValue");
         this.dataProvider.setDataValue(3, 1, "testValue");
@@ -226,7 +230,7 @@
     }
 
     @Test
-    public void testRegularExpressionWithPipes() {
+    public void shouldHandleRegularExpressionWithPipes() {
         this.configRegistry.registerConfigAttribute(
                 FilterRowConfigAttributes.TEXT_MATCHING_MODE,
                 TextMatchingMode.REGULAR_EXPRESSION,
@@ -241,7 +245,7 @@
     }
 
     @Test
-    public void testPersistenceRegularExpressionWithPipes() {
+    public void shouldPersistRegularExpressionWithPipes() {
         this.configRegistry.registerConfigAttribute(
                 FilterRowConfigAttributes.TEXT_MATCHING_MODE,
                 TextMatchingMode.REGULAR_EXPRESSION,
@@ -367,4 +371,45 @@
         assertEquals(3, data.size());
         assertEquals(new ArrayList<>(Arrays.asList("foo", "bar", "foo,bar")), data);
     }
+
+    @Test
+    public void shouldPersistWithContextualDisplayConverter() {
+        this.configRegistry.registerConfigAttribute(
+                CellConfigAttributes.DISPLAY_CONVERTER,
+                new ContextualDisplayConverter() {
+
+                    @Override
+                    public Object canonicalToDisplayValue(ILayerCell cell, IConfigRegistry configRegistry, Object canonicalValue) {
+                        return canonicalValue.toString() + "_" + cell.getColumnIndex();
+                    }
+
+                    @Override
+                    public Object displayToCanonicalValue(ILayerCell cell, IConfigRegistry configRegistry, Object displayValue) {
+                        return displayValue.toString().substring(0, displayValue.toString().length() - 2);
+                    }
+
+                });
+
+        this.dataProvider.setDataValue(1, 1, "foo");
+        this.dataProvider.setDataValue(2, 1, "testValue");
+
+        Properties properties = new Properties();
+
+        // save state
+        this.dataProvider.saveState("prefix", properties);
+        String persistedProperty = properties.getProperty("prefix" + FilterRowDataLayer.PERSISTENCE_KEY_FILTER_ROW_TOKENS);
+
+        assertEquals("1:foo_1|2:testValue_2|", persistedProperty);
+
+        // reset state
+        this.dataProvider.clearAllFilters();
+
+        assertNull(this.dataProvider.getDataValue(1, 1));
+
+        // load state
+        this.dataProvider.loadState("prefix", properties);
+
+        assertEquals("foo", this.dataProvider.getDataValue(1, 1));
+        assertEquals("testValue", this.dataProvider.getDataValue(2, 1));
+    }
 }
\ No newline at end of file