<commit_before>import Foundation

public enum RequestType {
    case launch
    case intent
    case sessionEnded
}

public class RequestParser {
    public let json: Any
    
    public convenience init(contentsOf url: URL) throws {
        let data = try Data(contentsOf: url)
        try self.init(with: data)
    }
    
    public convenience init(fileHandle: FileHandle) throws {
        try self.init(with: fileHandle.readDataToEndOfFile())
    }
    
    public convenience init(with data: Data) throws {
        let json = try JSONSerialization.jsonObject(with: data)
        self.init(json: json)
    }
    
    public init(json: Any) {
        self.json = json
    }
    
    public func parseSession() -> Session? {
        guard let jsonEnvelope = json as? [String: Any],
            let jsonSession = jsonEnvelope["session"] as? [String: Any],
            let isNew = jsonSession["new"] as? Bool,
            let sessionId = jsonSession["sessionId"] as? String,
            let application = RequestParser.parseApplication(jsonSession),
            let user = RequestParser.parseUser(jsonSession) else {
                return nil
        }
        
        return Session(isNew: isNew, sessionId: sessionId, application: application, attributes: [:], user: user)
    }
    
    public func parseRequestType() -> RequestType? {
        guard let jsonEnvelope = json as? [String: Any],
            let jsonRequest = jsonEnvelope["request"] as? [String: Any],
            let type = jsonRequest["type"] as? String else {
                return nil
        }
        
        switch type {
        case "LaunchRequest": return .launch
        case "IntentRequest": return .intent
        case "SessionEndedRequest": return .sessionEnded
        default: return nil
        }
    }
    
    public func parseLaunchRequest() -> LaunchRequest? {
        guard let jsonEnvelope = json as? [String: Any],
            let jsonRequest = jsonEnvelope["request"] as? [String: Any],
            let request = RequestParser.parseRequest(jsonRequest) else {
                return nil
        }
        
        return LaunchRequest(request: request)
    }
    
    public func parseIntentRequest() -> IntentRequest? {
        guard let jsonEnvelope = json as? [String: Any],
            let jsonRequest = jsonEnvelope["request"] as? [String: Any],
            let request = RequestParser.parseRequest(jsonRequest),
            let intent = RequestParser.parseIntent(jsonRequest) else {
                return nil
        }
        
        return IntentRequest(request: request, intent: intent)
    }
    
    public func parseSessionEndedRequest() -> SessionEndedRequest? {
        guard let jsonEnvelope = json as? [String: Any],
            let jsonRequest = jsonEnvelope["request"] as? [String: Any],
            let request = RequestParser.parseRequest(jsonRequest),
            let reason = RequestParser.parseReason(jsonRequest) else {
                return nil
        }
        
        return SessionEndedRequest(request: request, reason: reason)
    }
}

extension RequestParser {
    class func parseDate(_ string: String) -> Date? {
        let dateFormatter = DateFormatter()
        dateFormatter.locale = Locale(identifier: "en_US_POSIX")
        dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
        dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'"
        
        return dateFormatter.date(from: string)
    }
    
    class func parseApplication(_ jsonSession: [String: Any]) -> Application? {
        guard let jsonApplication = jsonSession["application"] as? [String: Any],
            let applicationId = jsonApplication["applicationId"] as? String else {
            return nil
        }
        
        return Application(applicationId: applicationId)
    }
    
    class func parseUser(_ jsonSession: [String: Any]) -> User? {
        guard let jsonUser = jsonSession["user"] as? [String: Any],
            let userId = jsonUser["userId"] as? String else {
                return nil
        }
        
        let accessToken = jsonUser["accessToken"] as? String
        return User(userId: userId, accessToken: accessToken)
    }
    
