Skip to content

Commit

Permalink
Merge pull request #70 from ZEXSM/feature/support-navigations
Browse files Browse the repository at this point in the history
feature/support navigations
  • Loading branch information
ZEXSM committed Jul 10, 2021
2 parents 6531eb2 + 70046f4 commit 6f8bf59
Show file tree
Hide file tree
Showing 12 changed files with 139 additions and 17 deletions.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,15 @@ var uri = new ODataQueryBuilder<ODataInfoContainer>("http://mock/odata")
.ToUri()
```
> http://mock/odata/ODataType("223123123")
```csharp
var uri = new ODataQueryBuilder<ODataInfoContainer>("http://mock/odata")
.For<ODataTypeEntity>(s => s.ODataType)
.ByKey(223123123)
.For<ODataKindEntity>(s => s.ODataKind)
.ByKey(223123123)
.ToUri()
```
> http://mock/odata/ODataType(223123123)/ODataKind(223123123)
#### <a name="ByList"/> ByList
```csharp
var uri = new ODataQueryBuilder<ODataInfoContainer>("http://mock/odata")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,23 @@ public AddressingEntries(StringBuilder stringBuilder, ODataQueryBuilderOptions o
_odataQueryBuilderOptions = odataQueryBuilderOptions;
}

public IODataQueryKey<TEntity> ByKey(int key)
public IODataQueryKey<TEntity> ByKey(params int[] keys)
{
_stringBuilder.Append($"({key}){QuerySeparators.Begin}");
_stringBuilder.Append($"({string.Join(QuerySeparators.Comma, keys)}){QuerySeparators.Begin}");

return new ODataQueryKey<TEntity>(_stringBuilder, _odataQueryBuilderOptions);
}

public IODataQueryKey<TEntity> ByKey(string key)
public IODataQueryKey<TEntity> ByKey(params string[] keys)
{
_stringBuilder.Append($"('{key}'){QuerySeparators.Begin}");
_stringBuilder.Append($"('{string.Join($"'{QuerySeparators.Comma}'", keys)}'){QuerySeparators.Begin}");

return new ODataQueryKey<TEntity>(_stringBuilder, _odataQueryBuilderOptions);
}

