         return false
     }
 }
+
+public func isEqualSuggestions(_ lhs: Suggestion?, _ rhs: Suggestion?) -> Bool {
+    if lhs == nil && rhs == nil {
+        return true
+    }
+    if let lhs = lhs, let rhs = rhs {
+        return lhs.isEqualTo(rhs)
+    }
+    return false
+}
+
 
 public enum SuggestionType: String, Codable {
     case term

public struct SuggestSource {
    
    public var globalText: String?
    public var suggestions: [String: String]
    
}

extension SuggestSource: Codable {
    
    public init(from decoder: Decoder) throws {
        var container = try decoder.unkeyedContainer()
        var dic = try container.decode([String: String].self)
        self.globalText = dic[CodingKeys.globalText.rawValue]
        dic.removeValue(forKey: CodingKeys.globalText.rawValue)
        self.suggestions = dic
    }
    
    public func encode(to encoder: Encoder) throws {

    }
}

extension SuggestSource: Equatable {
    public static func == (lhs: SuggestSource, rhs: SuggestSource) -> Bool {
        guard lhs.suggestions.count == lhs.suggestions.count else {
            return false
        }
        
        return lhs.globalText == rhs.globalText
            && lhs.suggestions.keys.allSatisfy({
                rhs.suggestions.keys.contains($0)
                && isEqualSuggestions(lhs.suggestions[$0], rhs.suggestions[$0])
            })
    }
}


public class TermSuggestionBuilder: SuggestionBuilder {
