// // 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 = GenerateError.fileNotExists(inputFile) Generate.exit(withError: error) } do { let tagFile = try YAMLDecoder().decode(AnalyticsFile.self, from: data) return tagFile } catch let error { Generate.exit(withError: error) } } private static func getParameters(fromData data: [AnalyticsParameterDTO]) -> [AnalyticsParameter] { var parameters: [AnalyticsParameter] = [] data.forEach { value in // Type let type = value.type.uppercasedFirst() guard type == "String" || type == "Int" || type == "Double" || type == "Bool" else { let error = GenerateError.invalidParameter("type of \(value.name)") Generate.exit(withError: error) } let parameter: AnalyticsParameter = AnalyticsParameter(name: value.name, type: type) if let replaceIn = value.replaceIn { parameter.replaceIn = replaceIn.components(separatedBy: ",") } parameters.append(parameter) } return parameters } private static func getTagDefinition( id: String, name: String, type: AnalyticsDefinition.TagType, tags: String, comments: String?, parameters: [AnalyticsParameterDTO]? ) -> AnalyticsDefinition { let definition: AnalyticsDefinition = AnalyticsDefinition(id: id, name: name, type: type) definition.tags = tags.components(separatedBy: ",") if let comments = comments { definition.comments = comments } if let parameters = parameters { definition.parameters = Self.getParameters(fromData: parameters) } return definition } private static func getTagDefinitionScreen(fromData screens: [AnalyticsDefinitionScreenDTO]) -> [AnalyticsDefinition] { var definitions: [AnalyticsDefinition] = [] for screen in screens { let definition: AnalyticsDefinition = Self.getTagDefinition( id: screen.id, name: screen.name, type: .screen, tags: screen.tags, comments: screen.comments, parameters: screen.parameters ) guard target.contains(Analytics.TargetType.matomo.value) else { continue } // Path guard let path = screen.path else { let error = GenerateError.missingElement("screen path") Generate.exit(withError: error) } definition.path = path definitions.append(definition) } return definitions } private static func getTagDefinitionEvent(fromData events: [AnalyticsDefinitionEventDTO]) -> [AnalyticsDefinition] { var definitions: [AnalyticsDefinition] = [] for event in events { let definition: AnalyticsDefinition = Self.getTagDefinition( id: event.id, name: event.name, type: .event, tags: event.tags, comments: event.comments, parameters: event.parameters ) guard target.contains(Analytics.TargetType.matomo.value) else { continue } // Category guard let category = event.category else { let error = GenerateError.missingElement("event category") Generate.exit(withError: error) } definition.category = category // Action guard let action = event.action else { let error = GenerateError.missingElement("event action") Generate.exit(withError: error) } definition.action = action definitions.append(definition) } return definitions } static func parse(_ inputFile: String, target: String) -> [AnalyticsCategory] { self.inputFile = inputFile self.target = target let tagFile: AnalyticsFile = Self.parseYaml() var sections: [AnalyticsCategory] = [] tagFile.categories.forEach { categorie in let section: AnalyticsCategory = AnalyticsCategory(id: categorie.id) if let screens = categorie.screens { section.definitions.append(contentsOf: Self.getTagDefinitionScreen(fromData: screens)) } if let events = categorie.events { section.definitions.append(contentsOf: Self.getTagDefinitionEvent(fromData: events)) } sections.append(section) } return sections } }