Bug 581359 - Support ContextualDisplayConverter for
FILTER_DISPLAY_CONVERTER

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

Change-Id: Iadfc11f728c31e1cdb8185c445abe5e2bc80d08a
diff --git a/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_600_GlazedLists/_603_Filter/_6037_MixedFilterRowExample.java b/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_600_GlazedLists/_603_Filter/_6037_MixedFilterRowExample.java
index 0d7d569..0506990 100644
--- a/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_600_GlazedLists/_603_Filter/_6037_MixedFilterRowExample.java
+++ b/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_600_GlazedLists/_603_Filter/_6037_MixedFilterRowExample.java
@@ -40,6 +40,7 @@
 import org.eclipse.nebula.widgets.nattable.data.IDataProvider;
 import org.eclipse.nebula.widgets.nattable.data.IRowIdAccessor;
 import org.eclipse.nebula.widgets.nattable.data.ListDataProvider;
+import org.eclipse.nebula.widgets.nattable.data.convert.ContextualDisplayConverter;
 import org.eclipse.nebula.widgets.nattable.data.convert.DefaultBooleanDisplayConverter;
 import org.eclipse.nebula.widgets.nattable.data.convert.DefaultDateDisplayConverter;
 import org.eclipse.nebula.widgets.nattable.data.convert.DefaultDisplayConverter;
@@ -65,7 +66,6 @@
 import org.eclipse.nebula.widgets.nattable.filterrow.FilterRowDataLayer;
 import org.eclipse.nebula.widgets.nattable.filterrow.FilterRowDataProvider;
 import org.eclipse.nebula.widgets.nattable.filterrow.FilterRowPainter;
-import org.eclipse.nebula.widgets.nattable.filterrow.FilterRowRegularExpressionConverter;
 import org.eclipse.nebula.widgets.nattable.filterrow.FilterRowTextCellEditor;
 import org.eclipse.nebula.widgets.nattable.filterrow.IFilterStrategy;
 import org.eclipse.nebula.widgets.nattable.filterrow.ParseResult;
@@ -214,6 +214,8 @@
         bodyLayerStack.getBodyDataLayer().setDataValue(0, 5, null);
         bodyLayerStack.getBodyDataLayer().setDataValue(1, 2, "");
         bodyLayerStack.getBodyDataLayer().setDataValue(1, 6, null);
+        bodyLayerStack.getBodyDataLayer().setDataValue(2, 3, null);
+        bodyLayerStack.getBodyDataLayer().setDataValue(2, 5, null);
 
         // build the column header layer
         IDataProvider columnHeaderDataProvider =