    class func parseRequest(_ jsonRequest: [String: Any]) -> Request? {
        guard let requestId = jsonRequest["requestId"] as? String,
            let timestampString = jsonRequest["timestamp"] as? String,
            let timestamp = RequestParser.parseDate(timestampString),
            let localeString = jsonRequest["locale"] as? String else {
                return nil
        }
        
        return Request(requestId: requestId, timestamp: timestamp, locale: Locale(identifier: localeString))
    }
    
    class func parseSlots(_ jsonSlots: [String: Any]) -> [String: Slot] {
        var slots = [String: Slot]()
        for (key, json) in jsonSlots {
            guard let jsonSlot = json as? [String: Any],
                let name = jsonSlot["name"] as? String else {
                    continue
            }
            
            let value = jsonSlot["value"] as? String
            slots[key] = Slot(name: name, value: value)
        }

        return slots
    }
    
    class func parseIntent(_ jsonRequest: [String: Any]) -> Intent? {
        guard let jsonIntent = jsonRequest["intent"] as? [String: Any],
            let name = jsonIntent["name"] as? String,
            let jsonSlots = jsonIntent["slots"] as? [String: Any] else {
                return nil
        }
        
        let slots = RequestParser.parseSlots(jsonSlots)
        return Intent(name: name, slots: slots)
    }
    
    class func parseReason(_ jsonRequest: [String: Any]) -> Reason? {
        guard let reason = jsonRequest["reason"] as? String else {
            return nil
        }
        
        switch reason {
        case "USER_INITIATED": return .userInitiated
        case "ERROR": return RequestParser.parseError(jsonRequest).map{ .error($0) }
        case "EXCEEDED_MAX_REPROMPTS": return .exceededMaxReprompts
        default: return .unknown
        }
    }
    
    class func parseError(_ jsonRequest: [String: Any]) -> Error? {
        guard let jsonError = jsonRequest["error"] as? [String: Any],<commit_msg>Parse top level attribute<commit_after>import Foundation

public enum RequestType {
    case launch
    case intent
    case sessionEnded
}

public class RequestParser {
    public let json: Any
    
    public convenience init(contentsOf url: URL) throws {
        let data = try Data(contentsOf: url)
        try self.init(with: data)
    }
    
    public convenience init(fileHandle: FileHandle) throws {
        try self.init(with: fileHandle.readDataToEndOfFile())
    }
    
    public convenience init(with data: Data) throws {
        let json = try JSONSerialization.jsonObject(with: data)
        self.init(json: json)
    }
    
    public init(json: Any) {
        self.json = json
    }
    
    public func parseSession() -> Session? {
        guard let jsonEnvelope = json as? [String: Any],
            let jsonSession = jsonEnvelope["session"] as? [String: Any],
            let isNew = jsonSession["new"] as? Bool,
            let sessionId = jsonSession["sessionId"] as? String,
            let application = RequestParser.parseApplication(jsonSession),
            let user = RequestParser.parseUser(jsonSession) else {
                return nil
        }
        
        return Session(isNew: isNew, sessionId: sessionId, application: application, attributes: [:], user: user)
    }
    
    public func parseRequestType() -> RequestType? {
        guard let jsonEnvelope = json as? [String: Any],
            let jsonRequest = jsonEnvelope["request"] as? [String: Any],
            let type = jsonRequest["type"] as? String else {
                return nil
        }
        
        switch type {
        case "LaunchRequest": return .launch
        case "IntentRequest": return .intent
        case "SessionEndedRequest": return .sessionEnded
        default: return nil
        }
    }
    
    public func parseLaunchRequest() -> LaunchRequest? {
        guard let jsonEnvelope = json as? [String: Any],
            let jsonRequest = jsonEnvelope["request"] as? [String: Any],
            let request = RequestParser.parseRequest(jsonRequest) else {
                return nil
        }
        
        return LaunchRequest(request: request)
    }
    
