diff --git a/src/Nest/CommonAbstractions/Extensions/Extensions.cs b/src/Nest/CommonAbstractions/Extensions/Extensions.cs index 1c470da587e..74602c5102e 100644 --- a/src/Nest/CommonAbstractions/Extensions/Extensions.cs +++ b/src/Nest/CommonAbstractions/Extensions/Extensions.cs @@ -183,6 +183,13 @@ internal static bool HasAny(this IEnumerable list) return list != null && list.Any(); } + internal static bool IsEmpty(this IEnumerable list) + { + if (list == null) return true; + var enumerable = list as T[] ?? list.ToArray(); + return !enumerable.Any() || enumerable.All(t => t == null); + } + internal static void ThrowIfNull(this T value, string name, string message = null) { if (value == null && message.IsNullOrEmpty()) throw new ArgumentNullException(name); @@ -193,6 +200,16 @@ internal static bool IsNullOrEmpty(this string value) { return string.IsNullOrWhiteSpace(value); } + internal static bool IsNullOrEmptyCommaSeparatedList(this string value, out string[] split) + { + split = null; + if (string.IsNullOrWhiteSpace(value)) return true; + split = value.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries) + .Where(t=>!t.IsNullOrEmpty()) + .Select(t=>t.Trim()) + .ToArray(); + return split.Length == 0; + } internal static void ForEach(this IEnumerable enumerable, Action handler) { @@ -282,5 +299,13 @@ private static async Task ProcessAsync( additionalRateLimiter?.Release(); } } + + internal static bool NullOrEquals(this T o, T other) + { + if (o == null && other == null) return true; + if (o == null || other == null) return false; + return o.Equals(other); + } + } } diff --git a/src/Nest/CommonAbstractions/Infer/ActionIds/ActionIds.cs b/src/Nest/CommonAbstractions/Infer/ActionIds/ActionIds.cs index 660de9009bd..72a8489068a 100644 --- a/src/Nest/CommonAbstractions/Infer/ActionIds/ActionIds.cs +++ b/src/Nest/CommonAbstractions/Infer/ActionIds/ActionIds.cs @@ -2,16 +2,15 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using System.Text; -using System.Threading.Tasks; using Elasticsearch.Net; namespace Nest { [DebuggerDisplay("{DebugDisplay,nq}")] - public class ActionIds : IUrlParameter + public class ActionIds : IUrlParameter, IEquatable { private readonly List _actionIds; + internal IReadOnlyList Ids => _actionIds; public ActionIds(IEnumerable actionIds) { @@ -31,8 +30,23 @@ public ActionIds(string actionIds) string IUrlParameter.GetString(IConnectionConfigurationValues settings) => string.Join(",", this._actionIds); - public static implicit operator ActionIds(string actionIds) => new ActionIds(actionIds); + public static implicit operator ActionIds(string actionIds) => actionIds.IsNullOrEmptyCommaSeparatedList(out var list) ? null : new ActionIds(list); - public static implicit operator ActionIds(string[] actionIds) => new ActionIds(actionIds); + public static implicit operator ActionIds(string[] actionIds) => actionIds.IsEmpty() ? null : new ActionIds(actionIds); + + public bool Equals(ActionIds other) + { + if (this.Ids == null && other.Ids == null) return true; + if (this.Ids == null || other.Ids == null) return false; + return this.Ids.Count == other.Ids.Count && !this.Ids.Except(other.Ids).Any(); + } + + public override bool Equals(object obj) => obj is ActionIds other && Equals(other); + + public override int GetHashCode() => this._actionIds.GetHashCode(); + + public static bool operator ==(ActionIds left, ActionIds right) => Equals(left, right); + + public static bool operator !=(ActionIds left, ActionIds right) => !Equals(left, right); } } diff --git a/src/Nest/CommonAbstractions/Infer/CategoryId/CategoryId.cs b/src/Nest/CommonAbstractions/Infer/CategoryId/CategoryId.cs index 1f8b19c00e1..df4e1801e22 100644 --- a/src/Nest/CommonAbstractions/Infer/CategoryId/CategoryId.cs +++ b/src/Nest/CommonAbstractions/Infer/CategoryId/CategoryId.cs @@ -1,19 +1,38 @@ -using System.Globalization; +using System; +using System.Globalization; using Elasticsearch.Net; namespace Nest { - public class CategoryId : IUrlParameter + public class CategoryId : IUrlParameter, IEquatable { - private readonly long _categoryId; + internal readonly long Value; - public CategoryId(long categoryId) + public CategoryId(long value) => Value = value; + + public static implicit operator CategoryId(long categoryId) => new CategoryId(categoryId); + public static implicit operator long(CategoryId categoryId) => categoryId.Value; + + // ReSharper disable once ImpureMethodCallOnReadonlyValueField + public string GetString(IConnectionConfigurationValues settings) => Value.ToString(CultureInfo.InvariantCulture); + + public bool Equals(CategoryId other) => this.Value == other.Value; + + public override bool Equals(object obj) { - _categoryId = categoryId; + switch (obj) + { + case int l: return this.Value == l; + case long l: return this.Value == l; + case CategoryId i: return this.Value == i.Value; + default: return false; + } } - public static implicit operator CategoryId(long categoryId) => new CategoryId(categoryId); + public override int GetHashCode() => this.Value.GetHashCode(); + + public static bool operator ==(CategoryId left, CategoryId right) => Equals(left, right); - public string GetString(IConnectionConfigurationValues settings) => _categoryId.ToString(CultureInfo.InvariantCulture); + public static bool operator !=(CategoryId left, CategoryId right) => !Equals(left, right); } } diff --git a/src/Nest/CommonAbstractions/Infer/DocumentPath/DocumentPath.cs b/src/Nest/CommonAbstractions/Infer/DocumentPath/DocumentPath.cs index 50ce7ff37d0..cf49fdb5c86 100644 --- a/src/Nest/CommonAbstractions/Infer/DocumentPath/DocumentPath.cs +++ b/src/Nest/CommonAbstractions/Infer/DocumentPath/DocumentPath.cs @@ -9,7 +9,7 @@ public interface IDocumentPath TypeName Type { get; set; } } - public class DocumentPath : IDocumentPath where T : class + public class DocumentPath : IEquatable>, IDocumentPath where T : class { internal IDocumentPath Self => this; internal T Document { get; set; } @@ -28,10 +28,10 @@ public DocumentPath(Id id) public static DocumentPath Id(Id id) => new DocumentPath(id); public static DocumentPath Id(T @object) => new DocumentPath(@object); - public static implicit operator DocumentPath(T @object) => new DocumentPath(@object); - public static implicit operator DocumentPath(Id id) => new DocumentPath(id); + public static implicit operator DocumentPath(T @object) => @object == null ? null : new DocumentPath(@object); + public static implicit operator DocumentPath(Id id) => id == null ? null : new DocumentPath(id); public static implicit operator DocumentPath(long id) => new DocumentPath(id); - public static implicit operator DocumentPath(string id) => new DocumentPath(id); + public static implicit operator DocumentPath(string id) => id.IsNullOrEmpty() ? null : new DocumentPath(id); public static implicit operator DocumentPath(Guid id) => new DocumentPath(id); public DocumentPath Index(IndexName index) @@ -46,5 +46,36 @@ public DocumentPath Type(TypeName type) Self.Type = type; return this; } + + public override int GetHashCode() + { + unchecked + { + var hashCode = Self.Type?.GetHashCode() ?? 0; + hashCode = (hashCode * 397) ^ (Self.Index?.GetHashCode() ?? 0); + hashCode = (hashCode * 397) ^ (Self.Id?.GetHashCode() ?? 0); + return hashCode; + } + } + + public bool Equals(DocumentPath other) + { + IDocumentPath o = other, s = Self; + return s.Index.NullOrEquals(o.Index) && s.Type.NullOrEquals(o.Type) && s.Id.NullOrEquals(o.Id) + && (this.Document?.Equals(other.Document) ?? true); + } + + public override bool Equals(object obj) + { + switch (obj) + { + case DocumentPath d: return this.Equals(d); + default: return false; + } + } + + public static bool operator ==(DocumentPath x, DocumentPath y) => Equals(x, y); + + public static bool operator !=(DocumentPath x, DocumentPath y)=> !Equals(x, y); } } diff --git a/src/Nest/CommonAbstractions/Infer/Field/Field.cs b/src/Nest/CommonAbstractions/Infer/Field/Field.cs index cc2470d8951..a2e1715dc8c 100644 --- a/src/Nest/CommonAbstractions/Infer/Field/Field.cs +++ b/src/Nest/CommonAbstractions/Infer/Field/Field.cs @@ -50,19 +50,16 @@ public Field(string name, double? boost = null) public Field(Expression expression, double? boost = null) { - if (expression == null) throw new ArgumentNullException(nameof(expression)); - Expression = expression; + Expression = expression ?? throw new ArgumentNullException(nameof(expression)); Boost = boost; - Type type; - _comparisonValue = expression.ComparisonValueFromExpression(out type); + _comparisonValue = expression.ComparisonValueFromExpression(out var type); _type = type; CachableExpression = !new HasVariableExpressionVisitor(expression).Found; } public Field(PropertyInfo property, double? boost = null) { - if (property == null) throw new ArgumentNullException(nameof(property)); - Property = property; + Property = property ?? throw new ArgumentNullException(nameof(property)); Boost = boost; _comparisonValue = property; _type = property.DeclaringType; @@ -74,26 +71,17 @@ private static string ParseFieldName(string name, out double? boost) if (name == null) return null; var parts = name.Split(new [] { '^' }, StringSplitOptions.RemoveEmptyEntries); - if (parts.Length <= 1) return name.Trim(); + if (parts.Length <= 1) return name; name = parts[0]; boost = double.Parse(parts[1], CultureInfo.InvariantCulture); - return name.Trim(); + return name; } - public static implicit operator Field(string name) - { - return name.IsNullOrEmpty() ? null : new Field(name); - } + public static implicit operator Field(string name) => name.IsNullOrEmpty() ? null : new Field(name); - public static implicit operator Field(Expression expression) - { - return expression == null ? null : new Field(expression); - } + public static implicit operator Field(Expression expression) => expression == null ? null : new Field(expression); - public static implicit operator Field(PropertyInfo property) - { - return property == null ? null : new Field(property); - } + public static implicit operator Field(PropertyInfo property) => property == null ? null : new Field(property); public override int GetHashCode() { @@ -114,27 +102,23 @@ public bool Equals(Field other) public override bool Equals(object obj) { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != GetType()) return false; - return this.Equals(obj as Field); + switch (obj) + { + case string s: return this.Equals(s); + case PropertyInfo p: return this.Equals(p); + case Field f: return this.Equals(f); + default: return false; + } } - public static bool operator ==(Field x, Field y) - { - return Equals(x, y); - } + public static bool operator ==(Field x, Field y) => Equals(x, y); - public static bool operator !=(Field x, Field y) - { - return !(x == y); - } + public static bool operator !=(Field x, Field y)=> !Equals(x, y); string IUrlParameter.GetString(IConnectionConfigurationValues settings) { - var nestSettings = settings as IConnectionSettingsValues; - if (nestSettings == null) - throw new Exception("Tried to pass field name on querystring but it could not be resolved because no nest settings are available"); + if (!(settings is IConnectionSettingsValues nestSettings)) + throw new ArgumentNullException(nameof(settings), $"Can not resolve {nameof(Field)} if no {nameof(IConnectionSettingsValues)} is provided"); return nestSettings.Inferrer.Field(this); } diff --git a/src/Nest/CommonAbstractions/Infer/Fields/Fields.cs b/src/Nest/CommonAbstractions/Infer/Fields/Fields.cs index 6f593bead45..e25d80bdccd 100644 --- a/src/Nest/CommonAbstractions/Infer/Fields/Fields.cs +++ b/src/Nest/CommonAbstractions/Infer/Fields/Fields.cs @@ -11,32 +11,40 @@ namespace Nest { [ContractJsonConverter(typeof(FieldsJsonConverter))] [DebuggerDisplay("{DebugDisplay,nq}")] - public class Fields : IUrlParameter, IEnumerable + public class Fields : IUrlParameter, IEnumerable, IEquatable { internal readonly List ListOfFields; - string IUrlParameter.GetString(IConnectionConfigurationValues settings) => - string.Join(",", ListOfFields.Select(f => ((IUrlParameter)f).GetString(settings))); + string IUrlParameter.GetString(IConnectionConfigurationValues settings) + { + if (!(settings is IConnectionSettingsValues nestSettings)) + throw new ArgumentNullException(nameof(settings), $"Can not resolve {nameof(Fields)} if no {nameof(IConnectionSettingsValues)} is provided"); - private string DebugDisplay => - $"Count: {ListOfFields.Count} [" + string.Join(",", ListOfFields.Select((t, i) => $"({i + 1}: {t.DebugDisplay})")) + "]"; + return string.Join(",", ListOfFields.Where(f => f != null).Select(f => ((IUrlParameter)f).GetString(nestSettings))); + } + private string DebugDisplay => + $"Count: {ListOfFields.Count} [" + string.Join(",", ListOfFields.Select((t, i) => $"({i + 1}: {t?.DebugDisplay ?? "NULL"})")) + "]"; internal Fields() { this.ListOfFields = new List(); } internal Fields(IEnumerable fieldNames) { this.ListOfFields = fieldNames.ToList(); } - public static implicit operator Fields(string[] fields) => new Fields(fields.Select(f => (Field)f)); + public static implicit operator Fields(string[] fields) => fields.IsEmpty() ? null : new Fields(fields.Select(f => (Field)f)); + + public static implicit operator Fields(string field) => field.IsNullOrEmptyCommaSeparatedList(out var split) + ? null : new Fields(split.Select(f=>(Field)f)); + + public static implicit operator Fields(Expression[] fields) => fields.IsEmpty() ? null : new Fields(fields.Select(f => (Field)f)); - public static implicit operator Fields(string field) => - new Fields(field.Split(new [] {','}, StringSplitOptions.RemoveEmptyEntries).Select(f=>(Field)f)); + public static implicit operator Fields(Expression field) => field == null ? null : new Fields(new [] { (Field)field }); - public static implicit operator Fields(Expression[] fields) => new Fields(fields.Select(f => (Field)f)); + public static implicit operator Fields(Field field) => field == null ? null : new Fields(new[] { field }); - public static implicit operator Fields(Expression field) => new Fields(new [] { (Field)field }); + public static implicit operator Fields(PropertyInfo field) => field == null ? null : new Fields(new Field[] { field }); - public static implicit operator Fields(Field field) => new Fields(new[] { field }); + public static implicit operator Fields(PropertyInfo[] fields) => fields.IsEmpty() ? null : new Fields(fields.Select(f=>(Field)f)); - public static implicit operator Fields(Field[] fields) => new Fields(fields); + public static implicit operator Fields(Field[] fields) => fields.IsEmpty() ? null : new Fields(fields); public Fields And(Expression> field, double? boost = null) where T : class { @@ -80,14 +88,38 @@ public Fields And(params Field[] fields) return this; } - public IEnumerator GetEnumerator() + public IEnumerator GetEnumerator() => this.ListOfFields.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); + + public static bool operator ==(Fields left, Fields right) => Equals(left, right); + + public static bool operator !=(Fields left, Fields right) => !Equals(left, right); + + public bool Equals(Fields other) => EqualsAllFields(this.ListOfFields, other.ListOfFields); + + public override bool Equals(object obj) { - return this.ListOfFields.GetEnumerator(); + switch (obj) + { + case Fields f: return Equals(f); + case string s: return Equals(s); + case Field fn: return Equals(fn); + case Field[] fns: return Equals(fns); + case Expression e: return Equals(e); + case Expression[] es: return Equals(es); + default: return false; + } } - IEnumerator IEnumerable.GetEnumerator() + private static bool EqualsAllFields(IReadOnlyList thisTypes, IReadOnlyList otherTypes) { - return this.GetEnumerator(); + if (thisTypes == null && otherTypes == null) return true; + if (thisTypes == null || otherTypes == null) return false; + if (thisTypes.Count != otherTypes.Count) return false; + return thisTypes.Count == otherTypes.Count && !thisTypes.Except(otherTypes).Any(); } + + public override int GetHashCode() => this.ListOfFields.GetHashCode(); } } diff --git a/src/Nest/CommonAbstractions/Infer/Id/Id.cs b/src/Nest/CommonAbstractions/Infer/Id/Id.cs index 71d719dad91..52e0577b054 100644 --- a/src/Nest/CommonAbstractions/Infer/Id/Id.cs +++ b/src/Nest/CommonAbstractions/Infer/Id/Id.cs @@ -1,5 +1,6 @@ using System; using System.Diagnostics; +using System.Globalization; using Elasticsearch.Net; using Newtonsoft.Json; @@ -9,20 +10,23 @@ namespace Nest [DebuggerDisplay("{DebugDisplay,nq}")] public class Id : IEquatable, IUrlParameter { - internal object Value { get; set; } + internal string StringValue { get; } + internal long? LongValue { get; } + internal string StringOrLongValue => this.StringValue ?? this.LongValue?.ToString(CultureInfo.InvariantCulture); internal object Document { get; } + internal int Tag { get; } - public Id(string id) { Value = id; } - public Id(long id) { Value = id; } - public Id(object document) { Document = document; } + public Id(string id) { Tag = 0; StringValue = id; } + public Id(long id) { Tag = 1; LongValue = id; } + public Id(object document) { Tag = 2; Document = document; } - public static implicit operator Id(string id) => new Id(id); + public static implicit operator Id(string id) => id.IsNullOrEmpty() ? null : new Id(id); public static implicit operator Id(long id) => new Id(id); public static implicit operator Id(Guid id) => new Id(id.ToString("D")); public static Id From(T document) where T : class => new Id(document); - private string DebugDisplay => Value?.ToString() ?? "Id from instance typeof: " + Document?.GetType().Name; + private string DebugDisplay => StringOrLongValue ?? "Id from instance typeof: " + Document?.GetType().Name; string IUrlParameter.GetString(IConnectionConfigurationValues settings) { @@ -30,47 +34,52 @@ string IUrlParameter.GetString(IConnectionConfigurationValues settings) return GetString(nestSettings); } - private string GetString(IConnectionSettingsValues nestSettings) - { - if (this.Document != null) - { - Value = nestSettings.Inferrer.Id(this.Document); - } - - var s = Value as string; - return s ?? this.Value?.ToString(); - } + private string GetString(IConnectionSettingsValues nestSettings) => + this.Document != null ? nestSettings.Inferrer.Id(this.Document) : this.StringOrLongValue; public bool Equals(Id other) { - if (ReferenceEquals(null, other)) return false; - if (ReferenceEquals(this, other)) return true; - return Equals(Value, other.Value) && Equals(Document, other.Document); + if (this.Tag + other.Tag == 1) + return this.StringOrLongValue == other.StringOrLongValue; + else if (this.Tag != other.Tag) return false; + switch (this.Tag) + { + case 0: + case 1: + return this.StringOrLongValue == other.StringOrLongValue; + default: + return this.Document?.Equals(other.Document) ?? false; + } } public override bool Equals(object obj) { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - return obj.GetType() == this.GetType() && Equals((Id)obj); + switch (obj) + { + case Id r: return Equals(r); + case string s: return Equals(s); + case int l: return Equals(l); + case long l: return Equals(l); + case Guid g: return Equals(g); + } + return Equals(new Id(obj)); } + private static int TypeHashCode { get; } = typeof(Id).GetHashCode(); public override int GetHashCode() { unchecked { - return ((Value?.GetHashCode() ?? 0) * 397) ^ (Document?.GetHashCode() ?? 0); + var result = TypeHashCode; + result = (result * 397) ^ (this.StringValue?.GetHashCode() ?? 0); + result = (result * 397) ^ (this.LongValue?.GetHashCode() ?? 0); + result = (result * 397) ^ (this.Document?.GetHashCode() ?? 0); + return result; } } - public static bool operator ==(Id left, Id right) - { - return Equals(left, right); - } + public static bool operator ==(Id left, Id right) => Equals(left, right); - public static bool operator !=(Id left, Id right) - { - return !Equals(left, right); - } + public static bool operator !=(Id left, Id right) => !Equals(left, right); } } diff --git a/src/Nest/CommonAbstractions/Infer/Id/IdExtensions.cs b/src/Nest/CommonAbstractions/Infer/Id/IdExtensions.cs index ab005605cdc..70853750430 100644 --- a/src/Nest/CommonAbstractions/Infer/Id/IdExtensions.cs +++ b/src/Nest/CommonAbstractions/Infer/Id/IdExtensions.cs @@ -9,7 +9,7 @@ internal static class IdExtensions { internal static bool IsConditionless(this Id id) { - return id == null || (id.Value == null && id.Document == null); + return id == null || (id.StringOrLongValue == null && id.Document == null); } } } diff --git a/src/Nest/CommonAbstractions/Infer/Id/IdJsonConverter.cs b/src/Nest/CommonAbstractions/Infer/Id/IdJsonConverter.cs index db461804935..7ef938694ac 100644 --- a/src/Nest/CommonAbstractions/Infer/Id/IdJsonConverter.cs +++ b/src/Nest/CommonAbstractions/Infer/Id/IdJsonConverter.cs @@ -30,7 +30,8 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s var documentId = settings.Inferrer.Id(id.Document.GetType(), id.Document); writer.WriteValue(documentId); } - else writer.WriteValue(id.Value); + else if (id.LongValue != null) writer.WriteValue(id.LongValue); + else writer.WriteValue(id.StringValue); } } } diff --git a/src/Nest/CommonAbstractions/Infer/IndexName/IndexName.cs b/src/Nest/CommonAbstractions/Infer/IndexName/IndexName.cs index 852656cca7f..adc0a93506e 100644 --- a/src/Nest/CommonAbstractions/Infer/IndexName/IndexName.cs +++ b/src/Nest/CommonAbstractions/Infer/IndexName/IndexName.cs @@ -19,24 +19,25 @@ public class IndexName : IEquatable, IUrlParameter private IndexName(string index, string cluster = null) { - this.Name = index?.Trim(); - this.Cluster = cluster?.Trim(); + this.Name = index; + this.Cluster = cluster; } private IndexName(Type type, string cluster = null) { this.Type = type; - this.Cluster = cluster?.Trim(); + this.Cluster = cluster; } private IndexName(string index, Type type, string cluster = null) { this.Name = index; this.Type = type; - this.Cluster = cluster?.Trim(); + this.Cluster = cluster; } public static IndexName From() => typeof(T); public static IndexName From(string clusterName) => From(typeof(T), clusterName); private static IndexName From(Type t, string clusterName) => new IndexName(t, clusterName); + // TODO private? public static IndexName Rebuild(string index, Type t, string clusterName = null) => new IndexName(index, t, clusterName); public Indices And() => new Indices(new[] { this, typeof(T) }); @@ -57,13 +58,7 @@ private static IndexName Parse(string indexName) bool IEquatable.Equals(IndexName other) => EqualsMarker(other); - public override bool Equals(object obj) - { - var s = obj as string; - if (!s.IsNullOrEmpty()) return this.EqualsString(s); - var pp = obj as IndexName; - return EqualsMarker(pp); - } + public override bool Equals(object obj) => obj is string s ? this.EqualsString(s) : obj is IndexName i && EqualsMarker(i); public override int GetHashCode() { @@ -76,6 +71,10 @@ public override int GetHashCode() } } + public static bool operator ==(IndexName left, IndexName right) => Equals(left, right); + + public static bool operator !=(IndexName left, IndexName right) => !Equals(left, right); + public override string ToString() { if (!this.Name.IsNullOrEmpty()) @@ -85,10 +84,7 @@ public override string ToString() private string PrefixClusterName(string name) => PrefixClusterName(this, name); private static string PrefixClusterName(IndexName i, string name) => i.Cluster.IsNullOrEmpty() ? name : $"{i.Cluster}:{name}"; - private bool EqualsString(string other) - { - return !other.IsNullOrEmpty() && other == PrefixClusterName(this.Name); - } + private bool EqualsString(string other) => !other.IsNullOrEmpty() && other == PrefixClusterName(this.Name); private bool EqualsMarker(IndexName other) { diff --git a/src/Nest/CommonAbstractions/Infer/Indices/Indices.cs b/src/Nest/CommonAbstractions/Infer/Indices/Indices.cs index b399d31c1ff..f893aaf4aab 100644 --- a/src/Nest/CommonAbstractions/Infer/Indices/Indices.cs +++ b/src/Nest/CommonAbstractions/Infer/Indices/Indices.cs @@ -50,18 +50,16 @@ internal Indices(IEnumerable indices) : base(new ManyIndices(indices) public static Indices Parse(string indicesString) { - if (indicesString.IsNullOrEmpty()) throw new Exception("can not parse an empty string to Indices"); - var indices = indicesString.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries); - if (indices.Contains("_all")) return Indices.All; - return Index(indices.Select(i => (IndexName)i)); + if (indicesString.IsNullOrEmptyCommaSeparatedList(out var indices)) return null; + return indices.Contains("_all") ? All : Index(indices.Select(i => (IndexName)i)); } public static implicit operator Indices(string indicesString) => Parse(indicesString); - public static implicit operator Indices(ManyIndices many) => new Indices(many); - public static implicit operator Indices(string[] many) => new ManyIndices(many); - public static implicit operator Indices(IndexName[] many) => new ManyIndices(many); - public static implicit operator Indices(IndexName index) => new ManyIndices(new[] { index }); - public static implicit operator Indices(Type type) => new ManyIndices(new IndexName[] { type }); + public static implicit operator Indices(ManyIndices many) => many == null ? null : new Indices(many); + public static implicit operator Indices(string[] many) => many.IsEmpty() ? null : new ManyIndices(many); + public static implicit operator Indices(IndexName[] many) => many.IsEmpty()? null : new ManyIndices(many); + 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 }); private string DebugDisplay => this.Match( all => "_all", diff --git a/src/Nest/CommonAbstractions/Infer/JoinFieldRouting/Routing.cs b/src/Nest/CommonAbstractions/Infer/JoinFieldRouting/Routing.cs index 8c04983dc1f..b3104b698e1 100644 --- a/src/Nest/CommonAbstractions/Infer/JoinFieldRouting/Routing.cs +++ b/src/Nest/CommonAbstractions/Infer/JoinFieldRouting/Routing.cs @@ -1,5 +1,7 @@ using System; using System.Diagnostics; +using System.Globalization; +using System.Linq; using Elasticsearch.Net; using Newtonsoft.Json; @@ -9,24 +11,48 @@ namespace Nest [DebuggerDisplay("{DebugDisplay,nq}")] public class Routing : IEquatable, IUrlParameter { - internal object Value { get; set; } + internal string StringValue { get; } + internal long? LongValue { get; } + internal string StringOrLongValue => this.StringValue ?? this.LongValue?.ToString(CultureInfo.InvariantCulture); + internal object Document { get; } internal Func DocumentGetter { get; } - internal Routing(Func documentGetter) { DocumentGetter = documentGetter; } - public Routing(string routing) { Value = routing; } - public Routing(long routing) { Value = routing; } - public Routing(object document) { Document = document; } + internal int Tag { get; } + + internal Routing(Func documentGetter) + { + Tag = 0; + DocumentGetter = documentGetter; + } + + public Routing(string routing) + { + Tag = 1; + StringValue = routing; + } - public static implicit operator Routing(string routing) => new Routing(routing); - public static implicit operator Routing(string[] routing) => new Routing(string.Join(",", routing)); + public Routing(long routing) + { + Tag = 2; + LongValue = routing; + } + + public Routing(object document) + { + Tag = 4; + Document = document; + } + + public static implicit operator Routing(string routing) => routing.IsNullOrEmptyCommaSeparatedList(out _) ? null : new Routing(routing); + public static implicit operator Routing(string[] routing) => routing.IsEmpty() ? null : new Routing(string.Join(",", routing)); public static implicit operator Routing(long routing) => new Routing(routing); public static implicit operator Routing(Guid routing) => new Routing(routing.ToString("D")); /// Use the inferred routing from public static Routing From(T document) where T : class => new Routing(document); - private string DebugDisplay => Value?.ToString() ?? "Routing from instance typeof: " + Document?.GetType().Name; + private string DebugDisplay => this.StringOrLongValue ?? "Routing from instance typeof: " + Document?.GetType().Name; string IUrlParameter.GetString(IConnectionConfigurationValues settings) { @@ -36,48 +62,85 @@ string IUrlParameter.GetString(IConnectionConfigurationValues settings) private string GetString(IConnectionSettingsValues nestSettings) { + string value = null; if (this.DocumentGetter != null) { var doc = this.DocumentGetter(); - Value = nestSettings.Inferrer.Routing(doc); + value = nestSettings.Inferrer.Routing(doc); } else if (this.Document != null) - Value = nestSettings.Inferrer.Routing(this.Document); + value = nestSettings.Inferrer.Routing(this.Document); - var s = Value as string; - return s ?? this.Value?.ToString(); + return value ?? this.StringOrLongValue; } + public static bool operator ==(Routing left, Routing right) => Equals(left, right); + + public static bool operator !=(Routing left, Routing right) => !Equals(left, right); + public bool Equals(Routing other) { - if (ReferenceEquals(null, other)) return false; - if (ReferenceEquals(this, other)) return true; - return Equals(Value, other.Value) && Equals(Document, other.Document); + if (this.Tag == other.Tag) + { + switch (this.Tag) + { + case 0: + var t = this.DocumentGetter(); + var o = other.DocumentGetter(); + return t?.Equals(o) ?? false; + case 4: return this.Document?.Equals(other.Document) ?? false; + default: + return StringEquals(this.StringOrLongValue, other.StringOrLongValue); + } + } + else if (this.Tag + other.Tag == 3) + return StringEquals(this.StringOrLongValue, other.StringOrLongValue); + else + return false; } - public override bool Equals(object obj) + private static readonly char[] Separator = {','}; + + private static bool StringEquals(string left, string right) { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - return obj.GetType() == this.GetType() && Equals((Routing)obj); + if (left == null && right == null) return true; + else if (left == null || right == null) + return false; + if (!left.Contains(",") || !right.Contains(",")) return left == right; + + var l1 = left.Split(Separator, StringSplitOptions.RemoveEmptyEntries).Select(v=>v.Trim()).ToList(); + var l2 = right.Split(Separator, StringSplitOptions.RemoveEmptyEntries).Select(v=>v.Trim()).ToList(); + if (l1.Count != l2.Count) return false; + return l1.Count == l2.Count && !l1.Except(l2).Any(); + } - public override int GetHashCode() + public override bool Equals(object obj) { - unchecked + switch (obj) { - return ((Value?.GetHashCode() ?? 0) * 397) ^ (Document?.GetHashCode() ?? 0); + case Routing r: return Equals(r); + case string s: return Equals(s); + case int l: return Equals(l); + case long l: return Equals(l); + case Guid g: return Equals(g); } - } - public static bool operator ==(Routing left, Routing right) - { - return Equals(left, right); + return Equals(new Routing(obj)); } - public static bool operator !=(Routing left, Routing right) + private static int TypeHashCode { get; } = typeof(Routing).GetHashCode(); + public override int GetHashCode() { - return !Equals(left, right); + unchecked + { + var result = TypeHashCode; + result = (result * 397) ^ (this.StringValue?.GetHashCode() ?? 0); + result = (result * 397) ^ (this.LongValue?.GetHashCode() ?? 0); + result = (result * 397) ^ (this.DocumentGetter?.GetHashCode() ?? 0); + result = (result * 397) ^ (this.Document?.GetHashCode() ?? 0); + return result; + } } } } diff --git a/src/Nest/CommonAbstractions/Infer/JoinFieldRouting/RoutingJsonConverter.cs b/src/Nest/CommonAbstractions/Infer/JoinFieldRouting/RoutingJsonConverter.cs index 3d710587669..63d4b76ad4c 100644 --- a/src/Nest/CommonAbstractions/Infer/JoinFieldRouting/RoutingJsonConverter.cs +++ b/src/Nest/CommonAbstractions/Infer/JoinFieldRouting/RoutingJsonConverter.cs @@ -23,14 +23,22 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s return; } - var id = (Routing)value; - if (id.Document != null) + var routing = (Routing)value; + if (routing.Document != null) { var settings = serializer.GetConnectionSettings(); - var documentId = settings.Inferrer.Routing(id.Document.GetType(), id.Document); + var documentId = settings.Inferrer.Routing(routing.Document.GetType(), routing.Document); writer.WriteValue(documentId); } - else writer.WriteValue(id.Value); + else if (routing.DocumentGetter != null) + { + var settings = serializer.GetConnectionSettings(); + var doc = routing.DocumentGetter(); + var documentId = settings.Inferrer.Routing(doc.GetType(), doc); + writer.WriteValue(documentId); + } + else if (routing.LongValue != null) writer.WriteValue(routing.LongValue); + else writer.WriteValue(routing.StringValue); } } } diff --git a/src/Nest/CommonAbstractions/Infer/JoinFieldRouting/RoutingResolver.cs b/src/Nest/CommonAbstractions/Infer/JoinFieldRouting/RoutingResolver.cs index 3106d5d6a1d..1008f2816b3 100644 --- a/src/Nest/CommonAbstractions/Infer/JoinFieldRouting/RoutingResolver.cs +++ b/src/Nest/CommonAbstractions/Infer/JoinFieldRouting/RoutingResolver.cs @@ -62,13 +62,8 @@ private bool TryConnectionSettingsRoute(Type type, object @object, out string ro return true; } - private string ResolveId(Id id, IConnectionSettingsValues nestSettings) - { - if (id.Document != null) return nestSettings.Inferrer.Id(id.Document); - - var s = id.Value as string; - return s ?? id.Value?.ToString(); - } + private string ResolveId(Id id, IConnectionSettingsValues nestSettings) => + id.Document != null ? nestSettings.Inferrer.Id(id.Document) : id.StringOrLongValue; private static JoinField GetJoinFieldFromObject(Type type, object @object) { diff --git a/src/Nest/CommonAbstractions/Infer/Metrics/IndexMetrics.cs b/src/Nest/CommonAbstractions/Infer/Metrics/IndexMetrics.cs index 3d4dc0262d6..240b15e6ece 100644 --- a/src/Nest/CommonAbstractions/Infer/Metrics/IndexMetrics.cs +++ b/src/Nest/CommonAbstractions/Infer/Metrics/IndexMetrics.cs @@ -3,13 +3,25 @@ namespace Nest { - public class IndexMetrics : IUrlParameter + public class IndexMetrics : IEquatable, IUrlParameter { private readonly NodesStatsIndexMetric _enumValue; + internal Enum Value => _enumValue; public string GetString(IConnectionConfigurationValues settings) => this._enumValue.GetStringValue(); internal IndexMetrics(NodesStatsIndexMetric metric) { _enumValue = metric; } public static implicit operator IndexMetrics(NodesStatsIndexMetric metric) => new IndexMetrics(metric); + + public bool Equals(Enum other) => this.Value.Equals(other); + public bool Equals(IndexMetrics other) => this.Value.Equals(other.Value); + + public override bool Equals(object obj) => obj is Enum e ? Equals(e) : obj is IndexMetrics m && Equals(m.Value); + + public override int GetHashCode() => (_enumValue.GetHashCode()); + + public static bool operator ==(IndexMetrics left, IndexMetrics right) => Equals(left, right); + + public static bool operator !=(IndexMetrics left, IndexMetrics right) => !Equals(left, right); } } diff --git a/src/Nest/CommonAbstractions/Infer/Metrics/Metrics.cs b/src/Nest/CommonAbstractions/Infer/Metrics/Metrics.cs index 87874b4b8ec..458f720e23f 100644 --- a/src/Nest/CommonAbstractions/Infer/Metrics/Metrics.cs +++ b/src/Nest/CommonAbstractions/Infer/Metrics/Metrics.cs @@ -3,9 +3,10 @@ namespace Nest { - public class Metrics : IUrlParameter + public class Metrics : IEquatable, IUrlParameter { private readonly Enum _enumValue; + internal Enum Value => _enumValue; public string GetString(IConnectionConfigurationValues settings) => this._enumValue.GetStringValue(); internal Metrics(IndicesStatsMetric metric) { _enumValue = metric; } @@ -21,5 +22,16 @@ public class Metrics : IUrlParameter public static implicit operator Metrics(ClusterStateMetric metric) => new Metrics(metric); public static implicit operator Metrics(WatcherStatsMetric metric) => new Metrics(metric); public static implicit operator Metrics(NodesUsageMetric metric) => new Metrics(metric); + + public bool Equals(Enum other) => this.Value.Equals(other); + public bool Equals(Metrics other) => this.Value.Equals(other.Value); + + public override bool Equals(object obj) => obj is Enum e ? Equals(e) : obj is Metrics m && Equals(m.Value); + + public override int GetHashCode() => (_enumValue != null ? _enumValue.GetHashCode() : 0); + + public static bool operator ==(Metrics left, Metrics right) => Equals(left, right); + + public static bool operator !=(Metrics left, Metrics right) => !Equals(left, right); } } diff --git a/src/Nest/CommonAbstractions/Infer/Name/Name.cs b/src/Nest/CommonAbstractions/Infer/Name/Name.cs index 435e7853d8a..5d9bd54915d 100644 --- a/src/Nest/CommonAbstractions/Infer/Name/Name.cs +++ b/src/Nest/CommonAbstractions/Infer/Name/Name.cs @@ -1,18 +1,42 @@ -using System.Diagnostics; +using System; +using System.Diagnostics; using Elasticsearch.Net; namespace Nest { [DebuggerDisplay("{DebugDisplay,nq}")] - public class Name : IUrlParameter + public class Name : IEquatable, IUrlParameter { private readonly string _name; - public Name(string name) { this._name = name; } + internal string Value => _name; + private string DebugDisplay => _name; + + public Name(string name) => this._name = name?.Trim(); string IUrlParameter.GetString(IConnectionConfigurationValues settings) => _name; - private string DebugDisplay => _name; + public static implicit operator Name(string name) => name.IsNullOrEmpty() ? null : new Name(name); + + public static bool operator ==(Name left, Name right) => Equals(left, right); + + public static bool operator !=(Name left, Name right) => !Equals(left, right); + + public bool Equals(Name other) => EqualsString(other?.Value); + + public override bool Equals(object obj) => + obj is string s ? this.EqualsString(s) : (obj is Name i) && this.EqualsString(i.Value); + + private bool EqualsString(string other) => !other.IsNullOrEmpty() && other.Trim() == this.Value; - public static implicit operator Name(string name) => new Name(name); + private static int TypeHashCode { get; } = typeof(Name).GetHashCode(); + public override int GetHashCode() + { + unchecked + { + var result = TypeHashCode; + result = (result * 397) ^ (this.Value?.GetHashCode() ?? 0); + return result; + } + } } } diff --git a/src/Nest/CommonAbstractions/Infer/Name/Names.cs b/src/Nest/CommonAbstractions/Infer/Name/Names.cs index 2ff39304d4c..b8b57032a8f 100644 --- a/src/Nest/CommonAbstractions/Infer/Name/Names.cs +++ b/src/Nest/CommonAbstractions/Infer/Name/Names.cs @@ -7,32 +7,49 @@ namespace Nest { [DebuggerDisplay("{DebugDisplay,nq}")] - public class Names : IUrlParameter + public class Names : IEquatable, IUrlParameter { - private readonly IEnumerable _names; + private readonly IList _names; + internal IList Value => _names; - public Names(IEnumerable names) - { - if (!names.HasAny()) throw new ArgumentException("can not create Names on an empty enumerable of string", nameof(names)); - this._names = names.Select(n => (Name)n); - } + public Names(IEnumerable names) : this(names?.Select(n=>(Name)n).ToList()) { } - public Names(IEnumerable names) { this._names = names; } - - public static Names Parse(string names) + public Names(IEnumerable names) { - if (names.IsNullOrEmpty()) throw new ArgumentException("can not create Names on an empty enumerable of string", nameof(names)); - var nameList = names.Split(new [] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(s=>s.Trim()); - return new Names(nameList); + this._names = names?.ToList(); + if (!this._names.HasAny()) + throw new ArgumentException($"can not create {nameof(Names)} on an empty enumerable of ", nameof(names)); } + public static Names Parse(string names) => names.IsNullOrEmptyCommaSeparatedList(out var list) ? null : new Names(list); + string IUrlParameter.GetString(IConnectionConfigurationValues settings) => string.Join(",", this._names.Cast().Select(n => n.GetString(settings))); private string DebugDisplay => ((IUrlParameter)this).GetString(null); - public static implicit operator Names(Name name) => new Names(new[] { name }); + public static implicit operator Names(Name name) => name == null ? null : new Names(new[] { name }); public static implicit operator Names(string names) => Parse(names); + + public static implicit operator Names(string[] names) => names.IsEmpty() ? null : new Names(names); + + public static bool operator ==(Names left, Names right) => Equals(left, right); + + public static bool operator !=(Names left, Names right) => !Equals(left, right); + + public bool Equals(Names other) => EqualsAllIds(this.Value, other.Value); + + private static bool EqualsAllIds(ICollection thisIds, ICollection otherIds) + { + if (thisIds == null && otherIds == null) return true; + if (thisIds == null || otherIds == null) return false; + if (thisIds.Count != otherIds.Count) return false; + return thisIds.Count == otherIds.Count && !thisIds.Except(otherIds).Any(); + } + + public override bool Equals(object obj) => obj is string s ? this.Equals(Parse(s)) : (obj is Names i) && this.Equals(i); + + public override int GetHashCode() => this._names.GetHashCode(); } } diff --git a/src/Nest/CommonAbstractions/Infer/NodeId/NodeIds.cs b/src/Nest/CommonAbstractions/Infer/NodeId/NodeIds.cs index 2a39c34beed..62649c870a7 100644 --- a/src/Nest/CommonAbstractions/Infer/NodeId/NodeIds.cs +++ b/src/Nest/CommonAbstractions/Infer/NodeId/NodeIds.cs @@ -7,23 +7,43 @@ namespace Nest { [DebuggerDisplay("{DebugDisplay,nq}")] - public class NodeIds : IUrlParameter + public class NodeIds : IEquatable, IUrlParameter { - private readonly IEnumerable _nodeIds; + private readonly IList _nodeIds; + internal IList Value => _nodeIds; - public NodeIds(IEnumerable nodeIds) { this._nodeIds = nodeIds; } + public NodeIds(IEnumerable nodeIds) + { + this._nodeIds = nodeIds?.ToList(); + if (!this._nodeIds.HasAny()) + throw new ArgumentException($"can not create {nameof(NodeIds )} on an empty enumerable of ", nameof(nodeIds)); + } private string DebugDisplay => ((IUrlParameter)this).GetString(null); string IUrlParameter.GetString(IConnectionConfigurationValues settings) => string.Join(",", this._nodeIds); - public static NodeIds Parse(string nodeIds) + public static NodeIds Parse(string nodeIds) => nodeIds.IsNullOrEmptyCommaSeparatedList(out var nodes) ? null : new NodeIds(nodes); + + public static implicit operator NodeIds(string nodes) => Parse(nodes); + public static implicit operator NodeIds(string[] nodes) => nodes.IsEmpty() ? null : new NodeIds(nodes); + + public static bool operator ==(NodeIds left, NodeIds right) => Equals(left, right); + + public static bool operator !=(NodeIds left, NodeIds right) => !Equals(left, right); + + public bool Equals(NodeIds other) => EqualsAllIds(this.Value, other.Value); + + private static bool EqualsAllIds(ICollection thisIds, ICollection otherIds) { - if (nodeIds.IsNullOrEmpty()) throw new ArgumentException("can not create NodeIds on an empty enumerable of ", nameof(nodeIds)); - var nodes = nodeIds.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(s=>s.Trim()); - return new NodeIds(nodes); + if (thisIds == null && otherIds == null) return true; + if (thisIds == null || otherIds == null) return false; + if (thisIds.Count != otherIds.Count) return false; + return thisIds.Count == otherIds.Count && !thisIds.Except(otherIds).Any(); } - public static implicit operator NodeIds(string nodes) => Parse(nodes); + public override bool Equals(object obj) => obj is string s ? this.Equals(Parse(s)) : (obj is NodeIds i) && this.Equals(i); + + public override int GetHashCode() => this._nodeIds.GetHashCode(); } } diff --git a/src/Nest/CommonAbstractions/Infer/PropertyName/PropertyName.cs b/src/Nest/CommonAbstractions/Infer/PropertyName/PropertyName.cs index 43a36862d14..1f4a7ef6ea3 100644 --- a/src/Nest/CommonAbstractions/Infer/PropertyName/PropertyName.cs +++ b/src/Nest/CommonAbstractions/Infer/PropertyName/PropertyName.cs @@ -46,7 +46,7 @@ public PropertyName(PropertyInfo property) _type = property.DeclaringType; } - public static implicit operator PropertyName(string name) => name == null ? null : new PropertyName(name); + public static implicit operator PropertyName(string name) => name.IsNullOrEmpty() ? null : new PropertyName(name); public static implicit operator PropertyName(Expression expression) => expression == null ? null : new PropertyName(expression); @@ -63,30 +63,30 @@ public override int GetHashCode() } } - public bool Equals(PropertyName other) + public bool Equals(PropertyName other) => EqualsMarker(other); + + public override bool Equals(object obj) => + obj is string s ? this.EqualsString(s) : (obj is PropertyName r) && this.EqualsMarker(r); + + private bool EqualsString(string other) => !other.IsNullOrEmpty() && other == this.Name; + + public bool EqualsMarker(PropertyName other) { return _type != null ? other != null && _type == other._type && _comparisonValue.Equals(other._comparisonValue) : other != null && _comparisonValue.Equals(other._comparisonValue); } - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != GetType()) return false; - return this.Equals(obj as PropertyName); - } - - public static bool operator ==(PropertyName x, PropertyName y) => Equals(x, y); + public static bool operator ==(PropertyName left, PropertyName right) => Equals(left, right); - public static bool operator !=(PropertyName x, PropertyName y) => !(x == y); + public static bool operator !=(PropertyName left, PropertyName right) => !Equals(left, right); string IUrlParameter.GetString(IConnectionConfigurationValues settings) { - var nestSettings = settings as IConnectionSettingsValues; + if (!(settings is IConnectionSettingsValues nestSettings)) + throw new ArgumentNullException(nameof(settings), $"Can not resolve {nameof(PropertyName)} if no {nameof(IConnectionSettingsValues)} is provided"); - return nestSettings?.Inferrer.PropertyName(this); + return nestSettings.Inferrer.PropertyName(this); } } } diff --git a/src/Nest/CommonAbstractions/Infer/RelationName/RelationName.cs b/src/Nest/CommonAbstractions/Infer/RelationName/RelationName.cs index a6d8a417b8c..90133c95fc5 100644 --- a/src/Nest/CommonAbstractions/Infer/RelationName/RelationName.cs +++ b/src/Nest/CommonAbstractions/Infer/RelationName/RelationName.cs @@ -9,34 +9,28 @@ namespace Nest [DebuggerDisplay("{DebugDisplay,nq}")] public class RelationName : IEquatable, IUrlParameter { - private static int TypeHashCode { get; } = typeof(RelationName).GetHashCode(); public string Name { get; } public Type Type { get; } - private RelationName(string type) - { - this.Name = type; - } - - private RelationName(Type type) - { - this.Type = type; - } + private RelationName(string type) => this.Name = type; + private RelationName(Type type) => this.Type = type; internal string DebugDisplay => Type == null ? Name : $"{nameof(RelationName)} for typeof: {Type?.Name}"; + public static RelationName From() => typeof(T); + public static RelationName Create(Type type) => GetRelationNameForType(type); public static RelationName Create() where T : class => GetRelationNameForType(typeof(T)); private static RelationName GetRelationNameForType(Type type) => new RelationName(type); - public static implicit operator RelationName(string typeName) => - typeName == null ? null : new RelationName(typeName); + public static implicit operator RelationName(string typeName) => typeName.IsNullOrEmpty() ? null : new RelationName(typeName); public static implicit operator RelationName(Type type) => type == null ? null : new RelationName(type); + private static int TypeHashCode { get; } = typeof(RelationName).GetHashCode(); public override int GetHashCode() { unchecked @@ -47,22 +41,14 @@ public override int GetHashCode() } } - bool IEquatable.Equals(RelationName other) => Equals(other); + public static bool operator ==(RelationName left, RelationName right) => Equals(left, right); - public override bool Equals(object obj) - { - var s = obj as string; - if (!s.IsNullOrEmpty()) return this.EqualsString(s); - if (obj is RelationName pp) return this.EqualsMarker(pp); - return base.Equals(obj); - } + public static bool operator !=(RelationName left, RelationName right) => !Equals(left, right); - public override string ToString() - { - if (!this.Name.IsNullOrEmpty()) - return this.Name; - return this.Type != null ? this.Type.Name : string.Empty; - } + public bool Equals(RelationName other) => EqualsMarker(other); + + public override bool Equals(object obj) => + obj is string s ? this.EqualsString(s) : (obj is RelationName r) && this.EqualsMarker(r); public bool EqualsMarker(RelationName other) { @@ -73,20 +59,21 @@ public bool EqualsMarker(RelationName other) return false; } - public bool EqualsString(string other) + private bool EqualsString(string other) => !other.IsNullOrEmpty() && other == this.Name; + + public override string ToString() { - return !other.IsNullOrEmpty() && other == this.Name; + if (!this.Name.IsNullOrEmpty()) return this.Name; + return this.Type != null ? this.Type.Name : string.Empty; } string IUrlParameter.GetString(IConnectionConfigurationValues settings) { - var nestSettings = settings as IConnectionSettingsValues; - if (nestSettings == null) - throw new Exception("Tried to pass type name on querystring but it could not be resolved because no nest settings are available"); + if (!(settings is IConnectionSettingsValues nestSettings)) + throw new ArgumentNullException(nameof(settings), $"Can not resolve {nameof(RelationName)} if no {nameof(IConnectionSettingsValues)} is provided"); return nestSettings.Inferrer.RelationName(this); } - public static RelationName From() => typeof(T); } } diff --git a/src/Nest/CommonAbstractions/Infer/TaskId/TaskId.cs b/src/Nest/CommonAbstractions/Infer/TaskId/TaskId.cs index a91a7a7f23d..80f52d4f409 100644 --- a/src/Nest/CommonAbstractions/Infer/TaskId/TaskId.cs +++ b/src/Nest/CommonAbstractions/Infer/TaskId/TaskId.cs @@ -10,7 +10,7 @@ public class TaskId : IUrlParameter, IEquatable { public string NodeId { get; } public long TaskNumber { get; } - public string FullyQualifiedId => $"{NodeId}:{TaskNumber.ToString(CultureInfo.InvariantCulture)}"; + public string FullyQualifiedId { get; } private string DebugDisplay => FullyQualifiedId; @@ -28,9 +28,11 @@ public TaskId(string taskId) throw new ArgumentException($"TaskId:{taskId} not in expected format of :", nameof(taskId)); this.NodeId = tokens[0]; - long t; - if (!long.TryParse(tokens[1], NumberStyles.Any, CultureInfo.InvariantCulture, out t) || t < -1 || t == 0) + this.FullyQualifiedId = taskId; + + if (!long.TryParse(tokens[1].Trim(), NumberStyles.Any, CultureInfo.InvariantCulture, out var t) || t < -1 || t == 0) throw new ArgumentException($"TaskId task component:{tokens[1]} could not be parsed to long or is out of range", nameof(taskId)); + this.TaskNumber = t; } @@ -38,22 +40,18 @@ public TaskId(string taskId) public string GetString(IConnectionConfigurationValues settings) => FullyQualifiedId; - public static implicit operator TaskId(string taskId) => new TaskId(taskId); + public static implicit operator TaskId(string taskId) => taskId.IsNullOrEmpty() ? null : new TaskId(taskId); - public bool Equals(TaskId other) - { - if (ReferenceEquals(null, other)) return false; - if (ReferenceEquals(this, other)) return true; - return string.Equals(NodeId, other.NodeId) && TaskNumber == other.TaskNumber; - } + public static bool operator ==(TaskId left, TaskId right) => Equals(left, right); - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) return false; - return Equals((TaskId) obj); - } + public static bool operator !=(TaskId left, TaskId right) => !Equals(left, right); + + public bool Equals(TaskId other) => EqualsString(other?.FullyQualifiedId); + + public override bool Equals(object obj) => + obj != null && obj is string s ? this.EqualsString(s) : (obj is TaskId i) && this.EqualsString(i.FullyQualifiedId); + + private bool EqualsString(string other) => !other.IsNullOrEmpty() && other == this.FullyQualifiedId; public override int GetHashCode() { @@ -62,9 +60,5 @@ public override int GetHashCode() return (NodeId.GetHashCode()*397) ^ TaskNumber.GetHashCode(); } } - - public static bool operator ==(TaskId left, TaskId right) => Equals(left, right); - - public static bool operator !=(TaskId left, TaskId right) => !Equals(left, right); } } diff --git a/src/Nest/CommonAbstractions/Infer/TypeName/TypeName.cs b/src/Nest/CommonAbstractions/Infer/TypeName/TypeName.cs index 7413fad440a..9fec2f045d8 100644 --- a/src/Nest/CommonAbstractions/Infer/TypeName/TypeName.cs +++ b/src/Nest/CommonAbstractions/Infer/TypeName/TypeName.cs @@ -14,14 +14,9 @@ public class TypeName : IEquatable, IUrlParameter public string Name { get; } public Type Type { get; } - private TypeName(string type) - { - this.Name = type; - } - private TypeName(Type type) - { - this.Type = type; - } + private TypeName(string type) => this.Name = type; + + private TypeName(Type type) => this.Type = type; internal string DebugDisplay => Type == null ? Name : $"{nameof(TypeName)} for typeof: {Type?.Name}"; @@ -31,7 +26,7 @@ private TypeName(Type type) private static TypeName GetTypeNameForType(Type type) => new TypeName(type); - public static implicit operator TypeName(string typeName) => typeName == null ? null : new TypeName(typeName); + public static implicit operator TypeName(string typeName) => typeName.IsNullOrEmpty() ? null : new TypeName(typeName); public static implicit operator TypeName(Type type) => type == null ? null : new TypeName(type); @@ -44,8 +39,11 @@ public override int GetHashCode() return result; } } + public static bool operator ==(TypeName left, TypeName right) => Equals(left, right); + + public static bool operator !=(TypeName left, TypeName right) => !Equals(left, right); - bool IEquatable.Equals(TypeName other) => Equals(other); + public bool Equals(TypeName other) => EqualsMarker(other); public override bool Equals(object obj) { @@ -78,9 +76,8 @@ private bool EqualsString(string other) string IUrlParameter.GetString(IConnectionConfigurationValues settings) { - var nestSettings = settings as IConnectionSettingsValues; - if (nestSettings == null) - throw new Exception("Tried to pass type name on querystring but it could not be resolved because no nest settings are available"); + if (!(settings is IConnectionSettingsValues nestSettings)) + throw new ArgumentNullException(nameof(settings), $"Can not resolve {nameof(TypeName)} if no {nameof(IConnectionSettingsValues)} is provided"); return nestSettings.Inferrer.TypeName(this); } diff --git a/src/Nest/CommonAbstractions/Infer/Types/Types.cs b/src/Nest/CommonAbstractions/Infer/Types/Types.cs index f18d79be311..b2e4a4ecd25 100644 --- a/src/Nest/CommonAbstractions/Infer/Types/Types.cs +++ b/src/Nest/CommonAbstractions/Infer/Types/Types.cs @@ -3,13 +3,12 @@ using System.Diagnostics; using System.Linq; using Elasticsearch.Net; -using Newtonsoft.Json; namespace Nest { [ContractJsonConverter(typeof(TypesJsonConverter))] [DebuggerDisplay("{DebugDisplay,nq}")] - public class Types : Union, IUrlParameter + public class Types : Union, IUrlParameter, IEquatable { public class AllTypesMarker { internal AllTypesMarker() { } } public static AllTypesMarker All { get; } = new AllTypesMarker(); @@ -48,50 +47,40 @@ internal Types(IEnumerable types) : base(new ManyTypes(types)) { } public static ManyTypes Type(IEnumerable indices) => new ManyTypes(indices); public static ManyTypes Type(params string[] indices) => new ManyTypes(indices); - - public static Types Parse(string typesString) - { - if (typesString.IsNullOrEmpty()) return Types.All; - var types = typesString.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries); - return Type(types.Select(i => (TypeName)i)); - } + public static Types Parse(string typesString) => typesString.IsNullOrEmptyCommaSeparatedList(out var types) ? null : Type(types.Select(i => (TypeName)i)); public static implicit operator Types(string typesString) => Parse(typesString); - public static implicit operator Types(AllTypesMarker all) => new Types(all); - public static implicit operator Types(ManyTypes many) => new Types(many); - public static implicit operator Types(TypeName type) => new ManyTypes(new[] { type }); - public static implicit operator Types(TypeName[] type) => new ManyTypes(type); - public static implicit operator Types(string[] many) => new ManyTypes(many); - public static implicit operator Types(Type type) => new ManyTypes(new TypeName[] { type }); + public static implicit operator Types(AllTypesMarker all) => all == null ? null : new Types(all); + public static implicit operator Types(ManyTypes many) => many == null ? null : new Types(many); + public static implicit operator Types(TypeName type) => type == null ? null : new ManyTypes(new[] { type }); + public static implicit operator Types(TypeName[] type) => type.IsEmpty() ? null : new ManyTypes(type); + public static implicit operator Types(string[] many) => many.IsEmpty() ? null : new ManyTypes(many); + public static implicit operator Types(Type type) => type == null ? null : new ManyTypes(new TypeName[] { type }); private string DebugDisplay => this.Match( all => "_all", types => $"Count: {types.Types.Count} [" + string.Join(",", types.Types.Select((t, i) => $"({i+1}: {t.DebugDisplay})")) + "]" ); - string IUrlParameter.GetString(IConnectionConfigurationValues settings) - { - return this.Match( - all => null, - many => - { - var nestSettings = settings as IConnectionSettingsValues; - if (nestSettings == null) - throw new Exception("Tried to pass field name on querystring but it could not be resolved because no nest settings are available"); - - var types = many.Types.Select(t => nestSettings.Inferrer.TypeName(t)).Distinct(); - return string.Join(",", types); - } - ); + string IUrlParameter.GetString(IConnectionConfigurationValues settings) => this.Match( + all => null, + many => + { + if (!(settings is IConnectionSettingsValues nestSettings)) + throw new ArgumentNullException(nameof(settings), $"Can not resolve Types if no {nameof(IConnectionSettingsValues)} is provided"); + + var types = many.Types.Select(t => nestSettings.Inferrer.TypeName(t)).Distinct(); + return string.Join(",", types); + } + ); - } public static bool operator ==(Types left, Types right) => Equals(left, right); public static bool operator !=(Types left, Types right) => !Equals(left, right); - public override bool Equals(object obj) + public bool Equals(Types other) { - if (!(obj is Types other)) return false; + if (other == null) return false; return this.Match( all => other.Match(a => true, m => false), many => other.Match( @@ -101,6 +90,15 @@ public override bool Equals(object obj) ); } + public override bool Equals(object obj) + { + Types other = null; + if (obj is Types t) other = t; + else if (obj is string s) other = s; + else if (obj is TypeName n) other = n; + return other != null && Equals(other); + } + private static bool EqualsAllTypes(IReadOnlyList thisTypes, IReadOnlyList otherTypes) { if (thisTypes == null && otherTypes == null) return true; diff --git a/src/Nest/Document/Single/Index/IndexRequest.cs b/src/Nest/Document/Single/Index/IndexRequest.cs index 8c72aa3cf7b..2a10eb19f2c 100644 --- a/src/Nest/Document/Single/Index/IndexRequest.cs +++ b/src/Nest/Document/Single/Index/IndexRequest.cs @@ -19,9 +19,10 @@ public partial class IndexRequest protected override HttpMethod HttpMethod => GetHttpMethod(this); - internal static HttpMethod GetHttpMethod(IIndexRequest request) => request.Id?.Value != null ? HttpMethod.PUT : HttpMethod.POST; + internal static HttpMethod GetHttpMethod(IIndexRequest request) => request.Id.IsConditionless() ? HttpMethod.POST : HttpMethod.PUT; partial void DocumentFromPath(TDocument document) => this.Document = document; + private TDocument AutoRouteDocument() => Self.Document; void IProxyRequest.WriteJson(IElasticsearchSerializer sourceSerializer, Stream stream, SerializationFormatting formatting) => diff --git a/src/Tests/ClientConcepts/HighLevel/Inference/Equality/ActionIdsEqualityTests.cs b/src/Tests/ClientConcepts/HighLevel/Inference/Equality/ActionIdsEqualityTests.cs new file mode 100644 index 00000000000..2123c9bf6cb --- /dev/null +++ b/src/Tests/ClientConcepts/HighLevel/Inference/Equality/ActionIdsEqualityTests.cs @@ -0,0 +1,37 @@ +using FluentAssertions; +using Nest; +using Tests.Framework; + +namespace Tests.ClientConcepts.HighLevel.Inference.Equality +{ + public class NamesEqualityTests + { + [U] public void Eq() + { + Names types = "foo,bar"; + Names[] equal = {"foo,bar", "bar,foo", "foo, bar", "bar, foo "}; + foreach (var t in equal) + { + (t == types).ShouldBeTrue(t); + t.Should().Be(types); + } + } + + [U] public void NotEq() + { + Names types = "foo,bar"; + Names[] notEqual = {"foo,bar,x", "foo" }; + foreach (var t in notEqual) + { + (t != types).ShouldBeTrue(t); + t.Should().NotBe(types); + } + } + [U] public void Null() + { + Names types = "foo,bar"; + (types == null).Should().BeFalse(); + (null == types).Should().BeFalse(); + } + } +} diff --git a/src/Tests/ClientConcepts/HighLevel/Inference/Equality/CategoryIdEqualityTests.cs b/src/Tests/ClientConcepts/HighLevel/Inference/Equality/CategoryIdEqualityTests.cs new file mode 100644 index 00000000000..783cd8297f0 --- /dev/null +++ b/src/Tests/ClientConcepts/HighLevel/Inference/Equality/CategoryIdEqualityTests.cs @@ -0,0 +1,49 @@ +using FluentAssertions; +using Nest; +using Tests.Framework; + +namespace Tests.ClientConcepts.HighLevel.Inference.Equality +{ + public class CategoryIdEqualityTests + { + [U] public void Eq() + { + CategoryId types = 2; + CategoryId[] equal = {2L, 2}; + foreach (var t in equal) + { + (t == types).ShouldBeTrue(t); + t.Should().Be(types); + } + + CategoryId l1 = 2, l2 = 2; + (l1 == l2).ShouldBeTrue(l2); + (l1 == 2).ShouldBeTrue(l1); + l1.Should().Be(l2); + l1.Should().Be(2); + } + + [U] public void NotEq() + { + CategoryId types = 3; + CategoryId[] notEqual = {4L, 4}; + foreach (var t in notEqual) + { + (t != types).ShouldBeTrue(t); + t.Should().NotBe(types); + } + CategoryId l1 = 2, l2 = 3; + (l1 != l2).ShouldBeTrue(l2); + (l1 != 3).ShouldBeTrue(l1); + l1.Should().NotBe(l2); + l1.Should().NotBe(3); + } + + [U] public void Null() + { + CategoryId c = 10; + (c == null).Should().BeFalse(); + (null == c).Should().BeFalse(); + } + } +} diff --git a/src/Tests/ClientConcepts/HighLevel/Inference/Equality/DocumentPathEqualityTests.cs b/src/Tests/ClientConcepts/HighLevel/Inference/Equality/DocumentPathEqualityTests.cs new file mode 100644 index 00000000000..392705face0 --- /dev/null +++ b/src/Tests/ClientConcepts/HighLevel/Inference/Equality/DocumentPathEqualityTests.cs @@ -0,0 +1,49 @@ +using FluentAssertions; +using Nest; +using Tests.Framework; +using Tests.Framework.MockData; + +namespace Tests.ClientConcepts.HighLevel.Inference.Equality +{ + public class DocumentPathEqualityTests + { + [U] public void Eq() + { + var project = new Project {Name = "x"}; + DocumentPath path = project; + DocumentPath pathOther = project; + (pathOther == path).Should().BeTrue(); + pathOther.Should().Be(path); + + path = new DocumentPath(2); + pathOther = new DocumentPath(2); + (pathOther == path).Should().BeTrue(); + pathOther.Should().Be(path); + } + + [U] public void NotEq() + { + var project = new Project {Name = "x"}; + DocumentPath path = project; + DocumentPath pathOther = new Project {Name = "x"}; + (pathOther != path).Should().BeTrue(); + pathOther.Should().NotBe(path); + + path = new DocumentPath(2); + pathOther = new DocumentPath(2).Index("x"); + (pathOther != path).Should().BeTrue(); + pathOther.Should().NotBe(path); + + path = new DocumentPath(2); + pathOther = new DocumentPath(2).Type("x"); + (pathOther != path).Should().BeTrue(); + pathOther.Should().NotBe(path); + } + [U] public void Null() + { + var value = new DocumentPath(2); + (value == null).Should().BeFalse(); + (null == value).Should().BeFalse(); + } + } +} diff --git a/src/Tests/ClientConcepts/HighLevel/Inference/Equality/FieldEqualityTests.cs b/src/Tests/ClientConcepts/HighLevel/Inference/Equality/FieldEqualityTests.cs new file mode 100644 index 00000000000..8735f6d4edf --- /dev/null +++ b/src/Tests/ClientConcepts/HighLevel/Inference/Equality/FieldEqualityTests.cs @@ -0,0 +1,69 @@ +using FluentAssertions; +using Nest; +using Tests.Framework; +using Tests.Framework.MockData; + +namespace Tests.ClientConcepts.HighLevel.Inference.Equality +{ + public class FieldEqualityTests + { + [U] public void Eq() + { + Field name = "foo"; + Field[] equal = {"foo"}; + foreach (var t in equal) + { + (t == name).ShouldBeTrue(t); + t.Should().Be(name); + } + } + + [U] public void NotEq() + { + Field name = "foo"; + Field[] notEqual = {"bar", "x", "", " ", " foo ", Infer.Field(p=>p.Name)}; + foreach (var t in notEqual) + { + (t != name).ShouldBeTrue(t); + t.Should().NotBe(name); + } + } + + [U] public void TypedEq() + { + Field t1 = Infer.Field(p => p.Name), t2 = Infer.Field(p => p.Name); + (t1 == t2).ShouldBeTrue(t2); + t1.Should().Be(t2); + } + + [U] public void TypedNotEq() + { + Field t1 = Infer.Field(p => p.Id), t2 = Infer.Field(p => p.Id); + (t1 != t2).ShouldBeTrue(t2); + t1.Should().NotBe(t2); + } + + [U] public void ReflectedEq() + { + Field t1 = typeof(Project).GetProperty(nameof(Project.Name)), + t2 = typeof(Project).GetProperty(nameof(Project.Name)); + (t1 == t2).ShouldBeTrue(t2); + t1.Should().Be(t2); + } + + [U] public void ReflectedNotEq() + { + Field t1 = typeof(CommitActivity).GetProperty(nameof(CommitActivity.Id)), + t2 = typeof(Developer).GetProperty(nameof(Developer.Id)); + (t1 != t2).ShouldBeTrue(t2); + t1.Should().NotBe(t2); + } + + [U] public void Null() + { + Field value = "foo"; + (value == null).Should().BeFalse(); + (null == value).Should().BeFalse(); + } + } +} diff --git a/src/Tests/ClientConcepts/HighLevel/Inference/Equality/FieldsEqualityTests.cs b/src/Tests/ClientConcepts/HighLevel/Inference/Equality/FieldsEqualityTests.cs new file mode 100644 index 00000000000..8637f289d87 --- /dev/null +++ b/src/Tests/ClientConcepts/HighLevel/Inference/Equality/FieldsEqualityTests.cs @@ -0,0 +1,87 @@ +using FluentAssertions; +using Nest; +using Tests.Framework; +using Tests.Framework.MockData; + +namespace Tests.ClientConcepts.HighLevel.Inference.Equality +{ + public class FieldsEqualityTests + { + [U] public void Eq() + { + Fields name = "foo, bar"; + Fields[] equal = {"foo, bar", " foo, bar", "bar, foo", " bar , foo "}; + foreach (var t in equal) + { + (t == name).ShouldBeTrue(t); + t.Should().BeEquivalentTo(name); + } + } + + [U] public void NotEq() + { + Fields name = "foo, bar"; + Fields[] notEqual = {"bar", "foo, bar, x", "", " ", " foo ", Infer.Field(p=>p.Name)}; + foreach (var t in notEqual) + { + (t != name).ShouldBeTrue(t); + if (t != null) t.Should().NotBeEquivalentTo(name); + } + } + + [U] public void TypedEq() + { + Fields t1 = Infer.Field(p => p.Name), t2 = Infer.Field(p => p.Name); + (t1 == t2).ShouldBeTrue(t2); + t1.Should().BeEquivalentTo(t2); + + t1 = Infer.Field(p => p.Name, 1.1); t2 = Infer.Field(p => p.Name, 1.1); + (t1 == t2).ShouldBeTrue(t2); + t1.Should().BeEquivalentTo(t2); + + // boost factor is not taken into account when comparing fields + t1 = Infer.Field(p => p.Name, 2.1); t2 = Infer.Field(p => p.Name, 1.1); + (t1 == t2).ShouldBeTrue(t2); + t1.Should().BeEquivalentTo(t2); + + // boost factor is not taken into account when comparing fields + t1 = Infer.Field(p => p.Name); t2 = Infer.Field(p => p.Name, 1.1); + (t1 == t2).ShouldBeTrue(t2); + t1.Should().BeEquivalentTo(t2); + } + + [U] public void TypedNotEq() + { + Fields t1 = Infer.Field(p => p.Id), t2 = Infer.Field(p => p.Id); + (t1 != t2).ShouldBeTrue(t2); + t1.Should().NotBeEquivalentTo(t2); + + t1 = Infer.Field(p => p.Name, 1.0); t2 = Infer.Field(p => p.Location, 1.0); + (t1 != t2).ShouldBeTrue(t2); + t1.Should().NotBeEquivalentTo(t2); + } + + [U] public void ReflectedEq() + { + Fields t1 = typeof(Project).GetProperty(nameof(Project.Name)), + t2 = typeof(Project).GetProperty(nameof(Project.Name)); + (t1 == t2).ShouldBeTrue(t2); + t1.Should().BeEquivalentTo(t2); + } + + [U] public void ReflectedNotEq() + { + Fields t1 = typeof(CommitActivity).GetProperty(nameof(CommitActivity.Id)), + t2 = typeof(Developer).GetProperty(nameof(Developer.Id)); + (t1 != t2).ShouldBeTrue(t2); + t1.Should().NotBeEquivalentTo(t2); + } + + [U] public void Null() + { + Fields value = "foo"; + (value == null).Should().BeFalse(); + (null == value).Should().BeFalse(); + } + } +} diff --git a/src/Tests/ClientConcepts/HighLevel/Inference/Equality/IdEqualityTests.cs b/src/Tests/ClientConcepts/HighLevel/Inference/Equality/IdEqualityTests.cs new file mode 100644 index 00000000000..9bbdbb022b9 --- /dev/null +++ b/src/Tests/ClientConcepts/HighLevel/Inference/Equality/IdEqualityTests.cs @@ -0,0 +1,75 @@ +using System; +using FluentAssertions; +using Nest; +using Tests.Framework; +using Tests.Framework.MockData; + +namespace Tests.ClientConcepts.HighLevel.Inference.Equality +{ + public class IdEqualityTests + { + [U] public void Eq() + { + Id types = "foo"; + Id[] equal = {"foo"}; + foreach (var t in equal) + { + (t == types).ShouldBeTrue(t); + t.Should().Be(types); + } + + Id l1 = 2, l2 = 2; + (l1 == l2).ShouldBeTrue(l2); + (l1 == 2).ShouldBeTrue(l1); + (l1 == "2").ShouldBeTrue(l1); + l1.Should().Be(l2); + l1.Should().Be("2"); + l1.Should().Be(2); + + var g = Guid.NewGuid(); + l1 = g; l2 = g; + (l1 == l2).ShouldBeTrue(l2); + l1.Should().Be(l2); + + var project = new Project {Name = "x"}; + l1 = Id.From(project); l2 = Id.From(project); + (l1 == l2).ShouldBeTrue(l2); + l1.Should().Be(l2); + + } + + [U] public void NotEq() + { + Id types = "foo"; + Id[] notEqual = {"bar", "" , "foo "}; + foreach (var t in notEqual) + { + (t != types).ShouldBeTrue(t); + t.Should().NotBe(types); + } + Id l1 = 2, l2 = 3; + (l1 != l2).ShouldBeTrue(l2); + (l1 != 3).ShouldBeTrue(l1); + (l1 != "3").ShouldBeTrue(l1); + l1.Should().NotBe(l2); + l1.Should().NotBe(3); + l1.Should().NotBe("3"); + + l1 = Guid.NewGuid(); l2 = Guid.NewGuid(); + (l1 != l2).ShouldBeTrue(l2); + l1.Should().NotBe(l2); + + //when comparing objects we can only do referential equality. Project does not have its own Equals implementation. + l1 = Id.From(new Project {Name = "x"}); l2 = Id.From(new Project {Name = "x"}); + (l1 != l2).ShouldBeTrue(l2); + l1.Should().NotBe(l2); + } + + [U] public void Null() + { + Id value = "foo"; + (value == null).Should().BeFalse(); + (null == value).Should().BeFalse(); + } + } +} diff --git a/src/Tests/ClientConcepts/HighLevel/Inference/Equality/IndexMetricsEqualityTests.cs b/src/Tests/ClientConcepts/HighLevel/Inference/Equality/IndexMetricsEqualityTests.cs new file mode 100644 index 00000000000..9677c5e5e1f --- /dev/null +++ b/src/Tests/ClientConcepts/HighLevel/Inference/Equality/IndexMetricsEqualityTests.cs @@ -0,0 +1,41 @@ +using Elasticsearch.Net; +using FluentAssertions; +using Nest; +using Tests.Framework; + +namespace Tests.ClientConcepts.HighLevel.Inference.Equality +{ + public class IndexMetricsEqualityTests + { + [U] public void Eq() + { + IndexMetrics metrics = NodesStatsIndexMetric.All; + IndexMetrics[] equal = {NodesStatsIndexMetric.All}; + foreach (var t in equal) + { + (t == metrics).ShouldBeTrue(t); + t.Should().Be(metrics); + } + metrics.Should().Be(NodesStatsIndexMetric.All); + } + + [U] public void NotEq() + { + IndexMetrics metrics = NodesStatsIndexMetric.All; + IndexMetrics[] notEqual = {NodesStatsIndexMetric.Flush}; + foreach (var t in notEqual) + { + (t != metrics).ShouldBeTrue(t); + t.Should().NotBe(metrics); + } + metrics.Should().NotBe(NodesStatsMetric.All); + } + + [U] public void Null() + { + IndexMetrics value = NodesStatsIndexMetric.All; + (value == null).Should().BeFalse(); + (null == value).Should().BeFalse(); + } + } +} diff --git a/src/Tests/ClientConcepts/HighLevel/Inference/Equality/IndexNameEqualityTests.cs b/src/Tests/ClientConcepts/HighLevel/Inference/Equality/IndexNameEqualityTests.cs new file mode 100644 index 00000000000..85a2f15d7c0 --- /dev/null +++ b/src/Tests/ClientConcepts/HighLevel/Inference/Equality/IndexNameEqualityTests.cs @@ -0,0 +1,72 @@ +using FluentAssertions; +using Nest; +using Tests.Framework; +using Tests.Framework.MockData; + +namespace Tests.ClientConcepts.HighLevel.Inference.Equality +{ + public class IndexNameEqualityTests + { + [U] public void Eq() + { + IndexName types = "foo"; + IndexName[] equal = {"foo"}; + foreach (var t in equal) + { + (t == types).ShouldBeTrue(t); + t.Should().Be(types); + } + } + + [U] public void NotEq() + { + IndexName types = "foo"; + IndexName[] notEqual = {"bar", "foo ", " foo ", "x", "", " ", typeof(Project)}; + foreach (var t in notEqual) + { + (t != types).ShouldBeTrue(t); + t.Should().NotBe(types); + } + } + [U] public void EqCluster() + { + IndexName types = "c:foo"; + IndexName[] equal = {"c:foo"}; + foreach (var t in equal) + { + (t == types).ShouldBeTrue(t); + t.Should().Be(types); + } + } + + [U] public void NotEqCluster() + { + IndexName types = "c:foo"; + IndexName[] notEqual = {"c1:bar", "c:foo ", " c:foo ", "c:foo1", "x", "", " ", typeof(Project) }; + foreach (var t in notEqual) + { + (t != types).ShouldBeTrue(t); + t.Should().NotBe(types); + } + } + + [U] public void IndexdEq() + { + IndexName t1 = typeof(Project), t2 = typeof(Project); + (t1 == t2).ShouldBeTrue(t2); + } + + [U] public void IndexdNotEq() + { + IndexName t1 = typeof(Project), t2 = typeof(CommitActivity); + (t1 != t2).ShouldBeTrue(t2); + } + + [U] public void Null() + { + IndexName value = typeof(Project); + (value == null).Should().BeFalse(); + (null == value).Should().BeFalse(); + } + } +} diff --git a/src/Tests/ClientConcepts/HighLevel/Inference/Equality/IndicesEqualityTests.cs b/src/Tests/ClientConcepts/HighLevel/Inference/Equality/IndicesEqualityTests.cs new file mode 100644 index 00000000000..422543f25b3 --- /dev/null +++ b/src/Tests/ClientConcepts/HighLevel/Inference/Equality/IndicesEqualityTests.cs @@ -0,0 +1,52 @@ +using FluentAssertions; +using Tests.Framework; +using Tests.Framework.MockData; + +namespace Tests.ClientConcepts.HighLevel.Inference.Equality +{ + public class IndicesEqualityTests + { + [U] public void Eq() + { + Nest.Indices types = "foo,bar"; + Nest.Indices[] equal = {"foo,bar", "bar,foo", "foo, bar", "bar, foo "}; + foreach (var t in equal) + { + (t == types).ShouldBeTrue(t); + t.Should().Be(types); + } + + (Nest.Indices.All == "_all").Should().BeTrue(); + } + + + [U] public void NotEq() + { + Nest.Indices types = "foo,bar"; + Nest.Indices[] notEqual = {"foo,bar,x", "foo", typeof(Project)}; + foreach (var t in notEqual) + { + (t != types).ShouldBeTrue(t); + t.Should().NotBe(types); + } + } + + [U] public void TypedEq() + { + Nest.Indices t1 = typeof(Project), t2 = typeof(Project); + (t1 == t2).ShouldBeTrue(t2); + } + + [U] public void TypedNotEq() + { + Nest.Indices t1 = typeof(Project), t2 = typeof(CommitActivity); + (t1 != t2).ShouldBeTrue(t2); + } + [U] public void Null() + { + Nest.Indices value = typeof(Project); + (value == null).Should().BeFalse(); + (null == value).Should().BeFalse(); + } + } +} diff --git a/src/Tests/ClientConcepts/HighLevel/Inference/Equality/MetricsEqualityTests.cs b/src/Tests/ClientConcepts/HighLevel/Inference/Equality/MetricsEqualityTests.cs new file mode 100644 index 00000000000..7c12e5d88f3 --- /dev/null +++ b/src/Tests/ClientConcepts/HighLevel/Inference/Equality/MetricsEqualityTests.cs @@ -0,0 +1,40 @@ +using Elasticsearch.Net; +using FluentAssertions; +using Nest; +using Tests.Framework; + +namespace Tests.ClientConcepts.HighLevel.Inference.Equality +{ + public class MetricsEqualityTests + { + [U] public void Eq() + { + Metrics metrics = IndicesStatsMetric.All; + Metrics[] equal = {IndicesStatsMetric.All}; + foreach (var t in equal) + { + (t == metrics).ShouldBeTrue(t); + t.Should().Be(metrics); + } + metrics.Should().Be(IndicesStatsMetric.All); + } + + [U] public void NotEq() + { + Metrics metrics = IndicesStatsMetric.All; + Metrics[] notEqual = {IndicesStatsMetric.Completion, ClusterStateMetric.All}; + foreach (var t in notEqual) + { + (t != metrics).ShouldBeTrue(t); + t.Should().NotBe(metrics); + } + metrics.Should().NotBe(ClusterStateMetric.All); + } + [U] public void Null() + { + Metrics value = IndicesStatsMetric.All; + (value == null).Should().BeFalse(); + (null == value).Should().BeFalse(); + } + } +} diff --git a/src/Tests/ClientConcepts/HighLevel/Inference/Equality/NameEqualityTests.cs b/src/Tests/ClientConcepts/HighLevel/Inference/Equality/NameEqualityTests.cs new file mode 100644 index 00000000000..48637bb65f2 --- /dev/null +++ b/src/Tests/ClientConcepts/HighLevel/Inference/Equality/NameEqualityTests.cs @@ -0,0 +1,38 @@ +using FluentAssertions; +using Nest; +using Tests.Framework; + +namespace Tests.ClientConcepts.HighLevel.Inference.Equality +{ + public class NameEqualityTests + { + [U] public void Eq() + { + Name types = "foo"; + Name[] equal = {"foo", " foo", "foo "}; + foreach (var t in equal) + { + (t == types).ShouldBeTrue(t); + t.Should().Be(types); + } + } + + [U] public void NotEq() + { + Name types = "foo"; + Name[] notEqual = {"bar", "" }; + foreach (var t in notEqual) + { + (t != types).ShouldBeTrue(t); + t.Should().NotBe(types); + } + } + + [U] public void Null() + { + Name value = "foo"; + (value == null).Should().BeFalse(); + (null == value).Should().BeFalse(); + } + } +} diff --git a/src/Tests/ClientConcepts/HighLevel/Inference/Equality/NamesEqualityTests.cs b/src/Tests/ClientConcepts/HighLevel/Inference/Equality/NamesEqualityTests.cs new file mode 100644 index 00000000000..e798df41fb6 --- /dev/null +++ b/src/Tests/ClientConcepts/HighLevel/Inference/Equality/NamesEqualityTests.cs @@ -0,0 +1,38 @@ +using FluentAssertions; +using Nest; +using Tests.Framework; + +namespace Tests.ClientConcepts.HighLevel.Inference.Equality +{ + public class ActionIdsEqualityTests + { + [U] public void Eq() + { + ActionIds types = "foo,bar"; + ActionIds[] equal = {"foo,bar", "bar,foo", "foo, bar", "bar, foo "}; + foreach (var t in equal) + { + (t == types).ShouldBeTrue(t); + t.Should().Be(types); + } + } + + [U] public void NotEq() + { + ActionIds types = "foo,bar"; + ActionIds[] notEqual = {"foo,bar,x", "foo" }; + foreach (var t in notEqual) + { + (t != types).ShouldBeTrue(t); + t.Should().NotBe(types); + } + } + + [U] public void Null() + { + Names value = "foo"; + (value == null).Should().BeFalse(); + (null == value).Should().BeFalse(); + } + } +} diff --git a/src/Tests/ClientConcepts/HighLevel/Inference/Equality/NodeIdsEqualityTests.cs b/src/Tests/ClientConcepts/HighLevel/Inference/Equality/NodeIdsEqualityTests.cs new file mode 100644 index 00000000000..da42600b1f9 --- /dev/null +++ b/src/Tests/ClientConcepts/HighLevel/Inference/Equality/NodeIdsEqualityTests.cs @@ -0,0 +1,38 @@ +using FluentAssertions; +using Nest; +using Tests.Framework; + +namespace Tests.ClientConcepts.HighLevel.Inference.Equality +{ + public class NodeIdsEqualityTests + { + [U] public void Eq() + { + NodeIds types = "foo,bar"; + NodeIds[] equal = {"foo,bar", "bar,foo", "foo, bar", "bar, foo "}; + foreach (var t in equal) + { + (t == types).ShouldBeTrue(t); + t.Should().Be(types); + } + } + + [U] public void NotEq() + { + NodeIds types = "foo,bar"; + NodeIds[] notEqual = {"foo,bar,x", "foo"}; + foreach (var t in notEqual) + { + (t != types).ShouldBeTrue(t); + t.Should().NotBe(types); + } + } + + [U] public void Null() + { + NodeIds value = "foo"; + (value == null).Should().BeFalse(); + (null == value).Should().BeFalse(); + } + } +} diff --git a/src/Tests/ClientConcepts/HighLevel/Inference/Equality/PropertyNameEqualityTests.cs b/src/Tests/ClientConcepts/HighLevel/Inference/Equality/PropertyNameEqualityTests.cs new file mode 100644 index 00000000000..c880c398706 --- /dev/null +++ b/src/Tests/ClientConcepts/HighLevel/Inference/Equality/PropertyNameEqualityTests.cs @@ -0,0 +1,51 @@ +using FluentAssertions; +using Nest; +using Tests.Framework; +using Tests.Framework.MockData; + +namespace Tests.ClientConcepts.HighLevel.Inference.Equality +{ + public class PropertyNameEqualityTests + { + [U] public void Eq() + { + PropertyName name = "foo"; + PropertyName[] equal = {"foo"}; + foreach (var t in equal) + { + (t == name).ShouldBeTrue(t); + t.Should().Be(name); + } + } + + [U] public void NotEq() + { + PropertyName name = "foo"; + PropertyName[] notEqual = {"bar", "foo ", " foo ", "x", "", " ", Infer.Property(p=>p.Name)}; + foreach (var t in notEqual) + { + (t != name).ShouldBeTrue(t); + t.Should().NotBe(name); + } + } + + [U] public void TypedEq() + { + PropertyName t1 = Infer.Property(p => p.Name), t2 = Infer.Property(p => p.Name); + (t1 == t2).ShouldBeTrue(t2); + } + + [U] public void TypedNotEq() + { + PropertyName t1 = Infer.Property(p => p.Id), t2 = Infer.Property(p => p.Id); + (t1 != t2).ShouldBeTrue(t2); + } + + [U] public void Null() + { + PropertyName value = "foo"; + (value == null).Should().BeFalse(); + (null == value).Should().BeFalse(); + } + } +} diff --git a/src/Tests/ClientConcepts/HighLevel/Inference/Equality/RelationNameEqualityTests.cs b/src/Tests/ClientConcepts/HighLevel/Inference/Equality/RelationNameEqualityTests.cs new file mode 100644 index 00000000000..488f9ff816a --- /dev/null +++ b/src/Tests/ClientConcepts/HighLevel/Inference/Equality/RelationNameEqualityTests.cs @@ -0,0 +1,50 @@ +using FluentAssertions; +using Nest; +using Tests.Framework; +using Tests.Framework.MockData; + +namespace Tests.ClientConcepts.HighLevel.Inference.Equality +{ + public class RelationNameEqualityTests + { + [U] public void Eq() + { + RelationName name = "foo"; + RelationName[] equal = {"foo"}; + foreach (var t in equal) + { + (t == name).ShouldBeTrue(t); + t.Should().Be(name); + } + } + + [U] public void NotEq() + { + RelationName name = "foo"; + RelationName[] notEqual = {"bar", "foo ", " foo ", "x", "", " ", typeof(Project)}; + foreach (var t in notEqual) + { + (t != name).ShouldBeTrue(t); + t.Should().NotBe(name); + } + } + + [U] public void TypedEq() + { + RelationName t1 = typeof(Project), t2 = typeof(Project); + (t1 == t2).ShouldBeTrue(t2); + } + + [U] public void TypedNotEq() + { + RelationName t1 = typeof(Project), t2 = typeof(CommitActivity); + (t1 != t2).ShouldBeTrue(t2); + } + [U] public void Null() + { + RelationName value = "foo"; + (value == null).Should().BeFalse(); + (null == value).Should().BeFalse(); + } + } +} diff --git a/src/Tests/ClientConcepts/HighLevel/Inference/Equality/RoutingEqualityTests.cs b/src/Tests/ClientConcepts/HighLevel/Inference/Equality/RoutingEqualityTests.cs new file mode 100644 index 00000000000..f028b445828 --- /dev/null +++ b/src/Tests/ClientConcepts/HighLevel/Inference/Equality/RoutingEqualityTests.cs @@ -0,0 +1,66 @@ +using FluentAssertions; +using Nest; +using Tests.Framework; + +namespace Tests.ClientConcepts.HighLevel.Inference.Equality +{ + public class RoutingEqualityTests + { + [U] public void Eq() + { + Routing types = "foo"; + Routing[] equal = {"foo"}; + foreach (var t in equal) + { + (t == types).ShouldBeTrue(t); + t.Should().Be(types); + } + + Routing l1 = 2, l2 = 2; + (l1 == l2).ShouldBeTrue(l2); + (l1 == 2).ShouldBeTrue(l1); + (l1 == "2").ShouldBeTrue(l1); + l1.Should().Be(l2); + l1.Should().Be("2"); + l1.Should().Be(2); + + l1 = "foo, bar"; l2 = "bar, foo"; + (l1 == l2).ShouldBeTrue(l2); + l1.Should().Be(l2); + + } + + [U] public void NotEq() + { + Routing types = "foo"; + Routing[] notEqual = {"bar", "" , "foo "}; + foreach (var t in notEqual) + { + (t != types).ShouldBeTrue(t); + t.Should().NotBe(types); + } + Routing l1 = 2, l2 = 3; + (l1 != l2).ShouldBeTrue(l2); + (l1 != 3).ShouldBeTrue(l1); + (l1 != "3").ShouldBeTrue(l1); + l1.Should().NotBe(l2); + l1.Should().NotBe(3); + l1.Should().NotBe("3"); + + l1 = "foo, bar"; l2 = "bar, foo, x"; + (l1 != l2).ShouldBeTrue(l2); + l1.Should().NotBe(l2); + + l1 = "foo, bar"; l2 = "bar"; + (l1 != l2).ShouldBeTrue(l2); + l1.Should().NotBe(l2); + } + + [U] public void Null() + { + Routing value = "foo"; + (value == null).Should().BeFalse(); + (null == value).Should().BeFalse(); + } + } +} diff --git a/src/Tests/ClientConcepts/HighLevel/Inference/Equality/TaskIdEqualityTests.cs b/src/Tests/ClientConcepts/HighLevel/Inference/Equality/TaskIdEqualityTests.cs new file mode 100644 index 00000000000..4abbf54da5b --- /dev/null +++ b/src/Tests/ClientConcepts/HighLevel/Inference/Equality/TaskIdEqualityTests.cs @@ -0,0 +1,38 @@ +using FluentAssertions; +using Nest; +using Tests.Framework; + +namespace Tests.ClientConcepts.HighLevel.Inference.Equality +{ + public class TaskIdEqualityTests + { + [U] public void Eq() + { + TaskId types = "node:1337"; + TaskId[] equal = {"node:1337"}; + foreach (var t in equal) + { + (t == types).ShouldBeTrue(t); + t.Should().Be(types); + } + } + + [U] public void NotEq() + { + TaskId types = "node:1337"; + TaskId[] notEqual = {"node:1338", " node:1337", "node:1337 ", "node:133", "node2:1337"}; + foreach (var t in notEqual) + { + (t != types).ShouldBeTrue(t); + t.Should().NotBe(types); + } + } + + [U] public void Null() + { + TaskId value = "node:1339"; + (value == null).Should().BeFalse(); + (null == value).Should().BeFalse(); + } + } +} diff --git a/src/Tests/ClientConcepts/HighLevel/Inference/Equality/TypeNameEqualityTests.cs b/src/Tests/ClientConcepts/HighLevel/Inference/Equality/TypeNameEqualityTests.cs new file mode 100644 index 00000000000..7d130dbe228 --- /dev/null +++ b/src/Tests/ClientConcepts/HighLevel/Inference/Equality/TypeNameEqualityTests.cs @@ -0,0 +1,51 @@ +using FluentAssertions; +using Nest; +using Tests.Framework; +using Tests.Framework.MockData; + +namespace Tests.ClientConcepts.HighLevel.Inference.Equality +{ + public class TypeNameEqualityTests + { + [U] public void Eq() + { + TypeName types = "foo"; + TypeName[] equal = {"foo"}; + foreach (var t in equal) + { + (t == types).ShouldBeTrue(t); + t.Should().Be(types); + } + } + + [U] public void NotEq() + { + TypeName types = "foo"; + TypeName[] notEqual = {"bar", "foo ", " foo ", "x", "", " ", typeof(Project)}; + foreach (var t in notEqual) + { + (t != types).ShouldBeTrue(t); + t.Should().NotBe(types); + } + } + + [U] public void TypedEq() + { + TypeName t1 = typeof(Project), t2 = typeof(Project); + (t1 == t2).ShouldBeTrue(t2); + } + + [U] public void TypedNotEq() + { + TypeName t1 = typeof(Project), t2 = typeof(CommitActivity); + (t1 != t2).ShouldBeTrue(t2); + } + + [U] public void Null() + { + TypeName value = "foo"; + (value == null).Should().BeFalse(); + (null == value).Should().BeFalse(); + } + } +} diff --git a/src/Tests/ClientConcepts/HighLevel/Inference/Equality/TypesEqualityTests.cs b/src/Tests/ClientConcepts/HighLevel/Inference/Equality/TypesEqualityTests.cs new file mode 100644 index 00000000000..5fb9935bd6b --- /dev/null +++ b/src/Tests/ClientConcepts/HighLevel/Inference/Equality/TypesEqualityTests.cs @@ -0,0 +1,52 @@ +using FluentAssertions; +using Nest; +using Tests.Framework; +using Tests.Framework.MockData; + +namespace Tests.ClientConcepts.HighLevel.Inference.Equality +{ + public class TypesEqualityTests + { + [U] public void Eq() + { + Types types = "foo,bar"; + Types[] equal = {"foo,bar", "bar,foo", "foo, bar", "bar, foo "}; + foreach (var t in equal) + { + (t == types).ShouldBeTrue(t); + t.Should().Be(types); + } + } + + + [U] public void NotEq() + { + Types types = "foo,bar"; + Types[] notEqual = {"foo,bar,x", "foo", "", " ", typeof(Project)}; + foreach (var t in notEqual) + { + (t != types).ShouldBeTrue(t); + t.Should().NotBe(types); + } + } + + [U] public void TypedEq() + { + Types t1 = typeof(Project), t2 = typeof(Project); + (t1 == t2).ShouldBeTrue(t2); + } + + [U] public void TypedNotEq() + { + Types t1 = typeof(Project), t2 = typeof(CommitActivity); + (t1 != t2).ShouldBeTrue(t2); + } + + [U] public void Null() + { + Types value = "foo"; + (value == null).Should().BeFalse(); + (null == value).Should().BeFalse(); + } + } +} diff --git a/src/Tests/ClientConcepts/HighLevel/Inference/FieldInference.doc.cs b/src/Tests/ClientConcepts/HighLevel/Inference/FieldInference.doc.cs index 55e49d1832a..23ecab66c32 100644 --- a/src/Tests/ClientConcepts/HighLevel/Inference/FieldInference.doc.cs +++ b/src/Tests/ClientConcepts/HighLevel/Inference/FieldInference.doc.cs @@ -54,8 +54,6 @@ public void UsingConstructorAlsoSetsComparisonValue() * * - determining `Field` equality * - getting the hash code for a `Field` instance - * - * IMPORTANT: Boost values are **not** taken into account when determining equality. */ var fieldStringWithBoostTwo = new Field("name^2"); var fieldStringWithBoostThree = new Field("name^3"); @@ -70,7 +68,7 @@ public void UsingConstructorAlsoSetsComparisonValue() fieldExpression.GetHashCode().Should().NotBe(0); fieldProperty.GetHashCode().Should().NotBe(0); - fieldStringWithBoostTwo.Should().Be(fieldStringWithBoostThree); //<1> <> + fieldStringWithBoostTwo.Should().Be(fieldStringWithBoostTwo); //<1> <> } /** diff --git a/src/Tests/ClientConcepts/HighLevel/Inference/ImplicitConversionTests.cs b/src/Tests/ClientConcepts/HighLevel/Inference/ImplicitConversionTests.cs new file mode 100644 index 00000000000..4554d94daff --- /dev/null +++ b/src/Tests/ClientConcepts/HighLevel/Inference/ImplicitConversionTests.cs @@ -0,0 +1,202 @@ +using System; +using System.Linq.Expressions; +using System.Reflection; +using FluentAssertions; +using Nest; +using Tests.Framework; +using Tests.Framework.MockData; + +namespace Tests.ClientConcepts.HighLevel.Inference +{ + public class ImplicitConversionTests + { + private static T Implicit(T i) => i; + + [U] public void ActionIds() + { + Implicit(null).Should().BeNull(); + Implicit("").Should().BeNull(); + Implicit(" ").Should().BeNull(); + Implicit(",, ,,").Should().BeNull(); + Implicit(new string[] {}).Should().BeNull(); + Implicit(new string[] {null, null}).Should().BeNull(); + } + + [U] public void CategoryId() + { + Implicit(null).Should().BeNull(); + } + + [U] public void DocumentPath() + { + Implicit>((Project)null).Should().BeNull(); + Implicit>((Id)null).Should().BeNull(); + Implicit>((string)null).Should().BeNull(); + Implicit>("").Should().BeNull(); + Implicit>(" ").Should().BeNull(); + } + + [U] public void Field() + { + Implicit((string)null).Should().BeNull(); + Implicit((Expression)null).Should().BeNull(); + Implicit((PropertyInfo)null).Should().BeNull(); + Implicit("").Should().BeNull(); + Implicit(" ").Should().BeNull(); + } + + [U] public void Fields() + { + Implicit((Expression)null).Should().BeNull(); + Implicit((Field)null).Should().BeNull(); + Implicit((string)null).Should().BeNull(); + Implicit((PropertyInfo)null).Should().BeNull(); + Implicit((string[])null).Should().BeNull(); + Implicit((Expression[])null).Should().BeNull(); + Implicit((PropertyInfo[])null).Should().BeNull(); + Implicit((Field[])null).Should().BeNull(); + Implicit("").Should().BeNull(); + Implicit(" ").Should().BeNull(); + Implicit(new string[] {}).Should().BeNull(); + Implicit(new Expression[] {}).Should().BeNull(); + Implicit(new PropertyInfo[] {}).Should().BeNull(); + Implicit(new Field[] {}).Should().BeNull(); + Implicit(new Expression[] {null, null}).Should().BeNull(); + Implicit(new PropertyInfo[] {null, null}).Should().BeNull(); + Implicit(new Field[] {null, null}).Should().BeNull(); + } + + [U] public void Id() + { + Implicit(null).Should().BeNull(); + Implicit("").Should().BeNull(); + Implicit(" ").Should().BeNull(); + } + + [U] public void IndexName() + { + Implicit((string)null).Should().BeNull(); + Implicit((Type)null).Should().BeNull(); + Implicit("").Should().BeNull(); + Implicit(" ").Should().BeNull(); + } + + [U] public void Indices() + { + Implicit((string)null).Should().BeNull(); + Implicit((Nest.Indices.ManyIndices)null).Should().BeNull(); + Implicit((string[])null).Should().BeNull(); + Implicit((IndexName)null).Should().BeNull(); + Implicit((IndexName[])null).Should().BeNull(); + Implicit((IndexName)null).Should().BeNull(); + Implicit("").Should().BeNull(); + Implicit(" ").Should().BeNull(); + Implicit(",, ,, ").Should().BeNull(); + Implicit(new string[] {}).Should().BeNull(); + Implicit(new IndexName[] {}).Should().BeNull(); + Implicit(new string[] {null, null}).Should().BeNull(); + Implicit(new IndexName[] {null, null}).Should().BeNull(); + } + + [U] public void Names() + { + Implicit((string)null).Should().BeNull(); + Implicit((string[])null).Should().BeNull(); + Implicit("").Should().BeNull(); + Implicit(",,").Should().BeNull(); + Implicit(", ,").Should().BeNull(); + Implicit(" ").Should().BeNull(); + Implicit(new string[] {}).Should().BeNull(); + Implicit(new string[] {null, null}).Should().BeNull(); + } + + [U] public void Routing() + { + Implicit((string)null).Should().BeNull(); + Implicit((string[])null).Should().BeNull(); + Implicit("").Should().BeNull(); + Implicit(",,").Should().BeNull(); + Implicit(", ,").Should().BeNull(); + Implicit(" ").Should().BeNull(); + Implicit(new string[] {}).Should().BeNull(); + Implicit(new string[] {null, null}).Should().BeNull(); + } + + [U] public void Metrics() + { + Implicit(null).Should().BeNull(); + } + + [U] public void IndexMetrics() + { + Implicit(null).Should().BeNull(); + } + + [U] public void Name() + { + Implicit(null).Should().BeNull(); + Implicit("").Should().BeNull(); + Implicit(" ").Should().BeNull(); + } + + [U] public void NodeId() + { + Implicit((string)null).Should().BeNull(); + Implicit((string[])null).Should().BeNull(); + Implicit("").Should().BeNull(); + Implicit(" ").Should().BeNull(); + Implicit(" ,, , ,,").Should().BeNull(); + Implicit(new string[] {}).Should().BeNull(); + Implicit(new string[] {null, null}).Should().BeNull(); + } + + [U] public void PropertyName() + { + Implicit((Expression)null).Should().BeNull(); + Implicit((PropertyInfo)null).Should().BeNull(); + Implicit((string)null).Should().BeNull(); + Implicit("").Should().BeNull(); + Implicit(" ").Should().BeNull(); + } + + [U] public void RelationName() + { + Implicit((string)null).Should().BeNull(); + Implicit((Type)null).Should().BeNull(); + Implicit(" ").Should().BeNull(); + } + + [U] public void TaskId() + { + Implicit((string)null).Should().BeNull(); + Implicit(" ").Should().BeNull(); + Implicit("").Should().BeNull(); + } + + [U] public void TypeName() + { + Implicit((Type)null).Should().BeNull(); + Implicit((string)null).Should().BeNull(); + Implicit("").Should().BeNull(); + Implicit(" ").Should().BeNull(); + } + + [U] public void Types() + { + Implicit((TypeName)null).Should().BeNull(); + Implicit((Type)null).Should().BeNull(); + Implicit((Types.ManyTypes)null).Should().BeNull(); + Implicit((Types.AllTypesMarker)null).Should().BeNull(); + Implicit((string)null).Should().BeNull(); + Implicit("").Should().BeNull(); + Implicit(" ,,, ").Should().BeNull(); + Implicit(" ").Should().BeNull(); + Implicit(new string[] {}).Should().BeNull(); + Implicit(new TypeName[] {}).Should().BeNull(); + Implicit(new string[] {null, null}).Should().BeNull(); + Implicit(new TypeName[] {null, null}).Should().BeNull(); + } + + + } +} diff --git a/src/Tests/ClientConcepts/HighLevel/Inference/IndexNameInference.doc.cs b/src/Tests/ClientConcepts/HighLevel/Inference/IndexNameInference.doc.cs index 357da5da6d7..1fae2880ed9 100644 --- a/src/Tests/ClientConcepts/HighLevel/Inference/IndexNameInference.doc.cs +++ b/src/Tests/ClientConcepts/HighLevel/Inference/IndexNameInference.doc.cs @@ -154,8 +154,8 @@ [U] public void RoundTripSerializationPreservesCluster() [U] public void ImplicitConversionReadsCluster() { var i = (IndexName)"cluster_one : project "; - i.Cluster.Should().Be("cluster_one"); - i.Name.Should().Be("project"); + i.Cluster.Should().Be("cluster_one "); + i.Name.Should().Be(" project "); i = (IndexName)"cluster_one:project"; i.Cluster.Should().Be("cluster_one"); diff --git a/src/Tests/Document/Single/Index/IndexUrlTests.cs b/src/Tests/Document/Single/Index/IndexUrlTests.cs index 52b5d324b94..03e7724ed46 100644 --- a/src/Tests/Document/Single/Index/IndexUrlTests.cs +++ b/src/Tests/Document/Single/Index/IndexUrlTests.cs @@ -23,10 +23,14 @@ await POST("/project/doc?routing=NEST") Document = project })); - await POST("/project/doc") + //no explit ID is provided and none can be inferred on the anonymous object so this falls back to a PUT to /index/type + await PUT("/project/doc") .Fluent(c => c.Index(new { }, i => i.Index(typeof(Project)).Type(typeof(Project)))) + .FluentAsync(c => c.IndexAsync(new { }, i => i.Index(typeof(Project)).Type(typeof(Project)))); + + //no explit ID is provided and document is not fed into DocumentPath using explicit OIS. + await POST("/project/doc") .Request(c => c.Index(new IndexRequest("project", "doc") {Document = new { }})) - .FluentAsync(c => c.IndexAsync(new { }, i => i.Index(typeof(Project)).Type(typeof(Project)))) .RequestAsync(c => c.IndexAsync(new IndexRequest(typeof(Project), TypeName.From()) { Document = new { } diff --git a/src/Tests/Framework/Extensions/ShouldExtensions.cs b/src/Tests/Framework/Extensions/ShouldExtensions.cs index ff1f775fe6c..4f418135722 100644 --- a/src/Tests/Framework/Extensions/ShouldExtensions.cs +++ b/src/Tests/Framework/Extensions/ShouldExtensions.cs @@ -1,4 +1,5 @@ -using FluentAssertions; +using Elasticsearch.Net; +using FluentAssertions; using Nest; using Tests.Framework.MockData; @@ -29,5 +30,8 @@ public static void ShouldAdhereToSourceSerializerWhenSet(this Project project) project.SourceOnly.NotWrittenByDefaultSerializer.Should().Be("written"); project.SourceOnly.NotReadByDefaultSerializer.Should().Be("read"); } + + public static void ShouldBeTrue(this bool b, IUrlParameter p) => + b.Should().BeTrue(p?.GetString(TestClient.GlobalDefaultSettings) ?? "NULL"); } }