Skip to content

Commit

Permalink
Rework spatial boolean methods (#2639)
Browse files Browse the repository at this point in the history
  • Loading branch information
PascalSenn committed Nov 22, 2020
1 parent 8be6cf6 commit f33e7b6
Show file tree
Hide file tree
Showing 60 changed files with 778 additions and 415 deletions.
Expand Up @@ -46,6 +46,11 @@ public static class SpatialFilterConventionDescriptorExtensions
descriptor.Operation(SpatialFilterOperations.Within).Name("within");
descriptor.Operation(SpatialFilterOperations.Buffer).Name("buffer");
descriptor.Operation(SpatialFilterOperations.Geometry).Name("geometry");
descriptor.Operation(SpatialFilterOperations.NotContains).Name("ncontains");
descriptor.Operation(SpatialFilterOperations.NotIntersects).Name("nintersects");
descriptor.Operation(SpatialFilterOperations.NotOverlaps).Name("noverlaps");
descriptor.Operation(SpatialFilterOperations.NotTouches).Name("ntouches");
descriptor.Operation(SpatialFilterOperations.NotWithin).Name("nwithin");

return descriptor;
}
Expand Down
Expand Up @@ -6,12 +6,24 @@ namespace HotChocolate.Data.Filters.Spatial
public static class SpatialFilterOperations
{
public const int Buffer = 513;

public const int Geometry = 514;

public const int Contains = 515;
public const int Distance = 516;
public const int Intersects = 517;
public const int Overlaps = 518;
public const int Touches = 519;
public const int Within = 520;
public const int NotContains = 516;

public const int Distance = 517;

public const int Intersects = 518;
public const int NotIntersects = 519;

public const int Overlaps = 520;
public const int NotOverlaps = 521;

public const int Touches = 522;
public const int NotTouches = 523;

public const int Within = 524;
public const int NotWithin = 525;
}
}
Expand Up @@ -12,10 +12,15 @@ public static class SpatialFilterProviderDescriptorQueryableExtensions
.AddFieldHandler<QueryableSpatialGeometryDataHandler>()
.AddFieldHandler<QueryableSpatialBufferDataHandler>()
.AddFieldHandler<QueryableSpatialContainsOperationHandler>()
.AddFieldHandler<QueryableSpatialNotContainsOperationHandler>()
.AddFieldHandler<QueryableSpatialDistanceOperationHandler>()
.AddFieldHandler<QueryableSpatialIntersectsOperationHandler>()
.AddFieldHandler<QueryableSpatialNotIntersectsOperationHandler>()
.AddFieldHandler<QueryableSpatialOverlapsOperationHandler>()
.AddFieldHandler<QueryableSpatialNotOverlapsOperationHandler>()
.AddFieldHandler<QueryableSpatialTouchesOperationHandler>()
.AddFieldHandler<QueryableSpatialWithinOperationHandler>();
.AddFieldHandler<QueryableSpatialNotTouchesOperationHandler>()
.AddFieldHandler<QueryableSpatialWithinOperationHandler>()
.AddFieldHandler<QueryableSpatialNotWithinOperationHandler>();
}
}
@@ -0,0 +1,112 @@
using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
using System.Reflection;
using HotChocolate.Configuration;
using HotChocolate.Data.Filters.Expressions;
using HotChocolate.Internal;
using HotChocolate.Language;
using HotChocolate.Language.Visitors;
using HotChocolate.Types.Descriptors;

