/* * SearchResult.vala * * Represents a search result item from the feed database. * Following GNOME HIG naming conventions and Vala/GObject patterns. */ /** * SearchResultType - Type of search result */ public enum RSSuper.SearchResultType { ARTICLE, FEED } /** * SearchResult - Represents a single search result */ public class RSSuper.SearchResult : Object { public string id { get; set; } public SearchResultType result_type { get; set; } public string title { get; set; } public string? snippet { get; set; } public string? link { get; set; } public string? feed_title { get; set; } public string? published { get; set; } public double score { get; set; } /** * Default constructor */ public SearchResult() { this.id = ""; this.result_type = SearchResultType.ARTICLE; this.title = ""; this.score = 0.0; } /** * Constructor with initial values */ public SearchResult.with_values(string id, SearchResultType type, string title, string? snippet = null, string? link = null, string? feed_title = null, string? published = null, double score = 0.0) { this.id = id; this.result_type = type; this.title = title; this.snippet = snippet; this.link = link; this.feed_title = feed_title; this.published = published; this.score = score; } /** * Get type as string */ public string get_type_string() { switch (this.result_type) { case SearchResultType.ARTICLE: return "article"; case SearchResultType.FEED: return "feed"; default: return "unknown"; } } /** * Parse type from string */ public static SearchResultType type_from_string(string str) { switch (str) { case "article": return SearchResultType.ARTICLE; case "feed": return SearchResultType.FEED; default: return SearchResultType.ARTICLE; } } /** * Serialize to JSON string */ public string to_json_string() { var sb = new StringBuilder(); sb.append("{"); sb.append("\"id\":\""); sb.append(this.id); sb.append("\",\"type\":\""); sb.append(this.get_type_string()); sb.append("\",\"title\":\""); sb.append(this.title); sb.append("\""); if (this.snippet != null) { sb.append(",\"snippet\":\""); sb.append(this.snippet); sb.append("\""); } if (this.link != null) { sb.append(",\"link\":\""); sb.append(this.link); sb.append("\""); } if (this.feed_title != null) { sb.append(",\"feedTitle\":\""); sb.append(this.feed_title); sb.append("\""); } if (this.published != null) { sb.append(",\"published\":\""); sb.append(this.published); sb.append("\""); } if (this.score != 0.0) { sb.append(",\"score\":%f".printf(this.score)); } sb.append("}"); return sb.str; } /** * Deserialize from JSON string */ public static SearchResult? from_json_string(string json_string) { var parser = new Json.Parser(); try { if (!parser.load_from_data(json_string)) { return null; } } catch (Error e) { warning("Failed to parse JSON: %s", e.message); return null; } return from_json_node(parser.get_root()); } /** * Deserialize from Json.Node */ public static SearchResult? from_json_node(Json.Node node) { if (node.get_node_type() != Json.NodeType.OBJECT) { return null; } var obj = node.get_object(); if (!obj.has_member("id") || !obj.has_member("type") || !obj.has_member("title")) { return null; } var result = new SearchResult(); result.id = obj.get_string_member("id"); result.result_type = SearchResult.type_from_string(obj.get_string_member("type")); result.title = obj.get_string_member("title"); if (obj.has_member("snippet")) { result.snippet = obj.get_string_member("snippet"); } if (obj.has_member("link")) { result.link = obj.get_string_member("link"); } if (obj.has_member("feedTitle")) { result.feed_title = obj.get_string_member("feedTitle"); } if (obj.has_member("published")) { result.published = obj.get_string_member("published"); } if (obj.has_member("score")) { result.score = obj.get_double_member("score"); } return result; } /** * Equality comparison */ public bool equals(SearchResult? other) { if (other == null) { return false; } return this.id == other.id && this.result_type == other.result_type && this.title == other.title && this.snippet == other.snippet && this.link == other.link && this.feed_title == other.feed_title && this.published == other.published && this.score == other.score; } /** * Get a human-readable summary */ public string get_summary() { if (this.feed_title != null) { return "[%s] %s - %s".printf(this.get_type_string(), this.feed_title, this.title); } return "[%s] %s".printf(this.get_type_string(), this.title); } }