public IODataQueryKey<TEntity> ByKey(Guid key)
public IODataQueryKey<TEntity> ByKey(params Guid[] keys)
{
_stringBuilder.Append($"({key}){QuerySeparators.Begin}");
_stringBuilder.Append($"({string.Join(QuerySeparators.Comma, keys)}){QuerySeparators.Begin}");

return new ODataQueryKey<TEntity>(_stringBuilder, _odataQueryBuilderOptions);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ namespace OData.QueryBuilder.Conventions.AddressingEntities
{
public interface IAddressingEntries<TEntity>
{
IODataQueryKey<TEntity> ByKey(int key);
IODataQueryKey<TEntity> ByKey(params int[] keys);

IODataQueryKey<TEntity> ByKey(string key);
IODataQueryKey<TEntity> ByKey(params string[] keys);

IODataQueryKey<TEntity> ByKey(Guid key);
IODataQueryKey<TEntity> ByKey(params Guid[] keys);

IODataQueryCollection<TEntity> ByList();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using OData.QueryBuilder.Conventions.Constants;
using OData.QueryBuilder.Extensions;
using OData.QueryBuilder.Options;
using System.Text;

Expand All @@ -15,6 +16,6 @@ public AbstractODataQueryExpand(StringBuilder stringBuilder, ODataQueryBuilderOp
_odataQueryBuilderOptions = odataQueryBuilderOptions;
}

public string Query => _stringBuilder.ToString().Trim(QuerySeparators.Nested);
public StringBuilder Query => _stringBuilder.LastRemove(QuerySeparators.Nested);
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
using OData.QueryBuilder.Conventions.AddressingEntities.Options;
using System;
using System.Linq.Expressions;

namespace OData.QueryBuilder.Conventions.AddressingEntities.Query
{
public interface IODataQueryKey<TEntity> : IODataOptionKey<IODataQueryKey<TEntity>, TEntity>, IODataQuery
{
public IAddressingEntries<TResource> For<TResource>(Expression<Func<TEntity, object>> resource);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using OData.QueryBuilder.Conventions.Constants;
using OData.QueryBuilder.Extensions;
using OData.QueryBuilder.Options;
using System;
using System.Collections.Generic;
Expand Down Expand Up @@ -34,6 +35,12 @@ public ODataQuery(StringBuilder stringBuilder, ODataQueryBuilderOptions odataQue
return dictionary;
}

public Uri ToUri(UriKind uriKind = UriKind.RelativeOrAbsolute) => new Uri(_stringBuilder.ToString().TrimEnd(QuerySeparators.Main), uriKind);
public Uri ToUri(UriKind uriKind = UriKind.RelativeOrAbsolute)
{
_stringBuilder.LastRemove(QuerySeparators.Begin);
_stringBuilder.LastRemove(QuerySeparators.Main);

return new Uri(_stringBuilder.ToString(), uriKind);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using OData.QueryBuilder.Conventions.AddressingEntities.Resources.Expand;
using OData.QueryBuilder.Conventions.AddressingEntities.Resources;
using OData.QueryBuilder.Conventions.AddressingEntities.Resources.Expand;
using OData.QueryBuilder.Conventions.Constants;
using OData.QueryBuilder.Expressions.Visitors;
using OData.QueryBuilder.Extensions;
using OData.QueryBuilder.Options;
using System;
using System.Linq.Expressions;
Expand All @@ -15,6 +17,13 @@ public ODataQueryKey(StringBuilder stringBuilder, ODataQueryBuilderOptions odata
{
}

public IAddressingEntries<TResource> For<TResource>(Expression<Func<TEntity, object>> resource)
{
_stringBuilder.LastReplace(QuerySeparators.Begin, QuerySeparators.Slash);

return new ODataResource<TEntity>(_stringBuilder, _odataQueryBuilderOptions).For<TResource>(resource);
}

public IODataQueryKey<TEntity> Expand(Expression<Func<TEntity, object>> expand)
{
var query = new ODataOptionExpandExpressionVisitor().ToQuery(expand.Body);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ internal class ODataExpandResource<TEntity> : IODataExpandResource<TEntity>
private readonly StringBuilder _stringBuilder;
private AbstractODataQueryExpand _odataQueryExpand;

public string Query => $"{_stringBuilder}({_odataQueryExpand.Query})";
public StringBuilder Query => new StringBuilder($"{_stringBuilder}({_odataQueryExpand.Query})");

public ODataExpandResource(ODataQueryBuilderOptions odataQueryBuilderOptions)
{
Expand All @@ -25,7 +25,7 @@ public IODataQueryExpand<TNestedEntity> For<TNestedEntity>(Expression<Func<TEnti
{
var query = new ODataResourceExpressionVisitor().ToQuery(nestedExpand.Body);

if (!string.IsNullOrEmpty(_odataQueryExpand?.Query))
if (_odataQueryExpand?.Query != default && _odataQueryExpand?.Query.Length != 0)
{
_stringBuilder.Append($"({_odataQueryExpand.Query}),{query}");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ protected override string VisitMethodCallExpression(MethodCallExpression methodC
var ascending0 = VisitExpression(methodCallExpression.Arguments[0]);

var ascendingQuery = VisitExpression(methodCallExpression.Object as MethodCallExpression);
var ascendingQueryComma = ascendingQuery == default ? string.Empty : ",";
var ascendingQueryComma = ascendingQuery == default ? string.Empty : QuerySeparators.Comma;

return $"{ascendingQuery}{ascendingQueryComma}{ascending0} {QuerySorts.Asc}";
case nameof(ISortFunction.Descending):
var descending0 = VisitExpression(methodCallExpression.Arguments[0]);

var descendingQuery = VisitExpression(methodCallExpression.Object as MethodCallExpression);
var descendingQueryComma = descendingQuery == default ? string.Empty : ",";
var descendingQueryComma = descendingQuery == default ? string.Empty : QuerySeparators.Comma;

return $"{descendingQuery}{descendingQueryComma}{descending0} {QuerySorts.Desc}";
default:
Expand Down
31 changes: 31 additions & 0 deletions src/OData.QueryBuilder/Extensions/StringBuilderExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System.Text;

namespace OData.QueryBuilder.Extensions
{
internal static class StringBuilderExtensions
{
public static StringBuilder LastRemove(this StringBuilder stringBuilder, char @char)
{
var lastIndex = stringBuilder.Length - 1;

if (stringBuilder[lastIndex] == @char)
{
stringBuilder.Remove(lastIndex, 1);
}

return stringBuilder;
}

public static StringBuilder LastReplace(this StringBuilder stringBuilder, char oldChar, char newChar)
{
var lastIndex = stringBuilder.Length - 1;

if (stringBuilder[lastIndex] == oldChar)
{
stringBuilder[lastIndex] = newChar;
}

return stringBuilder;
}
}
}
1 change: 0 additions & 1 deletion src/OData.QueryBuilder/Extensions/StringExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using OData.QueryBuilder.Conventions.Constants;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Text;

namespace OData.QueryBuilder.Extensions
Expand Down
63 changes: 63 additions & 0 deletions test/OData.QueryBuilder.Test/ODataQueryKeyTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,17 @@ public void ODataQueryBuilderKey_Expand_Simple_Success()
uri.Should().Be("http://mock/odata/ODataType(223123123)?$expand=ODataKind");
}

[Fact(DisplayName = "Simple with key ints => Success")]
public void ODataQueryBuilderKey_Simple_With_Key_Ints_Success()
{
var uri = _odataQueryBuilderDefault
.For<ODataTypeEntity>(s => s.ODataType)
.ByKey(223123123, 223123124, 223123125)
.ToUri();

uri.Should().Be("http://mock/odata/ODataType(223123123,223123124,223123125)");
}

[Fact(DisplayName = "Expand simple with key string => Success")]
public void ODataQueryBuilderKey_Expand_Simple_With_Key_String_Success()
{
Expand All @@ -40,6 +51,17 @@ public void ODataQueryBuilderKey_Expand_Simple_With_Key_String_Success()
uri.Should().Be("http://mock/odata/ODataType('223123123')?$expand=ODataKind");
}

[Fact(DisplayName = "Simple with key strings => Success")]
public void ODataQueryBuilderKey_Simple_With_Key_Strings_Success()
{
var uri = _odataQueryBuilderDefault
.For<ODataTypeEntity>(s => s.ODataType)
.ByKey("223123123", "223123124", "223123125")
.ToUri();

uri.Should().Be("http://mock/odata/ODataType('223123123','223123124','223123125')");
}

[Fact(DisplayName = "Expand simple with key guid => Success")]
public void ODataQueryBuilderKey_Expand_Simple_With_Key_Guid_Success()
{
Expand All @@ -54,6 +76,20 @@ public void ODataQueryBuilderKey_Expand_Simple_With_Key_Guid_Success()
uri.Should().Be($"http://mock/odata/ODataType({id})?$expand=ODataKind");
}

[Fact(DisplayName = "Simple with key guids => Success")]
public void ODataQueryBuilderKey_Simple_With_Key_Guids_Success()
{
var id1 = Guid.NewGuid();
var id2 = Guid.NewGuid();

var uri = _odataQueryBuilderDefault
.For<ODataTypeEntity>(s => s.ODataType)
.ByKey(id1, id2)
.ToUri();

uri.Should().Be($"http://mock/odata/ODataType({id1},{id2})");
}

[Fact(DisplayName = "Select simple => Success")]
public void ODataQueryBuilderKey_Select_Simple_Success()
{
Expand Down Expand Up @@ -95,5 +131,32 @@ public void ToDicionaryTest()

dictionary.Should().BeEquivalentTo(resultEquivalent);
}

[Fact(DisplayName = "Navigation properties => Success")]
public void Navigation_properties_test_success()
{
var uri = _odataQueryBuilderDefault
.For<ODataTypeEntity>(s => s.ODataType)
.ByKey(223123123)
.For<ODataKindEntity>(s => s.ODataKind)
.ByKey(223123124)
.ToUri();

uri.Should().Be("http://mock/odata/ODataType(223123123)/ODataKind(223123124)");
}

[Fact(DisplayName = "Navigation properties with select => Success")]
public void Navigation_properties_test_with_select_success()
{
var uri = _odataQueryBuilderDefault
.For<ODataTypeEntity>(s => s.ODataType)
.ByKey("223123123")
.For<ODataKindEntity>(s => s.ODataKind)
.ByKey("223123124")
.Select(s => s.Color)
.ToUri();

uri.Should().Be("http://mock/odata/ODataType('223123123')/ODataKind('223123124')?$select=Color");
}
}
}

0 comments on commit 6f8bf59

Please sign in to comment.