diff --git a/process/JditoFilter_lib/process.js b/process/JditoFilter_lib/process.js
index 28657e5ceeca29d86881a28abcb28979095b4fe0..b318e287639603ed313d77088be28239a1b7a6e1 100644
--- a/process/JditoFilter_lib/process.js
+++ b/process/JditoFilter_lib/process.js
@@ -214,16 +214,163 @@ JditoFilterUtils.filterRecords = function (pColumns, pRecords, pFilter, pCustomC
  */
 JditoFilterUtils.getSqlCondition = function (pFilter, pTable, pTableAlias, pColumnOrFnMap)
 {
-    var condition = newWhere();
+    var filterTranslator = new FilterSqlTranslator(pFilter)
+        .table(pTable, pTableAlias);
     
-    var ignoreCase = JditoFilterUtils.isUserIgnoreCase();
-    
-    if (!pFilter)
+    if (pColumnOrFnMap)
+    {
+        for (let fieldName in pColumnOrFnMap)
+        {
+            var columnOrFn = pColumnOrFnMap[fieldName];
+            if (typeof columnOrFn === "function")
+                filterTranslator.addSpecialFieldConditionFn(fieldName, columnOrFn);
+            else
+                filterTranslator.addSqlFieldMapping(fieldName, columnOrFn);
+        }
+    }
+    return filterTranslator.getSqlCondition();
+}
+
+/**
+ * @return {boolean} the selectionIgnoreCase property of the current user, defaults to true
+ */
+JditoFilterUtils.isUserIgnoreCase = function ()
+{
+    var user = tools.getCurrentUser();
+    var ignoreCase = user ? user[tools.PARAMS][tools.SELECTION_IGNORECASE] : "";
+    return ignoreCase == "" || /true/i.test(ignoreCase);
+}
+
+/**
+ * Object for translating a filter object to a sql condition.
+ * 
+ * @param {Object} pFilter the filter object that should be used
+ * @param {String} pTable the database table to build the condition for
+ */
+function FilterSqlTranslator (pFilter, pTable)
+{
+    this._filter = null;
+    this.filter(pFilter);
+    this._table = pTable;
+    this._tableAlias = null;
+    this._dbAlias = null;
+    this._sqlFieldMappings = {};
+    this._fieldConditionFns = {};
+    this._ignoreCase = JditoFilterUtils.isUserIgnoreCase();
+}
+
+/**
+ * Sets the filter of the object
+ * 
+ * @param {Object} pFilter the filter object that should be used
+ * @return {FilterSqlTranslator} current object
+ */
+FilterSqlTranslator.prototype.filter = function (pFilter)
+{
+    if (pFilter)
+    {
+        if (typeof pFilter !== "object")
+            throw new TypeError("FilterSqlTranslator: Wrong type for the filter, expected 'object' but got '" + (typeof pFilter) + "'");
+        this._filter = pFilter.filter || pFilter;
+    }
+    return this;
+}
+
+/**
+ * Sets the filter of the object
+ * 
+ * @param {String} pFilter the filter object that should be used as JSON string
+ * @return {FilterSqlTranslator} current object
+ */
+FilterSqlTranslator.prototype.filterJSON = function (pFilter)
+{
+    return this.filter(JSON.parse(pFilter));
+}
+
+/**
+ * Sets the table of the object
+ * 
+ * @param {String} pTable the database table to build the condition for
+ * @param {String} [pTableAlias] the alias of the table
+ * @return {FilterSqlTranslator} current object
+ */
+FilterSqlTranslator.prototype.table = function (pTable, pTableAlias)
+{
+    this._table = pTable;
+    if (pTableAlias)
+        this._tableAlias = pTableAlias;
+    return this;
+}
+
+/**
+ * Adds a special database field mapping for the given field that will be used for the sql condition
+ * 
+ * @param {String} pFieldName the field name
+ * @param {String|String[]} the database field ("TABLE.COLUMN" or ["TABLE", "COLUMN", "alias"])
+ * @return {FilterSqlTranslator} current object
+ */
+FilterSqlTranslator.prototype.addSqlFieldMapping = function (pFieldName, pDBField)
+{
+    this._sqlFieldMappings[pFieldName] = pDBField;
+    return this;
+}
+
+/**
+ * Adds a special function for building the condition for the given field. The function must return a sql condition (SqlBuilder or String)
+ * 
+ * @param {String} pFieldName the field name
+ * @param {Function} pConditionFn a function that generates the condition
+ * @return {FilterSqlTranslator} current object
+ */
+FilterSqlTranslator.prototype.addSpecialFieldConditionFn = function (pFieldName, pConditionFn)
+{
+    this._fieldConditionFns[pFieldName] = pConditionFn;
+    return this;
+}
+
+/**
+ * Sets the database alias
+ * 
+ * @param {String} pAlias the alias to be used
+ * @return {FilterSqlTranslator} current object
+ */
+FilterSqlTranslator.prototype.dbAlias = function (pAlias)
+{
+    this._dbAlias = pAlias;
+    return this;
+}
+
+/**
+ * Changes whether the condition should be case-insensitive for text
+ * 
+ * @param {boolean} [pIgnoreCase=true] if it should be case-insensitive
+ * @return {FilterSqlTranslator} current object
+ */
+FilterSqlTranslator.prototype.ignoreCase = function (pIgnoreCase)
+{
+    //"", 0 , false -> false, everything else is considered true
+    this._ignoreCase = pIgnoreCase != false;
+    return this;
+}
+
+/**
+ * Builds the sql condition from the filter
+ * 
+ * @return {SqlBuilder} the sql condition
+ */
+FilterSqlTranslator.prototype.getSqlCondition = function ()
+{
+    var condition = new SqlBuilder(this._dbAlias).where();
+    if (!this._filter)
         return condition;
-    if (!pColumnOrFnMap)
-        pColumnOrFnMap = {};
     
-    _addCondition.call(condition, pFilter, pFilter.operator);
+    var table = this._table;
+    var tableAlias = this._tableAlias;
+    var ignoreCase = this._ignoreCase;
+    var sqlFieldMappings = this._sqlFieldMappings;
+    var fieldConditionFns = this._fieldConditionFns;
+    
+    _addCondition.call(condition, this._filter, this._filter.operator);
     
     return condition;
     
@@ -233,53 +380,55 @@ JditoFilterUtils.getSqlCondition = function (pFilter, pTable, pTableAlias, pColu
     {
         if (pFilter.type == "row")
         {
-            var sqlField;
-            if (pFilter.name in pColumnOrFnMap)
+            var sqlField, condition;
+            var filterValue = (pFilter.key || pFilter.value);
+            if (pFilter.name in fieldConditionFns)
             {
-                sqlField = pColumnOrFnMap[pFilter.name];
+                var conditionFn = fieldConditionFns[pFilter.name];
+                
+                condition = conditionFn.call(null, filterValue, pFilter.operator);
+                if (pOperator == "AND")
+                    this.andIfSet(condition);
+                else if (pOperator == "OR")
+                    this.orIfSet(condition);
+                
+                return;
+            }
+            
+            if (pFilter.name in sqlFieldMappings)
+            {
+                sqlField = sqlFieldMappings[sqlField];
                 
                 //possibility to explicitly set the value to null/false so that the field is ignored
                 if (sqlField === null || sqlField === false)
                     return;
             }
-            else if (pTable && pTableAlias)
-                sqlField = [pTable, pFilter.name, pTableAlias];
-            else if (pTable)
-                sqlField = pTable + "." + pFilter.name;
+            else if (table && tableAlias)
+                sqlField = [table, pFilter.name, tableAlias];
+            else if (table)
+                sqlField = table + "." + pFilter.name;
             
-            var filterValue = (pFilter.key || pFilter.value);
-            
-            var condition;
-            if (typeof(sqlField) === "function")
+            var generatedCondition = _getCondition(filterValue, pFilter.operator, sqlField);
+            if (generatedCondition instanceof SqlBuilder || typeof generatedCondition === "string")
             {
-                condition = sqlField.call(null, filterValue, pFilter.operator);
                 if (pOperator == "AND")
-                    this.andIfSet(condition);
+                    this.andIfSet(generatedCondition);
                 else if (pOperator == "OR")
-                    this.orIfSet(condition);
+                    this.orIfSet(generatedCondition);
             }
             else
             {
-                var generatedCondition = _getCondition(filterValue, pFilter.operator, sqlField);
-                if (generatedCondition instanceof SqlBuilder)
-                {
-                    if (pOperator == "AND")
-                        this.andIfSet(generatedCondition);
-                    else if (pOperator == "OR")
-                        this.orIfSet(generatedCondition);
-                }
-                else
-                {
-                    var isStringType;
-                    [condition, filterValue, isStringType] = generatedCondition;
-                    if (isStringType && ignoreCase)
-                        condition = condition.replace("#", "UPPER(#)").replace("?", "UPPER(?)");
+                var isStringType = pFilter.contenttype != "NUMBER" 
+                    && pFilter.contenttype != "DATE" 
+                    && pFilter.contenttype != "BOOLEAN";
+                [condition, filterValue] = generatedCondition;
+                if (isStringType && ignoreCase)
+                    condition = condition.replace("#", "UPPER(#)").replace("?", "UPPER(?)");
 
-                    if (pOperator == "AND")
-                        this.andIfSet(sqlField, filterValue, condition);
-                    else if (pOperator == "OR")
-                        this.orIfSet(sqlField, filterValue, condition);
-                }
+                if (pOperator == "AND")
+                    this.andIfSet(sqlField, filterValue, condition);
+                else if (pOperator == "OR")
+                    this.orIfSet(sqlField, filterValue, condition);
             }
         }
         else if (pFilter.type == "group")
@@ -297,53 +446,41 @@ JditoFilterUtils.getSqlCondition = function (pFilter, pTable, pTableAlias, pColu
         }
     }
     
-    //returns [condition, value with wildcards, is a string type] depending on the operator
+    //returns [condition, value with wildcards] depending on the operator
     function _getCondition (pValue, pOperator, pField)
     {
         switch (pOperator)
         {
             case "CONTAINS":
-                return [SqlBuilder.LIKE(), "%" + pValue + "%", true];
+                return [SqlBuilder.LIKE(), "%" + pValue + "%"];
             case "CONTAINSNOT":
-                return [SqlBuilder.NOT_LIKE(), "%" + pValue + "%", true];
+                return [SqlBuilder.NOT_LIKE(), "%" + pValue + "%"];
             case "STARTSWITH":
-                return [SqlBuilder.LIKE(), pValue + "%", true];
+                return [SqlBuilder.LIKE(), pValue + "%"];
             case "ENDSWITH":
-                return [SqlBuilder.LIKE(), "%" + pValue, true];
+                return [SqlBuilder.LIKE(), "%" + pValue];
             case "EQUAL":
-                return [SqlBuilder.EQUAL(), pValue, true];
+                return [SqlBuilder.EQUAL(), pValue];
             case "NOT_EQUAL":
-                return [SqlBuilder.NOT_EQUAL(), pValue, true];
+                return [SqlBuilder.NOT_EQUAL(), pValue];
             case "LESS":
-                return [SqlBuilder.LESS(), pValue, false];
+                return [SqlBuilder.LESS(), pValue];
             case "LESS_OR_EQUAL":
-                return [SqlBuilder.LESS_OR_EQUAL(), pValue, false];
+                return [SqlBuilder.LESS_OR_EQUAL(), pValue];
             case "GREATER":
-                return [SqlBuilder.GREATER(), pValue, false];
+                return [SqlBuilder.GREATER(), pValue];
             case "GREATER_OR_EQUAL":
-                return [SqlBuilder.GREATER_OR_EQUAL(), pValue, false];
+                return [SqlBuilder.GREATER_OR_EQUAL(), pValue];
             case "ISNULL":
-                return ["# is null", pValue, false];
+                return pField + " is null";
             case "ISNOTNULL":
-                return ["# is not null", pValue, false];
+                return pField + " is not null";
             case "TIMEFRAME_EQUAL":
             case "TIMEFRAME_COMING":
             case "TIMEFRAME_PAST":
                 var [start, end] = datetime.resolveRelativeDateExpression(pValue);
                 return newWhere(pField, start, SqlBuilder.GREATER_OR_EQUAL())
                     .and(pField, end, SqlBuilder.LESS_OR_EQUAL());
-                
-                
         }
     }
-}
-
-/**
- * @return {boolean} the selectionIgnoreCase property of the current user, defaults to true
- */
-JditoFilterUtils.isUserIgnoreCase = function ()
-{
-    var user = tools.getCurrentUser();
-    var ignoreCase = user ? user[tools.PARAMS][tools.SELECTION_IGNORECASE] : "";
-    return ignoreCase == "" || /true/i.test(ignoreCase);
-}
+}
\ No newline at end of file