Skip to content

[Backport 8.2] Simplify Indices type and API #6458

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
193 changes: 116 additions & 77 deletions src/Elastic.Clients.Elasticsearch/Common/Infer/Indices/Indices.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
Expand All @@ -14,132 +15,178 @@ namespace Elastic.Clients.Elasticsearch;

[DebuggerDisplay("{DebugDisplay,nq}")]
[JsonConverter(typeof(IndicesJsonConverter))]
public sealed class Indices : Union<Indices.AllIndicesMarker, Indices.ManyIndices>, IUrlParameter
public sealed class Indices : IUrlParameter, IEnumerable<IndexName>, IEquatable<Indices>
{
internal Indices(AllIndicesMarker all) : base(all) { }
private static readonly HashSet<IndexName> AllIndexList = new() { AllValue };

internal Indices(ManyIndices indices) : base(indices) { }
internal const string AllValue = "_all";
internal const string WildcardValue = "*";

internal Indices(IEnumerable<IndexName> indices) : base(new ManyIndices(indices)) { }
private readonly HashSet<IndexName>? _indices;
private readonly bool _isAllIndices;

internal Indices(IEnumerable<string> indices) : base(new ManyIndices(indices)) { }
internal Indices(IndexName indexName)
{
if (indexName.Equals(AllValue) || indexName.Equals(WildcardValue))
{
_isAllIndices = true;
_indices = AllIndexList;
return;
}

/// <summary>All indices. Represents _all</summary>
public static Indices All { get; } = new Indices(new AllIndicesMarker());
_indices = new HashSet<IndexName>
{
indexName
};
}

/// <inheritdoc cref="All" />
public static Indices AllIndices { get; } = All;
internal Indices(IEnumerable<IndexName> indices)
{
var enumerated = indices.NotEmpty(nameof(indices));

private string DebugDisplay => Match(
all => "_all",
types => $"Count: {types.Indices.Count} [" + string.Join(",", types.Indices.Select((t, i) => $"({i + 1}: {t.DebugDisplay})")) + "]"
);
foreach (var index in enumerated)
{
if (index.Equals(AllValue) || index.Equals(WildcardValue))
{
_isAllIndices = true;
_indices = AllIndexList;
return;
}
}

public override string ToString() => DebugDisplay;
_indices = new HashSet<IndexName>(enumerated);
}

string IUrlParameter.GetString(ITransportConfiguration? settings) => Match(
all => "_all",
many =>
{
if (settings is not IElasticsearchClientSettings clientSettings)
throw new Exception(
"Tried to pass index names on querysting but it could not be resolved because no nest settings are available");
internal Indices(IEnumerable<string> indices)
{
var enumerated = indices.NotEmpty(nameof(indices));

var infer = clientSettings.Inferrer;
var indices = many.Indices.Select(i => infer.IndexName(i)).Distinct();
return string.Join(",", indices);
foreach (var index in enumerated)
{
if (index.Equals(AllValue) || index.Equals(WildcardValue))
{
_isAllIndices = true;
_indices = AllIndexList;
return;
}
}
);

public static IndexName Index(string index) => index;
_indices = new HashSet<IndexName>(enumerated.Select(s => (IndexName)s));
}

public static IndexName Index(IndexName index) => index;
public Indices And<T>()
{
if (_isAllIndices)
return this;

public static IndexName Index<T>() => typeof(T);
_indices.Add(typeof(T));

return this;
}

internal HashSet<IndexName> IndexNames => _indices;

public static Indices All { get; } = new Indices(AllValue);

private string DebugDisplay => _isAllIndices ? "_all" : $"Count: {_indices.Count} [" + string.Join(",", _indices.Select((t, i) => $"({i + 1}: {t.DebugDisplay})")) + "]";

public static ManyIndices Index(IEnumerable<IndexName> indices) => new(indices);
public override string ToString() => DebugDisplay;

string IUrlParameter.GetString(ITransportConfiguration? settings)
{
if (settings is not IElasticsearchClientSettings clientSettings)
throw new Exception(
"Tried to pass index names on querysting but it could not be resolved because no nest settings are available.");

if (_isAllIndices)
return "_all";

public static ManyIndices Index(params IndexName[] indices) => new(indices);
var inferrer = clientSettings.Inferrer;

public static ManyIndices Index(IEnumerable<string> indices) => new(indices);
if (_indices.Count == 1)
{
var value = inferrer.IndexName(_indices.First());
return value;
}

var indices = _indices.Select(i => inferrer.IndexName(i));
return string.Join(",", indices);
}

public static ManyIndices Index(params string[] indices) => new(indices);
public static IndexName Index(string index) => index;

public static IndexName Index(IndexName index) => index;

public static IndexName Index<T>() => typeof(T);

public static Indices Parse(string indicesString)
{
if (indicesString.IsNullOrEmptyCommaSeparatedList(out var indices))
return null;

return indices.Contains("_all") ? All : Index(indices.Select(i => (IndexName)i));
return indices.Contains(AllValue) || indices.Contains(WildcardValue) ? All : new Indices(indices);
}

public static implicit operator Indices(string indicesString) => Parse(indicesString);

public static implicit operator Indices(ManyIndices many) => many == null ? null : new Indices(many);
public static implicit operator Indices(string[] indices) => indices.IsEmpty() ? null : new Indices(indices);

public static implicit operator Indices(string[] many) => many.IsEmpty() ? null : new ManyIndices(many);
public static implicit operator Indices(IndexName[] indices) => indices.IsEmpty() ? null : new Indices(indices);

public static implicit operator Indices(IndexName[] many) => many.IsEmpty() ? null : new ManyIndices(many);
public static implicit operator Indices(IndexName index) => index == null ? null : new Indices(new[] { index });

public static implicit operator Indices(IndexName index) => index == null ? null : new ManyIndices(new[] { index });

public static implicit operator Indices(Type type) => type == null ? null : new ManyIndices(new IndexName[] { type });
public static implicit operator Indices(Type type) => type == null ? null : new Indices(new IndexName[] { type });

public static bool operator ==(Indices left, Indices right) => Equals(left, right);

public static bool operator !=(Indices left, Indices right) => !Equals(left, right);

public bool Equals(Indices other) => EqualsAllIndices(IndexNames, other.IndexNames);

public override bool Equals(object obj)
{
if (!(obj is Indices other))
if (obj is not Indices other)
return false;

return Match(
all => other.Match(a => true, m => false),
many => other.Match(
a => false,
m => EqualsAllIndices(m.Indices, many.Indices)
)
);
return EqualsAllIndices(IndexNames, other.IndexNames);
}

private static bool EqualsAllIndices(IReadOnlyList<IndexName> thisIndices, IReadOnlyList<IndexName> otherIndices)
private static bool EqualsAllIndices(HashSet<IndexName> thisIndices, HashSet<IndexName> otherIndices)
{
if (thisIndices == null && otherIndices == null)
return true;

if (thisIndices == null || otherIndices == null)
return false;

return thisIndices.Count == otherIndices.Count && !thisIndices.Except(otherIndices).Any();
}

public override int GetHashCode() => Match(
all => "_all".GetHashCode(),
many => string.Concat(many.Indices.OrderBy(i => i.ToString())).GetHashCode()
);

public class AllIndicesMarker
{
internal AllIndicesMarker() { }
}

public class ManyIndices
public override int GetHashCode()
{
private readonly List<IndexName> _indices = new();
var hashCodes = new List<int>(IndexNames.Count);

internal ManyIndices(IEnumerable<IndexName> indices) => _indices.AddRange(indices.NotEmpty(nameof(indices)));

internal ManyIndices(IEnumerable<string> indices) =>
_indices.AddRange(indices.NotEmpty(nameof(indices)).Select(s => (IndexName)s));
foreach (var item in IndexNames.OrderBy(s => s))
{
hashCodes.Add(item.GetHashCode());
}

public IReadOnlyList<IndexName> Indices => _indices;
hashCodes.Sort();

public ManyIndices And<T>()
unchecked
{
_indices.Add(typeof(T));
return this;
var hash = 17;
foreach (var hashCode in hashCodes)
{
hash = hash * 23 + hashCode;
}
return typeof(IndexName).GetHashCode() ^ hash;
}
}

IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();

public IEnumerator<IndexName> GetEnumerator() => IndexNames.GetEnumerator();
}

internal sealed class IndicesJsonConverter : JsonConverter<Indices>
Expand Down Expand Up @@ -178,14 +225,6 @@ public override void Write(Utf8JsonWriter writer, Indices value, JsonSerializerO
return;
}

switch (value.Tag)
{
case 0:
writer.WriteStringValue("_all");
break;
case 1:
writer.WriteStringValue(((IUrlParameter)value).GetString(_settings));
break;
}
writer.WriteStringValue(((IUrlParameter)value).GetString(_settings));
}
}

