text: /*!
   * SAP UI development toolkit for HTML5 (SAPUI5/OpenUI5)
   * (c) Copyright 2009-2015 SAP SE or an SAP affiliate company.
   * Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
   */
  
  sap.ui.define(['jquery.sap.global'],
  	function(jQuery) {
  	"use strict";
  	
  	/**
  	 * Clientside Filter processor
  	 * @namespace sap.ui.model.FilterProcessor
  	 */
  	var FilterProcessor = {};
  
  	/**
  	 * Filters the list
  	 * Filters are first grouped according to their binding path.
  	 * All filters belonging to a group are ORed and after that the
  	 * results of all groups are ANDed.
  	 * Usually this means, all filters applied to a single table column
  	 * are ORed, while filters on different table columns are ANDed.
  	 * Multiple MultiFilters are ORed.
  	 * 
  	 * @param {array} aData the data array to be filtered
  	 * @param {array} aFilters the filter array
  	 * @param {function} fnGetValue the method to get the actual value to filter on
  	 *
  	 * @public
  	 */
  	FilterProcessor.apply = function(aData, aFilters, fnGetValue){
  		if (!aFilters || aFilters.length == 0) {
  			return aData;
  		}
  		var that = this,
  			oFilterGroups = {},
  			aFilterGroup,
  			aFiltered = [],
  			bGroupFiltered = false,
  			bFiltered = true;
  	
  		jQuery.each(aFilters, function(j, oFilter) {
  			if (oFilter.sPath !== undefined) {
  				aFilterGroup = oFilterGroups[oFilter.sPath];
  				if (!aFilterGroup) {
  					aFilterGroup = oFilterGroups[oFilter.sPath] = [];
  				}
  			} else {
  				aFilterGroup = oFilterGroups["__multiFilter"];
  				if (!aFilterGroup) {
  					aFilterGroup = oFilterGroups["__multiFilter"] = [];
  				}
  			}
  			aFilterGroup.push(oFilter);
  		});
  		jQuery.each(aData, function(i, vRef) {
  			bFiltered = true;
  			jQuery.each(oFilterGroups, function(sPath, aFilterGroup) {
  				if (sPath !== "__multiFilter") {
  					var oValue = fnGetValue(vRef, sPath);
  					oValue = that.normalizeFilterValue(oValue);
  					bGroupFiltered = false;
  					jQuery.each(aFilterGroup, function(j, oFilter) {
  						var fnTest = that.getFilterFunction(oFilter);
  						if (oValue != undefined && fnTest(oValue)) {
  							bGroupFiltered = true;
  							return false;
  						}
  					});
  				} else {
  					bGroupFiltered = false;
  					jQuery.each(aFilterGroup, function(j, oFilter) {
  						bGroupFiltered = that._resolveMultiFilter(oFilter, vRef, fnGetValue);
  						if (bGroupFiltered) {
  							return false;
  						}
  					});
  				}
  				if (!bGroupFiltered) {
  					bFiltered = false;
  					return false;
  				}
  			});
  			if (bFiltered) {
  				aFiltered.push(vRef);
  			}
  		});
  		return aFiltered;
  	};
  
  	/**
  	 * Normalize filter value
  	 * 
  	 * @private
  	 */
  	FilterProcessor.normalizeFilterValue = function(oValue){
  		if (typeof oValue == "string") {
  			return oValue.toUpperCase();
  		}
  		if (oValue instanceof Date) {
  			return oValue.getTime();
  		}
  		return oValue;
  	};
  	
  	/**
  	 * Resolve the client list binding and check if an index matches
  	 *
  	 * @private
  	 */
  	FilterProcessor._resolveMultiFilter = function(oMultiFilter, vRef, fnGetValue){
  		var that = this,
  			bMatched = false,
  			aFilters = oMultiFilter.aFilters;
  		
  		if (aFilters) {
  			jQuery.each(aFilters, function(i, oFilter) {
  				var bLocalMatch = false;
  				if (oFilter._bMultiFilter) {
  					bLocalMatch = that._resolveMultiFilter(oFilter, vRef, fnGetValue);
  				} else if (oFilter.sPath !== undefined) {
  					var oValue = fnGetValue(vRef, oFilter.sPath);
  					oValue = that.normalizeFilterValue(oValue);
  					var fnTest = that.getFilterFunction(oFilter);
  					if (oValue != undefined && fnTest(oValue)) {
  						bLocalMatch = true;
  					}
  				}
  				if (bLocalMatch && oMultiFilter.bAnd) {
  					bMatched = true;
  				} else if (!bLocalMatch && oMultiFilter.bAnd) {
  					bMatched = false;
  					return false;
  				} else if (bLocalMatch) {
  					bMatched = true;
  					return false;
  				}
  			});
  		}
  		
  		return bMatched;
  	};
  	
  	/**
  	 * Provides a JS filter function for the given filter
  	 */
  	FilterProcessor.getFilterFunction = function(oFilter){
  		if (oFilter.fnTest) {
  			return oFilter.fnTest;
  		}
  		var oValue1 = this.normalizeFilterValue(oFilter.oValue1),
  			oValue2 = this.normalizeFilterValue(oFilter.oValue2);
  	
  		switch (oFilter.sOperator) {
  			case "EQ":
  				oFilter.fnTest = function(value) { return value == oValue1; }; break;
  			case "NE":
  				oFilter.fnTest = function(value) { return value != oValue1; }; break;
  			case "LT":
  				oFilter.fnTest = function(value) { return value < oValue1; }; break;
  			case "LE":
  				oFilter.fnTest = function(value) { return value <= oValue1; }; break;
  			case "GT":
  				oFilter.fnTest = function(value) { return value > oValue1; }; break;
  			case "GE":
  				oFilter.fnTest = function(value) { return value >= oValue1; }; break;
  			case "BT":
  				oFilter.fnTest = function(value) { return (value >= oValue1) && (value <= oValue2); }; break;
  			case "Contains":
  				oFilter.fnTest = function(value) {
  					if (typeof value != "string") {
  						throw new Error("Only \"String\" values are supported for the FilterOperator: \"Contains\".");
  					}
  					return value.indexOf(oValue1) != -1;
  				};
  				break;
  			case "StartsWith":
  				oFilter.fnTest = function(value) {
  					if (typeof value != "string") {
  						throw new Error("Only \"String\" values are supported for the FilterOperator: \"StartsWith\".");
  					}
  					return value.indexOf(oValue1) == 0;
  				};
  				break;
  			case "EndsWith":
  				oFilter.fnTest = function(value) {
  					if (typeof value != "string") {
  						throw new Error("Only \"String\" values are supported for the FilterOperator: \"EndsWith\".");
  					}
  					var iPos = value.lastIndexOf(oValue1);
  					if (iPos == -1) {
  						return false;
  					}
  					return iPos == value.length - new String(oFilter.oValue1).length;
  				};
  				break;
  			default:
  				oFilter.fnTest = function(value) { return true; };
  		}
  		return oFilter.fnTest;
  	};
  	
  	return FilterProcessor;
  	
  });
  	