// // AnalyticsFileParser.swift // // // Created by Loris Perret on 06/12/2023. // import Foundation import Yams class AnalyticsFileParser { private static var inputFile: String = "" private static var target: String = "" private static func parseYaml() -> AnalyticsFile { guard let data = FileManager().contents(atPath: inputFile) else { let error = AnalyticsError.fileNotExists(inputFile) print(error.description) Analytics.exit(withError: error) } do { let tagFile = try YAMLDecoder().decode(AnalyticsFile.self, from: data) return tagFile } catch let error { print(error.description) Analytics.exit(withError: error) } } private static func getParameters(from parameters: [AnalyticsParameterDTO]) -> [AnalyticsParameter] { parameters.map { dtoParameter in // Type let type = value.type.uppercasedFirst() guard type == "String" || type == "Int" || type == "Double" || type == "Bool" else { let error = AnalyticsError.invalidParameter("type of \(value.name)") print(error.description) Analytics.exit(withError: error) } let parameter = AnalyticsParameter( name: dtoParameter.name, type: type ) if let replaceIn = dtoParameter.replaceIn { parameter.replaceIn = replaceIn.components(separatedBy: ",") } return parameter } } private static func getTagDefinition( id: String, name: String, type: AnalyticsDefinition.TagType, tags: String, comments: String?, parameters: [AnalyticsParameterDTO]? ) -> AnalyticsDefinition { let definition = AnalyticsDefinition(id: id, name: name, type: type) definition.tags = tags .components(separatedBy: ",") .map { $0.removeLeadingTrailingWhitespace() } if let comments = comments { definition.comments = comments } if let parameters = parameters { definition.parameters = Self.getParameters(from: parameters) } return definition } private static func getTagDefinitionScreen(from screens: [AnalyticsDefinitionScreenDTO]) -> [AnalyticsDefinition] { screens.map { screen in let definition: AnalyticsDefinition = Self.getTagDefinition( id: screen.id, name: screen.name, type: .screen, tags: screen.tags, comments: screen.comments, parameters: screen.parameters ) if target.contains(Analytics.TargetType.matomo.value) { // Path guard let path = screen.path else { let error = AnalyticsError.missingElement("screen path") print(error.description) Analytics.exit(withError: error) } definition.path = path } return definition } } private static func getTagDefinitionEvent(from events: [AnalyticsDefinitionEventDTO]) -> [AnalyticsDefinition] { events.map { event in let definition: AnalyticsDefinition = Self.getTagDefinition( id: event.id, name: event.name, type: .event, tags: event.tags, comments: event.comments, parameters: event.parameters ) if target.contains(Analytics.TargetType.matomo.value) { // Category guard let category = event.category else { let error = AnalyticsError.missingElement("event category") print(error.description) Analytics.exit(withError: error) } definition.category = category // Action guard let action = event.action else { let error = AnalyticsError.missingElement("event action") print(error.description) Analytics.exit(withError: error) } definition.action = action } return definition } } static func parse(_ inputFile: String, target: String) -> [AnalyticsCategory] { self.inputFile = inputFile self.target = target let tagFile = Self.parseYaml() return tagFile .categories .map { categorie in let section: AnalyticsCategory = AnalyticsCategory(id: categorie.id) if let screens = categorie.screens { section .definitions .append( contentsOf: Self.getTagDefinitionScreen(from: screens) ) } if let events = categorie.events { section .definitions .append( contentsOf: Self.getTagDefinitionEvent(from: events) ) } return section } } }