using System; using System.Collections.Concurrent; using System.Collections.Generic; using Newtonsoft.Json; namespace LibSearchBox { public class SearchBoxException : Exception { public SearchBoxException(string message) : base(message) { } } [JsonObject(MemberSerialization.OptIn)] public class SearchBox { private IdMap idMap = new IdMap(); [JsonProperty("ids")] public Dictionary IdMap { get { Dictionary result = idMap.MapOut; if (result.Count == 0) return null; return result; } set { if (value == null) return; idMap.Import(value); } } [JsonProperty] public ConcurrentDictionary metaTable = new ConcurrentDictionary(); [JsonProperty] public InvertedIndex index = new InvertedIndex(); public SearchBox() { } public void AddDocument(string title, IEnumerable tags, string content) { DocumentMeta info = new DocumentMeta(title, tags); int id = idMap.GetId(info.Title); metaTable.AddOrUpdate(id, info, (key, oldValue) => info); Index upsideIndex = new Index(content); index.AddIndex(id, upsideIndex); } public void UpdateDocument(string title, IEnumerable newTags, string oldContent, string newContent) { int id = idMap.GetId(title); DocumentMeta info = metaTable[id]; info.ReplaceTags(newTags); Index oldIndex = new Index(oldContent), newIndex = new Index(newContent); if (!index.ReplaceIndex(id, oldIndex, newIndex)) throw new SearchBoxException($"Error: Failed to replace index for document with title {title}."); } public void RemoveDocument(string title) { int id = idMap.DeletePageName(title); metaTable.TryRemove(id, out DocumentMeta noop); if (!index.RemoveById(id)) throw new SearchBoxException($"Failed to remove page with title '{title}' from inverted index."); } } }