namespace HotChocolate.Data.Filters.Spatial
{
public abstract class QueryableSpatialBooleanMethodHandler
: FilterFieldHandler<QueryableFilterContext, Expression>
{
private readonly IExtendedType _runtimeType;

protected abstract int Operation { get; }

protected abstract bool IsTrue { get; }
protected string GeometryFieldName { get; }
protected string BufferFieldName { get; }

protected QueryableSpatialBooleanMethodHandler(
IFilterConvention convention,
ITypeInspector inspector,
MethodInfo method)
{
_runtimeType = inspector.GetReturnType(method);
GeometryFieldName = convention.GetOperationName(SpatialFilterOperations.Geometry);
BufferFieldName = convention.GetOperationName(SpatialFilterOperations.Buffer);
}

public override bool CanHandle(
ITypeCompletionContext context,
IFilterInputTypeDefinition typeDefinition,
IFilterFieldDefinition fieldDefinition) =>
fieldDefinition is FilterOperationFieldDefinition op &&
op.Id == Operation;

public override bool TryHandleEnter(
QueryableFilterContext context,
IFilterField field,
ObjectFieldNode node,
[NotNullWhen(true)] out ISyntaxVisitorAction? action)
{
if (field is IFilterOperationField filterOperationField)
{
if (node.Value.IsNull())
{
context.ReportError(
ErrorHelper.CreateNonNullError(
field, node.Value, context));
action = SyntaxVisitor.Skip;
return true;
}

if (!TryHandleOperation(
context,
filterOperationField,
node,
out Expression? nestedProperty))
{
context.ReportError(
ErrorHelper.CouldNotCreateFilterForOperation(
field, node.Value, context));
action = SyntaxVisitor.Skip;
return true;
}

context.RuntimeTypes.Push(_runtimeType);
context.PushInstance(nestedProperty );
action = SyntaxVisitor.SkipAndLeave;
}
else
{
action = SyntaxVisitor.Break;
}

return true;
}

protected abstract bool TryHandleOperation(
QueryableFilterContext context,
IFilterOperationField field,
ObjectFieldNode node,
[NotNullWhen(true)] out Expression? result);

public override bool TryHandleLeave(
QueryableFilterContext context,
IFilterField field,
ObjectFieldNode node,
[NotNullWhen(true)] out ISyntaxVisitorAction? action)
{
// Dequeue last
Expression instance = context.PopInstance();
context.RuntimeTypes.Pop();
Expression condition = IsTrue ? instance : FilterExpressionBuilder.Not(instance);

if (context.InMemory)
{
condition = FilterExpressionBuilder.NotNullAndAlso(
context.GetInstance(),
condition);
}

context.GetLevel().Enqueue(condition);
action = SyntaxVisitor.Continue;
return true;
}
}
}
@@ -1,51 +1,19 @@
using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
using System.Reflection;
using HotChocolate.Data.Filters.Expressions;
using HotChocolate.Language;
using HotChocolate.Types.Descriptors;
using NetTopologySuite.Geometries;

namespace HotChocolate.Data.Filters.Spatial
{
public class QueryableSpatialContainsOperationHandler
: QueryableSpatialMethodHandler
: QueryableSpatialContainsOperationHandlerBase
{
private static readonly MethodInfo _contains =
typeof(Geometry).GetMethod(nameof(Geometry.Contains))!;

public QueryableSpatialContainsOperationHandler(
IFilterConvention convention,
ITypeInspector inspector)
: base(convention, inspector, _contains)
: base(convention, inspector)
{
}

protected override int Operation => SpatialFilterOperations.Contains;

protected override bool TryHandleOperation(
QueryableFilterContext context,
IFilterOperationField field,
ObjectFieldNode node,
[NotNullWhen(true)] out Expression? result)
{
if (TryGetParameter(field, node.Value, GeometryFieldName, out Geometry g))
{
if (TryGetParameter(field, node.Value, BufferFieldName, out double buffer))
{
result = ExpressionBuilder.Contains(
context.GetInstance(),
ExpressionBuilder.Buffer(g, buffer));

return true;
}

result = ExpressionBuilder.Contains(context.GetInstance(), g);
return true;
}

result = null;
return false;
}
protected override bool IsTrue => true;
}
}
@@ -0,0 +1,50 @@
using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
using System.Reflection;
using HotChocolate.Data.Filters.Expressions;
using HotChocolate.Language;
using HotChocolate.Types.Descriptors;
using NetTopologySuite.Geometries;
using static HotChocolate.Data.Filters.Spatial.SpatialOperationHandlerHelper;