This file was deleted.

2 changes: 1 addition & 1 deletion tests/Tests.Configuration/tests.default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# tracked by git).

# mode either u (unit test), i (integration test) or m (mixed mode)
mode: i
mode: u
# the elasticsearch version that should be started
# Can be a snapshot version of sonatype or "latest" to get the latest snapshot of sonatype
elasticsearch_version: latest-8
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ [U] public void Eq()
foreach (var t in equal)
{
(t == types).ShouldBeTrue(t);
t.Should().Be(types);
t.Should().BeEquivalentTo(types);
}

(Indices.All == "_all").Should().BeTrue();
Expand All @@ -32,7 +32,7 @@ [U] public void NotEq()
foreach (var t in notEqual)
{
(t != types).ShouldBeTrue(t);
t.Should().NotBe(types);
t.Should().NotBeEquivalentTo(types);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ [U] public void Fields()
Implicit<Fields>((Field[])null).Should().BeNull();
Implicit<Fields>("").Should().BeNull();
Implicit<Fields>(" ").Should().BeNull();
Implicit<Fields>(new string[] { }).Should().BeNull();
Implicit<Fields>(new Expression[] { }).Should().BeNull();
Implicit<Fields>(new PropertyInfo[] { }).Should().BeNull();
Implicit<Fields>(new Field[] { }).Should().BeNull();
Implicit<Fields>(Array.Empty<string>()).Should().BeNull();
Implicit<Fields>(Array.Empty<Expression>()).Should().BeNull();
Implicit<Fields>(Array.Empty<PropertyInfo>()).Should().BeNull();
Implicit<Fields>(Array.Empty<Field>()).Should().BeNull();
Implicit<Fields>(new Expression[] { null, null }).Should().BeNull();
Implicit<Fields>(new PropertyInfo[] { null, null }).Should().BeNull();
Implicit<Fields>(new Field[] { null, null }).Should().BeNull();
Expand All @@ -82,16 +82,15 @@ [U] public void IndexName()
[U] public void Indices()
{
Implicit<Indices>((string)null).Should().BeNull();
Implicit<Indices>((Indices.ManyIndices)null).Should().BeNull();
Implicit<Indices>((string[])null).Should().BeNull();
Implicit<Indices>((IndexName)null).Should().BeNull();
Implicit<Indices>((IndexName[])null).Should().BeNull();
Implicit<Indices>((IndexName)null).Should().BeNull();
Implicit<Indices>("").Should().BeNull();
Implicit<Indices>(" ").Should().BeNull();
Implicit<Indices>(",, ,, ").Should().BeNull();
Implicit<Indices>(new string[] { }).Should().BeNull();
Implicit<Indices>(new IndexName[] { }).Should().BeNull();
Implicit<Indices>(Array.Empty<string>()).Should().BeNull();
Implicit<Indices>(Array.Empty<IndexName>()).Should().BeNull();
Implicit<Indices>(new string[] { null, null }).Should().BeNull();
Implicit<Indices>(new IndexName[] { null, null }).Should().BeNull();
}
Expand All @@ -104,7 +103,7 @@ [U] public void Names()
Implicit<Names>(",,").Should().BeNull();
Implicit<Names>(", ,").Should().BeNull();
Implicit<Names>(" ").Should().BeNull();
Implicit<Names>(new string[] { }).Should().BeNull();
Implicit<Names>(Array.Empty<string>()).Should().BeNull();
Implicit<Names>(new string[] { null, null }).Should().BeNull();
}

Expand All @@ -116,7 +115,7 @@ [U] public void Routing()
Implicit<Routing>(",,").Should().BeNull();
Implicit<Routing>(", ,").Should().BeNull();
Implicit<Routing>(" ").Should().BeNull();
Implicit<Routing>(new string[] { }).Should().BeNull();
Implicit<Routing>(Array.Empty<string>()).Should().BeNull();
Implicit<Routing>(new string[] { null, null }).Should().BeNull();
}

Expand All @@ -138,7 +137,7 @@ [U] public void NodeId()
Implicit<NodeIds>("").Should().BeNull();
Implicit<NodeIds>(" ").Should().BeNull();
Implicit<NodeIds>(" ,, , ,,").Should().BeNull();
Implicit<NodeIds>(new string[] { }).Should().BeNull();
Implicit<NodeIds>(Array.Empty<string>()).Should().BeNull();
Implicit<NodeIds>(new string[] { null, null }).Should().BeNull();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ [U] public void EqualsValidation()

Indices indices1 = "foo,bar";
Indices indices2 = "bar,foo";
indices1.Should().Be(indices2);
indices1.Should().BeEquivalentTo(indices2);
(indices1 == indices2).Should().BeTrue();
}

Expand Down
Loading