Skip to content

Commit 992adcb

Browse files
committed
Adding StartsWith and EndsWith filter functionality
1 parent 50612f6 commit 992adcb

File tree

1 file changed

+58
-3
lines changed

1 file changed

+58
-3
lines changed

src/DatatablesParser/DatatablesParser.cs

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ public class Parser<T> where T : class
1919
private int _take;
2020
private int _skip;
2121
private bool _sortDisabled = false;
22+
private string _startsWithtoken = "*|";
23+
private string _endsWithToken = "|*";
2224

2325
private Dictionary<string,Expression> _converters = new Dictionary<string, Expression>();
2426

@@ -166,6 +168,35 @@ public Parser<T> SetConverter(Expression<Func<T,object>> property, Expression<Fu
166168
return this;
167169
}
168170

171+
///<summary>
172+
/// SetStartsWithToken overrides the default StartsWith filter token
173+
/// The default token is *|
174+
/// By default all filters are in the form of string.Contains(FILTER_STRING)
175+
/// If a filter string is in the form of token + FILTER_STRING eg. *|app,
176+
/// the search will be translated to string.StartsWith("app")
177+
///</summary>
178+
/// <param name="token">A string used to replace the default token</param>
179+
public Parser<T> SetStartsWithToken(string token)
180+
{
181+
this._startsWithtoken = token;
182+
return this;
183+
}
184+
185+
///<summary>
186+
/// SetEndsWithToken overrides the default EndsWith filter token
187+
/// The default token is |*
188+
/// By default all filters are in the form of string.Contains(FILTER_STRING)
189+
/// If a filter string is in the form of FILTER_STRING + token eg. app|*,
190+
/// the search will be translated to string.EndsWith("app")
191+
///</summary>
192+
/// <param name="token">A string used to replace the default token</param>
193+
public Parser<T> SetEndsWithToken(string token)
194+
{
195+
this._endsWithToken = token;
196+
return this;
197+
}
198+
199+
169200
private void ApplySort()
170201
{
171202
var sorted = false;
@@ -268,6 +299,23 @@ private bool EnumerablFilter(T item)
268299

269300
}
270301

302+
private string GetFilterFn(string filter)
303+
{
304+
switch(filter)
305+
{
306+
case null:
307+
return Constants.CONTAINS_FN;
308+
case var f when f.StartsWith(_startsWithtoken) && f.EndsWith(_endsWithToken):
309+
return Constants.CONTAINS_FN;
310+
case var f when f.StartsWith(_startsWithtoken):
311+
return Constants.STARTS_WITH_FN;
312+
case var f when f.EndsWith(_endsWithToken):
313+
return Constants.ENDS_WITH_FN;
314+
default:
315+
return Constants.CONTAINS_FN;
316+
}
317+
}
318+
271319
/// <summary>
272320
/// Generate a lamda expression based on a search filter for all mapped columns
273321
/// </summary>
@@ -277,11 +325,12 @@ private Expression<Func<T, bool>> GenerateEntityFilter()
277325
var paramExpression = Expression.Parameter(_type, "val");
278326

279327
string filter = _config[Constants.SEARCH_KEY];
280-
328+
string globalFilterFn = null;
281329
ConstantExpression globalFilterConst = null;
282330
Expression filterExpr = null;
283331
if(!string.IsNullOrWhiteSpace(filter))
284332
{
333+
globalFilterFn = GetFilterFn(filter);
285334
globalFilterConst = Expression.Constant(filter.ToLower());
286335
}
287336

@@ -293,6 +342,7 @@ private Expression<Func<T, bool>> GenerateEntityFilter()
293342
var prop = propMap.Value.Property;
294343
var isString = prop.PropertyType == typeof(string);
295344
var hasCustomExpr = _converters.ContainsKey(prop.Name);
345+
string propFilterFn = null;
296346

297347
if ((!prop.CanWrite || (!_convertable.Any(t => t == prop.PropertyType) && !isString )) && !hasCustomExpr )
298348
{
@@ -302,6 +352,7 @@ private Expression<Func<T, bool>> GenerateEntityFilter()
302352
ConstantExpression individualFilterConst = null;
303353
if(!string.IsNullOrWhiteSpace(propMap.Value.Filter))
304354
{
355+
propFilterFn = GetFilterFn(propMap.Value.Filter);
305356
individualFilterConst = Expression.Constant(propMap.Value.Filter.ToLower());
306357
}
307358

@@ -323,7 +374,7 @@ private Expression<Func<T, bool>> GenerateEntityFilter()
323374

324375
if(globalFilterConst!=null)
325376
{
326-
var globalTest = Expression.Call(toLower, typeof(string).GetMethod("Contains", new[] { typeof(string) }), globalFilterConst);
377+
var globalTest = Expression.Call(toLower, typeof(string).GetMethod(globalFilterFn, new[] { typeof(string) }), globalFilterConst);
327378

328379
if(filterExpr == null)
329380
{
@@ -337,7 +388,7 @@ private Expression<Func<T, bool>> GenerateEntityFilter()
337388

338389
if(individualFilterConst!=null)
339390
{
340-
individualConditions.Add(Expression.Call(toLower, typeof(string).GetMethod("Contains", new[] { typeof(string) }), individualFilterConst));
391+
individualConditions.Add(Expression.Call(toLower, typeof(string).GetMethod(propFilterFn, new[] { typeof(string) }), individualFilterConst));
341392

342393
}
343394

@@ -419,6 +470,10 @@ public class Constants
419470
public const string ORDER_DIRECTION_FORMAT = "order[{0}][dir]";
420471
public const string ORDERING_ENABLED = "ordering";
421472

473+
public const string CONTAINS_FN = "Contains";
474+
public const string STARTS_WITH_FN = "StartsWith";
475+
public const string ENDS_WITH_FN = "EndsWith";
476+
422477
public static string GetKey(string format,string index)
423478
{
424479
return String.Format(format, index);

0 commit comments

Comments
 (0)