|
/** |
|
* Copyright 2017 d-fens GmbH |
|
* |
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
* you may not use this file except in compliance with the License. |
|
* You may obtain a copy of the License at |
|
* |
|
* http://www.apache.org/licenses/LICENSE-2.0 |
|
* |
|
* Unless required by applicable law or agreed to in writing, software |
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
* See the License for the specific language governing permissions and |
|
* limitations under the License. |
|
*/ |
|
|
|
using System; |
|
using System.Collections.Generic; |
|
using System.Collections.ObjectModel; |
|
using System.Diagnostics.Contracts; |
|
using System.Linq; |
|
using System.Text; |
|
using System.Web.Http.OData.Query; |
|
using biz.dfch.CS.Commons.Linq; |
|
using Net.Appclusive.Public.Domain; |
|
|
|
namespace Net.Appclusive.WebApi.OdataServices |
|
{ |
|
public class ODataQueryOptionsUtilities |
|
{ |
|
public const char QUERY_OPTIONS_PREFIX = '?'; |
|
public const char QUERY_OPTIONS_SEPARATOR = '&'; |
|
public const char QUERY_OPTIONS_DELIMITER = '='; |
|
public const string QUERY_OPTION_EXPAND = "$expand"; |
|
public const string QUERY_OPTION_SELECT = "$select"; |
|
public const string QUERY_OPTION_SKIP = "$skip"; |
|
public const string QUERY_OPTION_TOP = "$top"; |
|
public const char QUERY_OPTION_SELECT_EXPAND_DELIMITER = ','; |
|
|
|
public static ODataQueryOptions Transform |
|
( |
|
ODataQueryOptions queryOptions, |
|
ODataQueryOptionsUtilitiesTransformSettings settings |
|
) |
|
{ |
|
Contract.Requires(null != queryOptions); |
|
Contract.Requires(null != settings); |
|
Contract.Ensures(null != Contract.Result<ODataQueryOptions>()); |
|
|
|
return Transform |
|
( |
|
queryOptions: queryOptions, |
|
transformFilter: settings.Filter, |
|
transformOrderBy: settings.OrderBy, |
|
transformExpand: settings.Expand, |
|
transformSelect: settings.Select, |
|
transformSkip: settings.Skip, |
|
transformTop: settings.Top |
|
); |
|
} |
|
|
|
public static ODataQueryOptions Transform |
|
( |
|
ODataQueryOptions queryOptions, |
|
Func<IReadOnlyDictionary<string, string>, FilterQueryOption, string> transformFilter, |
|
Func<IReadOnlyDictionary<string, string>, OrderByQueryOption, IList<string>> transformOrderBy, |
|
Func<IReadOnlyDictionary<string, string>, SelectExpandQueryOption, IList<string>> transformExpand, |
|
Func<IReadOnlyDictionary<string, string>, SelectExpandQueryOption, IList<string>> transformSelect, |
|
Func<IReadOnlyDictionary<string, string>, SkipQueryOption, int?> transformSkip, |
|
Func<IReadOnlyDictionary<string, string>, TopQueryOption, int?> transformTop |
|
) |
|
{ |
|
Contract.Requires(null != queryOptions); |
|
Contract.Ensures(null != Contract.Result<ODataQueryOptions>()); |
|
|
|
var uri = queryOptions.Request.RequestUri; |
|
var queryParameters = uri.Query |
|
.TrimStart(QUERY_OPTIONS_PREFIX) |
|
.Split(new[] { QUERY_OPTIONS_SEPARATOR }, StringSplitOptions.RemoveEmptyEntries) |
|
.ToDictionary |
|
( |
|
e => e.Split(QUERY_OPTIONS_DELIMITER).FirstOrDefault(), |
|
e => e.Split(QUERY_OPTIONS_DELIMITER).LastOrDefault() |
|
); |
|
|
|
if (null != transformFilter) |
|
{ |
|
var result = transformFilter(new ReadOnlyDictionary<string, string>(queryParameters), queryOptions.Filter); |
|
if (null != result) |
|
{ |
|
queryParameters[QUERY_OPTION_EXPAND] = result; |
|
} |
|
} |
|
|
|
if (null != transformOrderBy) |
|
{ |
|
var result = transformOrderBy(new ReadOnlyDictionary<string, string>(queryParameters), queryOptions.OrderBy); |
|
if (null != result) |
|
{ |
|
queryParameters[QUERY_OPTION_EXPAND] = string.Join(QUERY_OPTION_SELECT_EXPAND_DELIMITER.ToString(), result); |
|
} |
|
} |
|
|
|
if (null != transformExpand) |
|
{ |
|
var result = transformExpand(new ReadOnlyDictionary<string, string>(queryParameters), queryOptions.SelectExpand); |
|
if (null != result) |
|
{ |
|
queryParameters[QUERY_OPTION_EXPAND] = string.Join(QUERY_OPTION_SELECT_EXPAND_DELIMITER.ToString(), result); |
|
} |
|
} |
|
|
|
if (null != transformSelect) |
|
{ |
|
var result = transformSelect(new ReadOnlyDictionary<string, string>(queryParameters), queryOptions.SelectExpand); |
|
if (null != result) |
|
{ |
|
queryParameters[QUERY_OPTION_SELECT] = string.Join(QUERY_OPTION_SELECT_EXPAND_DELIMITER.ToString(), result); |
|
} |
|
} |
|
|
|
if (null != transformSkip) |
|
{ |
|
var result = transformSkip(new ReadOnlyDictionary<string, string>(queryParameters), queryOptions.Skip); |
|
if (result.HasValue) |
|
{ |
|
queryParameters[QUERY_OPTION_SKIP] = result.Value.ToString(); |
|
} |
|
else |
|
{ |
|
if (queryParameters.ContainsKey(QUERY_OPTION_SKIP)) |
|
{ |
|
queryParameters.Remove(QUERY_OPTION_SKIP); |
|
} |
|
} |
|
} |
|
|
|
if (null != transformTop) |
|
{ |
|
var result = transformTop(new ReadOnlyDictionary<string, string>(queryParameters), queryOptions.Top); |
|
if (result.HasValue) |
|
{ |
|
queryParameters[QUERY_OPTION_TOP] = result.Value.ToString(); |
|
} |
|
else |
|
{ |
|
if (queryParameters.ContainsKey(QUERY_OPTION_TOP)) |
|
{ |
|
queryParameters.Remove(QUERY_OPTION_TOP); |
|
} |
|
} |
|
} |
|
|
|
var newQueryOptions = new StringBuilder(); |
|
queryParameters.ForEach(e => |
|
{ |
|
newQueryOptions.Append(QUERY_OPTIONS_SEPARATOR); |
|
newQueryOptions.Append(e.Key); |
|
newQueryOptions.Append(QUERY_OPTIONS_DELIMITER); |
|
newQueryOptions.Append(e.Value); |
|
}); |
|
|
|
queryOptions.Request.RequestUri = |
|
new Uri($"{uri.Scheme}://{uri.Authority}{uri.AbsolutePath}{QUERY_OPTIONS_PREFIX}{newQueryOptions}"); |
|
|
|
var newOdataQueryOptions = (ODataQueryOptions)Activator.CreateInstance(queryOptions.GetType(), queryOptions.Context, queryOptions.Request); |
|
|
|
return newOdataQueryOptions; |
|
} |
|
} |
|
} |
This comment has been minimized.
@dfch
https://gist.github.com/victorperez2911/a23989aa73263f5b285e9a0961d90260
Victor Perez