 }
 
 public extension EUtils {
-    static func summary(accession: String) throws -> [String:AnyObject]
+    static func summary(database: String, accession: String) -> [String:AnyObject]
     {
-        let gilist = search(accession, database: "nuccore")
+        let gilist = IDList(database, term: accession)
         guard gilist.count > 0 else { return [:] }
-        let url = summaryURL(gilist[0], database: "nuccore").url
+        let url = summaryURL(gilist[0], database: database)
         guard
             let data = try? NSData(contentsOfURL: url, options: []),
             let json = try? NSJSONSerialization.JSONObjectWithData(data, options: []),

    }
}

private extension EUtils {
    static func search(term: String, database: String) -> [String]
    {
        let url = searchURL(term, database: database).url
        guard
            let data = try? NSData(contentsOfURL: url, options: []),
            let json = try? NSJSONSerialization.JSONObjectWithData(data, options: []),

public extension EUtils {
    static func FASTA(accession: String, f: (String) -> Bool) throws
    {
        let gilist = IDList("nuccore", term: accession)
        guard gilist.count > 0 else { return }
        let url = fetchURL(gilist[0], database: "nuccore")
        try String(contentsOfURL: url, encoding: NSUTF8StringEncoding).enumerateLines { (line, inout stop: Bool) in
            stop = f(line)
        }
    }
}

func extractRunAttributes(escapedXML: String) -> [EUtils.Run]
{
    let xml = escapedXML.stringByReplacingOccurrencesOfString("&lt;", withString: "<")
                        .stringByReplacingOccurrencesOfString("&gt;", withString: ">")
                        .stringByReplacingOccurrencesOfString("&amp;", withString: "&")

    class parserDelegate: NSObject, NSXMLParserDelegate {
        var runs : [EUtils.Run] = []
        
        @objc func parser(_: NSXMLParser, didStartElement element: String, namespaceURI: String?, qualifiedName: String?, attributes: [String : String]) {
            if element == "Run" && attributes["acc"] != nil {
                runs.append(EUtils.Run(attr: attributes))
            }
        }
    }
    let d = parserDelegate()
    let p = NSXMLParser(data: xml.dataUsingEncoding(NSUTF8StringEncoding)!)
    
    p.delegate = d
    if p.parse() {
        return d.runs
    }
    return []
}

public extension EUtils {
    public struct Run : CustomStringConvertible {
        private let attr: [String : String]
        
        public var accession: String {
            get {
                return attr["acc"]!
            }
        }
        public var baseCount: UInt {
            get {
                if let x = attr["total_bases"], y = UInt(x) { return y }
                return 0
            }
        }
        public var spotCount: UInt {
            get {
                if let x = attr["total_spots"], y = UInt(x) { return y }
                return 0
            }
        }
        public var isLoaded: Bool {
            get {
                if let x = attr["load_done"] where x == "true" { return true }
                return false
            }
        }
        public var isPublic: Bool {
            get {
                if let x = attr["is_public"] where x == "true" { return true }
                return false
            }
        }
        public var description: String { get { return attr.description } }
    }
    static func SRARunList(term: String) -> [Run]
    {
        var rslt = [Run]()
        for id in IDList("sra", term: term) {
            let s = summary("sra", accession: id)
            if let runs = s["runs"] as? String {
                rslt.appendContentsOf(extractRunAttributes(runs))
            }
        }
        return rslt
    }
}