    public func parseIntentRequest() -> IntentRequest? {
        guard let jsonEnvelope = json as? [String: Any],
            let jsonRequest = jsonEnvelope["request"] as? [String: Any],
            let request = RequestParser.parseRequest(jsonRequest),
            let intent = RequestParser.parseIntent(jsonRequest) else {
                return nil
        }
        
        return IntentRequest(request: request, intent: intent)
    }
    
    public func parseSessionEndedRequest() -> SessionEndedRequest? {
        guard let jsonEnvelope = json as? [String: Any],
            let jsonRequest = jsonEnvelope["request"] as? [String: Any],
            let request = RequestParser.parseRequest(jsonRequest),
            let reason = RequestParser.parseReason(jsonRequest) else {
                return nil
        }
        
        return SessionEndedRequest(request: request, reason: reason)
    }
}

extension RequestParser {
    class func parseDate(_ string: String) -> Date? {
        let dateFormatter = DateFormatter()
        dateFormatter.locale = Locale(identifier: "en_US_POSIX")
        dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
        dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'"
        
        return dateFormatter.date(from: string)
    }
    
    class func parseApplication(_ jsonSession: [String: Any]) -> Application? {
        guard let jsonApplication = jsonSession["application"] as? [String: Any],
            let applicationId = jsonApplication["applicationId"] as? String else {
            return nil
        }
        
        return Application(applicationId: applicationId)
    }
    
    class func parseUser(_ jsonSession: [String: Any]) -> User? {
        guard let jsonUser = jsonSession["user"] as? [String: Any],
            let userId = jsonUser["userId"] as? String else {
                return nil
        }
        
        let accessToken = jsonUser["accessToken"] as? String
        return User(userId: userId, accessToken: accessToken)
    }
    
    class func parseRequest(_ jsonRequest: [String: Any]) -> Request? {
        guard let requestId = jsonRequest["requestId"] as? String,
            let timestampString = jsonRequest["timestamp"] as? String,
            let timestamp = RequestParser.parseDate(timestampString),
            let localeString = jsonRequest["locale"] as? String else {
                return nil
        }
        
        return Request(requestId: requestId, timestamp: timestamp, locale: Locale(identifier: localeString))
    }
    
    class func parseSlots(_ jsonIntent: [String: Any]) -> [String: Slot] {
        var slots = [String: Slot]()
        
        if let jsonSlots = jsonIntent["slots"] as? [String: Any] {
            for (key, json) in jsonSlots {
                guard let jsonSlot = json as? [String: Any],
                    let name = jsonSlot["name"] as? String else {
                        continue
                }
            
                let value = jsonSlot["value"] as? String
                slots[key] = Slot(name: name, value: value)
            }
        }

        return slots
    }
    
    class func parseIntent(_ jsonRequest: [String: Any]) -> Intent? {
        guard let jsonIntent = jsonRequest["intent"] as? [String: Any],
            let name = jsonIntent["name"] as? String else {
                return nil
        }
        
        let slots = RequestParser.parseSlots(jsonIntent)
        return Intent(name: name, slots: slots)
    }
    
    class func parseReason(_ jsonRequest: [String: Any]) -> Reason? {
        guard let reason = jsonRequest["reason"] as? String else {
            return nil
        }
        
        switch reason {
        case "USER_INITIATED": return .userInitiated
        case "ERROR": return RequestParser.parseError(jsonRequest).map{ .error($0) }
        case "EXCEEDED_MAX_REPROMPTS": return .exceededMaxReprompts
        default: return .unknown
        }
    }
    
    class func parseError(_ jsonRequest: [String: Any]) -> Error? {
        guard let jsonError = jsonRequest["error"] as? [String: Any],
{'fraction_non_alphanumeric': 0.0957983193277311, 'fraction_numerical': 0.0001600640256102441, 'mean_word_length': 2.153962645128723, 'pattern_counts': {'":': 12, '<': 3, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4614852', 'n_tokens_mistral': 3252, 'n_tokens_neox': 3219, 'n_words': 957}