using Hqub.MusicBrainz.API.Entities; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Hqub.MusicBrainz.API { /// /// Helper for building MusicBrainz query strings. /// /// The entity type to search for. /// /// See https://musicbrainz.org/doc/Development/XML_Web_Service/Version_2/Search /// public class QueryParameters where T : Entity { List values; public QueryParameters() { values = new List(); } /// /// Add a field to the query paramaters. /// /// The field key. /// The field value. /// Negate the field (will result in 'AND NOT key:value') public void Add(string key, string value, bool negate = false) { if (string.IsNullOrEmpty(key)) { throw new ArgumentException(string.Format(Resources.Messages.MissingParameter, "key")); } if (!Validate(key)) { throw new Exception(string.Format(Resources.Messages.InvalidQueryParameter, key)); } values.Add(new QueryNode(key, value, negate)); } public override string ToString() { return BuildQueryString(); } private string BuildQueryString() { var sb = new StringBuilder(); string value; foreach (var item in values) { // Append operator. if (sb.Length > 0) { sb.Append(" AND "); } // Negate operator. if (item.Negate) { sb.Append("NOT "); } // Append key. sb.Append(item.Key); sb.Append(':'); // Append value. value = item.Value; if (value.Contains("AND") || value.Contains("OR")) { if (!value.StartsWith("(")) { // The search value appears to be an expression, so enclose it in brackets. sb.Append("(" + value + ")"); } else { sb.Append(value); } } else if (value.Contains(" ") && !value.StartsWith("\"")) { // The search value contains whitespace but isn't quoted. sb.Append("\"" + value + "\""); } else { // The search value is already quoted or doesn't need quoting, so just append it. sb.AppendFormat(value); } } return sb.ToString(); } private bool Validate(string key) { key = "-" + key + "-"; if (typeof(T) == typeof(Artist)) { return Resources.Constants.ArtistQueryParams.IndexOf(key) >= 0; } if (typeof(T) == typeof(Recording)) { return Resources.Constants.RecordingQueryParams.IndexOf(key) >= 0; } if (typeof(T) == typeof(Release)) { return Resources.Constants.ReleaseQueryParams.IndexOf(key) >= 0; } if (typeof(T) == typeof(ReleaseGroup)) { return Resources.Constants.ReleaseGroupQueryParams.IndexOf(key) >= 0; } return false; } class QueryNode { public string Key { get; private set; } public string Value { get; private set; } public bool Negate { get; private set; } public QueryNode(string key, string value, bool negate) { this.Key = key; this.Value = value; this.Negate = negate; } } } }