namespace HotChocolate.Data.Filters.Spatial
{
public abstract class QueryableSpatialContainsOperationHandlerBase
: QueryableSpatialBooleanMethodHandler
{
private static readonly MethodInfo _contains =
typeof(Geometry).GetMethod(nameof(Geometry.Contains))!;

public QueryableSpatialContainsOperationHandlerBase(
IFilterConvention convention,
ITypeInspector inspector)
: base(convention, inspector, _contains)
{
}

protected override bool TryHandleOperation(
QueryableFilterContext context,
IFilterOperationField field,
ObjectFieldNode node,
[NotNullWhen(true)] out Expression? result)
{
if (TryGetParameter(field, node.Value, GeometryFieldName, out Geometry g))
{
if (TryGetParameter(field, node.Value, BufferFieldName, out double buffer))
{
result = ExpressionBuilder.Contains(
context.GetInstance(),
ExpressionBuilder.Buffer(g, buffer));

return true;
}

result = ExpressionBuilder.Contains(context.GetInstance(), g);
return true;
}

result = null;
return false;
}
}
}
@@ -1,11 +1,11 @@
using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
using System.Reflection;
using HotChocolate.Data.Filters;
using HotChocolate.Data.Filters.Expressions;
using HotChocolate.Language;
using HotChocolate.Types.Descriptors;
using NetTopologySuite.Geometries;
using static HotChocolate.Data.Filters.Spatial.SpatialOperationHandlerHelper;

namespace HotChocolate.Data.Filters.Spatial
{
Expand Down
@@ -1,51 +1,19 @@
using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
using System.Reflection;
using HotChocolate.Data.Filters.Expressions;
using HotChocolate.Language;
using HotChocolate.Types.Descriptors;
using NetTopologySuite.Geometries;

namespace HotChocolate.Data.Filters.Spatial
{
public class QueryableSpatialIntersectsOperationHandler
: QueryableSpatialMethodHandler
: QueryableSpatialIntersectsOperationHandlerBase
{
private static readonly MethodInfo _intersects =
typeof(Geometry).GetMethod(nameof(Geometry.Intersects))!;

public QueryableSpatialIntersectsOperationHandler(
IFilterConvention convention,
ITypeInspector inspector)
: base(convention, inspector, _intersects)
: base(convention, inspector)
{
}

protected override int Operation => SpatialFilterOperations.Intersects;

protected override bool TryHandleOperation(
QueryableFilterContext context,
IFilterOperationField field,
ObjectFieldNode node,
[NotNullWhen(true)] out Expression? result)
{
if (TryGetParameter(field, node.Value, GeometryFieldName, out Geometry g))
{
if (TryGetParameter(field, node.Value, BufferFieldName, out double buffer))
{
result = ExpressionBuilder.Intersects(
context.GetInstance(),
ExpressionBuilder.Buffer(g, buffer));

return true;
}

result = ExpressionBuilder.Intersects(context.GetInstance(), g);
return true;
}

result = null;
return false;
}
protected override bool IsTrue => true;
}
}
@@ -0,0 +1,50 @@
using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
using System.Reflection;
using HotChocolate.Data.Filters.Expressions;
using HotChocolate.Language;
using HotChocolate.Types.Descriptors;
using NetTopologySuite.Geometries;
using static HotChocolate.Data.Filters.Spatial.SpatialOperationHandlerHelper;

namespace HotChocolate.Data.Filters.Spatial
{
public abstract class QueryableSpatialIntersectsOperationHandlerBase
: QueryableSpatialBooleanMethodHandler
{
private static readonly MethodInfo _intersects =
typeof(Geometry).GetMethod(nameof(Geometry.Intersects))!;

public QueryableSpatialIntersectsOperationHandlerBase(
IFilterConvention convention,
ITypeInspector inspector)
: base(convention, inspector, _intersects)
{
}

protected override bool TryHandleOperation(
QueryableFilterContext context,
IFilterOperationField field,
ObjectFieldNode node,
[NotNullWhen(true)] out Expression? result)
{
if (TryGetParameter(field, node.Value, GeometryFieldName, out Geometry g))
{
if (TryGetParameter(field, node.Value, BufferFieldName, out double buffer))
{
result = ExpressionBuilder.Intersects(
context.GetInstance(),
ExpressionBuilder.Buffer(g, buffer));

return true;
}

result = ExpressionBuilder.Intersects(context.GetInstance(), g);
return true;
}

result = null;
return false;
}
}
}

0 comments on commit f33e7b6

Please sign in to comment.