@@ -852,13 +854,20 @@
             // regular expressions
             configRegistry.registerConfigAttribute(
                     CellConfigAttributes.DISPLAY_CONVERTER,
-                    new CustomFilterRowRegularExpressionConverter(configRegistry),
+                    new DefaultDisplayConverter(),
                     DisplayMode.NORMAL,
                     FilterRowDataLayer.FILTER_ROW_COLUMN_LABEL_PREFIX
                             + DataModelConstants.FIRSTNAME_COLUMN_POSITION);
 
             configRegistry.registerConfigAttribute(
                     FilterRowConfigAttributes.FILTER_DISPLAY_CONVERTER,
+                    new CustomFilterRowRegularExpressionConverter(),
+                    DisplayMode.NORMAL,
+                    FilterRowDataLayer.FILTER_ROW_COLUMN_LABEL_PREFIX
+                            + DataModelConstants.FIRSTNAME_COLUMN_POSITION);
+
+            configRegistry.registerConfigAttribute(
+                    FilterRowConfigAttributes.FILTER_CONTENT_DISPLAY_CONVERTER,
                     new DefaultDisplayConverter(),
                     DisplayMode.NORMAL,
                     FilterRowDataLayer.FILTER_ROW_COLUMN_LABEL_PREFIX
@@ -873,8 +882,8 @@
             // FilterRowDataLayer.FILTER_ROW_COLUMN_LABEL_PREFIX + column
             // position
             ComboBoxCellEditor comboBoxCellEditor = new ComboBoxCellEditor(Arrays.asList(
-                    CustomFilterRowRegularExpressionConverter.EMPTY_REGEX,
-                    CustomFilterRowRegularExpressionConverter.NOT_EMPTY_REGEX,
+                    CustomFilterRowRegularExpressionConverter.EMPTY_LITERAL,
+                    CustomFilterRowRegularExpressionConverter.NOT_EMPTY_LITERAL,
                     Gender.FEMALE.toString(),
                     Gender.MALE.toString()));
             configRegistry.registerConfigAttribute(
@@ -893,7 +902,21 @@
 
             configRegistry.registerConfigAttribute(
                     CellConfigAttributes.DISPLAY_CONVERTER,
-                    new CustomFilterRowRegularExpressionConverter(configRegistry),
+                    new DefaultDisplayConverter(),
+                    DisplayMode.NORMAL,
+                    FilterRowDataLayer.FILTER_ROW_COLUMN_LABEL_PREFIX
+                            + DataModelConstants.GENDER_COLUMN_POSITION);
+
+            configRegistry.registerConfigAttribute(
+                    FilterRowConfigAttributes.FILTER_DISPLAY_CONVERTER,
+                    new CustomFilterRowRegularExpressionConverter(),
+                    DisplayMode.NORMAL,
+                    FilterRowDataLayer.FILTER_ROW_COLUMN_LABEL_PREFIX
+                            + DataModelConstants.GENDER_COLUMN_POSITION);
+
+            configRegistry.registerConfigAttribute(
+                    FilterRowConfigAttributes.FILTER_CONTENT_DISPLAY_CONVERTER,
+                    new DefaultDisplayConverter(),
                     DisplayMode.NORMAL,
                     FilterRowDataLayer.FILTER_ROW_COLUMN_LABEL_PREFIX
                             + DataModelConstants.GENDER_COLUMN_POSITION);
@@ -1117,11 +1140,11 @@
     }
 
     /**
-     * Specialization of the {@link FilterRowRegularExpressionConverter} that
-     * additionally parses special literals to corresponding regular
-     * expressions.
+     * Special implementation of a {@link ContextualDisplayConverter} that is
+     * used to convert a filter string with special literals and wildcards
+     * characters to a corresponding complex regular expression.
      */
-    class CustomFilterRowRegularExpressionConverter extends FilterRowRegularExpressionConverter {
+    class CustomFilterRowRegularExpressionConverter extends ContextualDisplayConverter {
 
         static final String EMPTY_LITERAL = "<empty>";
         static final String EMPTY_REGEX = "^$";
@@ -1134,55 +1157,53 @@
         static final String NOT_EQUALS_REGEX_PREFIX = "^((?!";
         static final String NOT_EQUALS_REGEX_SUFFIX = ").)*$";
 
-        private IConfigRegistry configRegistry;
-
-        public CustomFilterRowRegularExpressionConverter(IConfigRegistry configRegistry) {
-            this.configRegistry = configRegistry;
-        }
-
         @Override
-        public Object displayToCanonicalValue(ILayerCell cell, IConfigRegistry configRegistry, Object displayValue) {
-            if (displayValue != null) {
+        public Object canonicalToDisplayValue(ILayerCell cell, IConfigRegistry configRegistry, Object canonicalValue) {
+            if (canonicalValue != null) {
                 // first convert the wildcards
-                displayValue = super.displayToCanonicalValue(displayValue);
-                String dvString = displayValue.toString();
+                if (canonicalValue != null) {
+                    canonicalValue = canonicalValue.toString().replaceAll("\\*", "(.\\*)"); //$NON-NLS-1$ //$NON-NLS-2$
+                    canonicalValue = canonicalValue.toString().replaceAll("\\?", "(.\\?)"); //$NON-NLS-1$ //$NON-NLS-2$
+                }
 
-                if (dvString.contains(EMPTY_LITERAL)
-                        || dvString.contains(NOT_EMPTY_LITERAL)
-                        || dvString.contains("*")
-                        || dvString.contains("?")) {
+                String cvString = canonicalValue.toString();
 
-                    this.configRegistry.registerConfigAttribute(
+                if (cvString.contains(EMPTY_LITERAL)
+                        || cvString.contains(NOT_EMPTY_LITERAL)
+                        || cvString.contains("*")
+                        || cvString.contains("?")) {
+
+                    configRegistry.registerConfigAttribute(
                             FilterRowConfigAttributes.TEXT_MATCHING_MODE,
                             TextMatchingMode.REGULAR_EXPRESSION,
                             DisplayMode.NORMAL,
                             FilterRowDataLayer.FILTER_ROW_COLUMN_LABEL_PREFIX + cell.getColumnIndex());
 
                     // add the ignore case flag to the regex
-                    dvString = IGNORE_CASE_MODE_FLAG + dvString;
+                    cvString = IGNORE_CASE_MODE_FLAG + cvString;
                 } else {
 
-                    if (dvString.startsWith("=")) {
+                    if (cvString.startsWith("=")) {
 
-                        this.configRegistry.registerConfigAttribute(
+                        configRegistry.registerConfigAttribute(
                                 FilterRowConfigAttributes.TEXT_MATCHING_MODE,
                                 TextMatchingMode.EXACT,
                                 DisplayMode.NORMAL,
                                 FilterRowDataLayer.FILTER_ROW_COLUMN_LABEL_PREFIX + cell.getColumnIndex());
 
-                        dvString = dvString.substring(1).trim();
-                    } else if (dvString.startsWith(NOT_EQUALS_LITERAL)) {
-                        this.configRegistry.registerConfigAttribute(
+                        cvString = cvString.substring(1).trim();
+                    } else if (cvString.startsWith(NOT_EQUALS_LITERAL)) {
+                        configRegistry.registerConfigAttribute(
                                 FilterRowConfigAttributes.TEXT_MATCHING_MODE,
                                 TextMatchingMode.REGULAR_EXPRESSION,
                                 DisplayMode.NORMAL,
                                 FilterRowDataLayer.FILTER_ROW_COLUMN_LABEL_PREFIX + cell.getColumnIndex());
 
-                        dvString = IGNORE_CASE_MODE_FLAG + NOT_EQUALS_REGEX_PREFIX + dvString.substring(2).trim() + NOT_EQUALS_REGEX_SUFFIX;
+                        cvString = IGNORE_CASE_MODE_FLAG + NOT_EQUALS_REGEX_PREFIX + cvString.substring(2).trim() + NOT_EQUALS_REGEX_SUFFIX;
                     } else {
                         // only switch to CONTAINS if RegEx filtering is not
                         // activated
-                        this.configRegistry.registerConfigAttribute(
+                        configRegistry.registerConfigAttribute(
                                 FilterRowConfigAttributes.TEXT_MATCHING_MODE,
                                 TextMatchingMode.CONTAINS,
                                 DisplayMode.NORMAL,
@@ -1190,42 +1211,19 @@
                     }
                 }
 
-                dvString = dvString.replace(EMPTY_LITERAL, EMPTY_REGEX);
-                dvString = dvString.replace(NOT_EMPTY_LITERAL, NOT_EMPTY_REGEX);
-
-                return dvString;
-            }
-            return displayValue;
-        }
-
-        @Override
-        public Object canonicalToDisplayValue(ILayerCell cell, IConfigRegistry configRegistry, Object canonicalValue) {
-            if (canonicalValue != null) {
-                // first remove a possible ignore case flag
-                canonicalValue = canonicalValue.toString().replace(IGNORE_CASE_MODE_FLAG, "");
-
-                canonicalValue = super.canonicalToDisplayValue(canonicalValue);
-
-                String cvString = canonicalValue.toString();
-                cvString = cvString.replace(EMPTY_REGEX, EMPTY_LITERAL);
-                cvString = cvString.replace(NOT_EMPTY_REGEX, NOT_EMPTY_LITERAL);
-
-                if (cvString.startsWith(NOT_EQUALS_REGEX_PREFIX) && cvString.endsWith(NOT_EQUALS_REGEX_SUFFIX)) {
-                    cvString = NOT_EQUALS_LITERAL + cvString.substring(NOT_EQUALS_REGEX_PREFIX.length(), cvString.length() - NOT_EQUALS_REGEX_SUFFIX.length());
-                } else {
-                    TextMatchingMode mode = this.configRegistry.getConfigAttribute(
-                            FilterRowConfigAttributes.TEXT_MATCHING_MODE,
-                            DisplayMode.NORMAL,
-                            FilterRowDataLayer.FILTER_ROW_COLUMN_LABEL_PREFIX + cell.getColumnIndex());
-                    if (mode == TextMatchingMode.EXACT) {
-                        cvString = "=" + cvString;
-                    }
-                }
+                cvString = cvString.replace(EMPTY_LITERAL, EMPTY_REGEX);
+                cvString = cvString.replace(NOT_EMPTY_LITERAL, NOT_EMPTY_REGEX);
 
                 return cvString;
             }
             return canonicalValue;
         }
+
+        @Override
+        public Object displayToCanonicalValue(ILayerCell cell, IConfigRegistry configRegistry, Object displayValue) {
+            // empty as never called
+            return null;
+        }
     }
 
     /**
diff --git a/org.eclipse.nebula.widgets.nattable.extension.glazedlists/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/filterrow/ComboBoxGlazedListsFilterStrategy.java b/org.eclipse.nebula.widgets.nattable.extension.glazedlists/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/filterrow/ComboBoxGlazedListsFilterStrategy.java
index 1d68032..70bb157 100644
--- a/org.eclipse.nebula.widgets.nattable.extension.glazedlists/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/filterrow/ComboBoxGlazedListsFilterStrategy.java
+++ b/org.eclipse.nebula.widgets.nattable.extension.glazedlists/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/filterrow/ComboBoxGlazedListsFilterStrategy.java
@@ -31,6 +31,7 @@
 import org.eclipse.nebula.widgets.nattable.edit.EditConstants;
 import org.eclipse.nebula.widgets.nattable.filterrow.combobox.ComboBoxFilterUtils;
 import org.eclipse.nebula.widgets.nattable.filterrow.combobox.FilterRowComboBoxDataProvider;
+import org.eclipse.nebula.widgets.nattable.layer.cell.LayerCell;
 import org.eclipse.nebula.widgets.nattable.util.ObjectUtils;
 
 import ca.odell.glazedlists.FilterList;
@@ -196,7 +197,10 @@
                 if (result.length() > 0) {
                     result += "|"; //$NON-NLS-1$
                 }
-                String convertedValue = displayConverter.canonicalToDisplayValue(value).toString();
+                String convertedValue = displayConverter.canonicalToDisplayValue(
+                        new LayerCell(null, columnIndex, 0),
+                        this.configRegistry,
+                        value).toString();
                 if (convertedValue.isEmpty()) {
                     // for an empty String add the regular expression for empty
                     // String
@@ -209,7 +213,10 @@
         }
 
         if (displayConverter != null) {
-            Object result = displayConverter.canonicalToDisplayValue(object);
+            Object result = displayConverter.canonicalToDisplayValue(
+                    new LayerCell(null, columnIndex, 0),
+                    this.configRegistry,
+                    object);
             if (result != null) {
                 return result.toString();
             }
@@ -228,7 +235,7 @@
      *
      * @return <code>true</code> if at least one combobox cell editor is
      *         registered, <code>false</code> if not.
-     * 
+     *
      * @since 2.1
      */
     protected boolean hasComboBoxFilterEditorRegistered() {
diff --git a/org.eclipse.nebula.widgets.nattable.extension.glazedlists/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/filterrow/DefaultGlazedListsFilterStrategy.java b/org.eclipse.nebula.widgets.nattable.extension.glazedlists/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/filterrow/DefaultGlazedListsFilterStrategy.java
index 3203d9a..29d7409 100644
--- a/org.eclipse.nebula.widgets.nattable.extension.glazedlists/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/filterrow/DefaultGlazedListsFilterStrategy.java
+++ b/org.eclipse.nebula.widgets.nattable.extension.glazedlists/src/org/eclipse/nebula/widgets/nattable/extension/glazedlists/filterrow/DefaultGlazedListsFilterStrategy.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2012, 2022 Original authors and others.
+ * Copyright (c) 2012, 2023 Original authors and others.
  *
  * This program and the accompanying materials are made
  * available under the terms of the Eclipse Public License 2.0
@@ -29,6 +29,7 @@
 import org.eclipse.nebula.widgets.nattable.filterrow.ParseResult.MatchType;
 import org.eclipse.nebula.widgets.nattable.filterrow.TextMatchingMode;
 import org.eclipse.nebula.widgets.nattable.filterrow.config.FilterRowConfigAttributes;
+import org.eclipse.nebula.widgets.nattable.layer.cell.LayerCell;
 import org.eclipse.nebula.widgets.nattable.style.DisplayMode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -325,7 +326,11 @@
                 FilterRowConfigAttributes.FILTER_DISPLAY_CONVERTER,
                 DisplayMode.NORMAL,
                 FilterRowDataLayer.FILTER_ROW_COLUMN_LABEL_PREFIX + columnIndex);
-        return displayConverter.canonicalToDisplayValue(object).toString();
+
+        return displayConverter.canonicalToDisplayValue(
+                new LayerCell(null, columnIndex, 0),
+                this.configRegistry,
+                object).toString();
     }
 
     /**