/* SPDX-License-Identifier: Apache-2.0 * * The OpenSearch Contributors require contributions made to * this file be licensed under the Apache-2.0 license or a * compatible open source license. */ /* * Modifications Copyright OpenSearch Contributors. See * GitHub history for details. * * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright * ownership. Elasticsearch B.V. licenses this file to you under * the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ using System; using System.Diagnostics; using System.Globalization; using OpenSearch.Net; using OpenSearch.Net.Utf8Json; namespace OpenSearch.Client { [DebuggerDisplay("{DebugDisplay,nq}")] [JsonFormatter(typeof(TaskIdFormatter))] public class TaskId : IUrlParameter, IEquatable<TaskId> { /// <summary> /// A task id exists in the form [node_id]:[task_id] /// </summary> /// <param name="taskId">the task identifier</param> public TaskId(string taskId) { if (string.IsNullOrWhiteSpace(taskId)) throw new ArgumentException("TaskId can not be an empty string", nameof(taskId)); var tokens = taskId.Split(new[] { ':' }, StringSplitOptions.RemoveEmptyEntries); if (tokens.Length != 2) throw new ArgumentException($"TaskId:{taskId} not in expected format of <node_id>:<task_id>", nameof(taskId)); NodeId = tokens[0]; 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)); TaskNumber = t; } public string FullyQualifiedId { get; } public string NodeId { get; } public long TaskNumber { get; } private string DebugDisplay => FullyQualifiedId; public bool Equals(TaskId other) => EqualsString(other?.FullyQualifiedId); public string GetString(IConnectionConfigurationValues settings) => FullyQualifiedId; public override string ToString() => FullyQualifiedId; public static implicit operator TaskId(string taskId) => taskId.IsNullOrEmpty() ? null : new TaskId(taskId); public static bool operator ==(TaskId left, TaskId right) => Equals(left, right); public static bool operator !=(TaskId left, TaskId right) => !Equals(left, right); public override bool Equals(object obj) => obj != null && obj is string s ? EqualsString(s) : obj is TaskId i && EqualsString(i.FullyQualifiedId); private bool EqualsString(string other) => !other.IsNullOrEmpty() && other == FullyQualifiedId; public override int GetHashCode() { unchecked { return (NodeId.GetHashCode() * 397) ^ TaskNumber.GetHashCode(); } } } internal class TaskIdFormatter : IJsonFormatter<TaskId>, IObjectPropertyNameFormatter<TaskId> { public TaskId Deserialize(ref JsonReader reader, IJsonFormatterResolver formatterResolver) { if (reader.GetCurrentJsonToken() == JsonToken.String) return new TaskId(reader.ReadString()); reader.ReadNextBlock(); return null; } public void Serialize(ref JsonWriter writer, TaskId value, IJsonFormatterResolver formatterResolver) { if (value == null) { writer.WriteNull(); return; } writer.WriteString(value.ToString()); } public TaskId DeserializeFromPropertyName(ref JsonReader reader, IJsonFormatterResolver formatterResolver) => Deserialize(ref reader, formatterResolver); public void SerializeToPropertyName(ref JsonWriter writer, TaskId value, IJsonFormatterResolver formatterResolver) => Serialize(ref writer, value, formatterResolver); } }