2323 */
2424package dev.shreyaspatil.composeCompilerMetricsGenerator.cli
2525
26+ import dev.shreyaspatil.composeCompilerMetricsGenerator.cli.file.ReportAndMetricsFileFinder
2627import dev.shreyaspatil.composeCompilerMetricsGenerator.core.ComposeCompilerMetricsProvider
28+ import dev.shreyaspatil.composeCompilerMetricsGenerator.core.ComposeCompilerReportFiles
2729import dev.shreyaspatil.composeCompilerMetricsGenerator.generator.HtmlReportGenerator
2830import dev.shreyaspatil.composeCompilerMetricsGenerator.generator.ReportSpec
2931import kotlinx.cli.ArgParser
3032import kotlinx.cli.ArgType
3133import kotlinx.cli.required
3234import java.io.File
3335import java.io.FileNotFoundException
36+ import java.nio.file.Path
3437import java.nio.file.Paths
3538
3639/* *
3740 * Entry point of a CLI application
3841 */
3942fun main (args : Array <String >) {
40- val arguments = CliArguments (args)
43+ val arguments = CliArguments (args, Paths .get( " " ).toAbsolutePath() )
4144
4245 val reportSpec = ReportSpec (arguments.applicationName)
46+ val inputFiles = arguments.getRequiredFiles()
4347
4448 printHeader(" Generating Composable HTML Report" )
4549
4650 val html = HtmlReportGenerator (
4751 reportSpec = reportSpec,
4852 metricsProvider = ComposeCompilerMetricsProvider (
49- briefStatisticsJsonFilePath = arguments.overallStatsFile,
50- detailedStatisticsJsonFilePath = arguments.detailedStatsFile,
51- composableReportFilePath = arguments.composableMetricsFile,
52- classesReportFilePath = arguments.classMetricsFile
53+ ComposeCompilerReportFiles (
54+ briefStatisticsJsonFiles = inputFiles.briefStatisticsJsonFilePath,
55+ detailedStatisticsCsvFiles = inputFiles.detailedStatisticsJsonFilePath,
56+ composableReportFiles = inputFiles.composableReportFilePath,
57+ classesReportFiles = inputFiles.classesReportFilePath
58+ )
5359 )
5460 ).generateHtml()
5561
@@ -83,7 +89,7 @@ fun saveReportAsHtml(htmlContent: String, outputDirectory: String): String {
8389/* *
8490 * Parses and validates CLI arguments
8591 */
86- class CliArguments (args : Array <String >) {
92+ class CliArguments (args : Array <String >, private val path : Path ) {
8793 private val parser = ArgParser (" Compose Compiler Report to HTML Generator ~ ${Constants .VERSION } " )
8894
8995 val applicationName by parser.option(
@@ -92,29 +98,35 @@ class CliArguments(args: Array<String>) {
9298 description = " Application name (To be displayed in the report)"
9399 ).required()
94100
101+ val inputDirectory by parser.option(
102+ ArgType .String ,
103+ shortName = " i" ,
104+ description = " Input directory where composable report and metrics are available"
105+ )
106+
95107 val overallStatsFile by parser.option(
96108 ArgType .String ,
97109 shortName = " overallStatsReport" ,
98- description = " Overall Statistics Metrics JSON file "
99- ).required()
110+ description = " Overall Statistics Metrics JSON files (separated by commas) "
111+ )
100112
101113 val detailedStatsFile by parser.option(
102114 ArgType .String ,
103115 shortName = " detailedStatsMetrics" ,
104- description = " Detailed Statistics Metrics CSV file "
105- ).required()
116+ description = " Detailed Statistics Metrics CSV files (separated by commas) "
117+ )
106118
107119 val composableMetricsFile by parser.option(
108120 ArgType .String ,
109121 shortName = " composableMetrics" ,
110- description = " Composable Metrics TXT file "
111- ).required()
122+ description = " Composable Metrics TXT files (separated by commas) "
123+ )
112124
113125 val classMetricsFile by parser.option(
114126 ArgType .String ,
115127 shortName = " classMetrics" ,
116- description = " Class Metrics TXT file "
117- ).required()
128+ description = " Class Metrics TXT files (separated by commas) "
129+ )
118130
119131 val outputDirectory by parser.option(
120132 ArgType .String ,
@@ -129,28 +141,85 @@ class CliArguments(args: Array<String>) {
129141
130142 require(applicationName.isNotBlank()) { " Application name should not be blank" }
131143 require(outputDirectory.isNotBlank()) { " Output directory path should not be blank" }
144+ }
145+
146+ fun getRequiredFiles (): InputFiles {
147+ val directory = inputDirectory
132148
133- printHeader(" Checking files" )
134- listOf (overallStatsFile, detailedStatsFile, composableMetricsFile, classMetricsFile).forEach { filename ->
135- ensureFileExists(filename) { fileNotExistMessage(filename) }
149+ val files = arrayOf(
150+ overallStatsFile,
151+ detailedStatsFile,
152+ composableMetricsFile,
153+ classMetricsFile
154+ )
155+
156+ if (directory != null ) {
157+ ensureDirectory(directory) { " Directory '$directory ' not exists" }
158+ return findRequiredFilesInDirectory(directory)
159+ } else if (files.all { ! it.isNullOrBlank() }) {
160+ return InputFiles (
161+ briefStatisticsJsonFilePath = files(overallStatsFile!! ),
162+ detailedStatisticsJsonFilePath = files(detailedStatsFile!! ),
163+ composableReportFilePath = files(composableMetricsFile!! ),
164+ classesReportFilePath = files(classMetricsFile!! )
165+ )
166+ } else {
167+ // Assume report and metric files available in the current working directory as specified in the `path`
168+ val defaultDirectory = path.toAbsolutePath().toString()
169+ return findRequiredFilesInDirectory(defaultDirectory)
136170 }
137171 }
138172
139- companion object {
140- fun fileNotExistMessage (filename : String ) = " File not exists with name '$filename '"
173+ private fun findRequiredFilesInDirectory (directory : String ): InputFiles {
174+ val finder = ReportAndMetricsFileFinder (File (Paths .get(directory).toAbsolutePath().toString()))
175+
176+ return InputFiles (
177+ briefStatisticsJsonFilePath = finder.findBriefStatisticsJsonFile(),
178+ detailedStatisticsJsonFilePath = finder.findDetailsStatisticsCsvFile(),
179+ composableReportFilePath = finder.findComposablesReportTxtFile(),
180+ classesReportFilePath = finder.findClassesReportTxtFile()
181+ )
182+ }
183+
184+ private fun files (filenames : String ): List <File > {
185+ return filenames.split(" ," ).map { ensureFileExists(it) { " File not exist: $it " } }
141186 }
187+
188+ /* *
189+ *
190+ */
191+ class InputFiles (
192+ val briefStatisticsJsonFilePath : List <File >,
193+ val detailedStatisticsJsonFilePath : List <File >,
194+ val composableReportFilePath : List <File >,
195+ val classesReportFilePath : List <File >
196+ )
142197}
143198
144199/* *
145200 * Checks whether file with [filename] exists or not. Else throws [FileNotFoundException].
146201 */
147- inline fun ensureFileExists (filename : String , lazyMessage : () -> Any ) {
202+ inline fun ensureFileExists (filename : String , lazyMessage : () -> Any ): File {
148203 val file = File (Paths .get(filename).toAbsolutePath().toString())
149204 println (" Checking file '${file.absolutePath} '" )
150205 if (! file.exists()) {
151206 val message = lazyMessage()
152207 throw FileNotFoundException (message.toString())
153208 }
209+ return file
210+ }
211+
212+ /* *
213+ * Checks whether directory with [name] exists or not.
214+ * Else throws [FileNotFoundException].
215+ */
216+ inline fun ensureDirectory (name : String , lazyMessage : () -> Any ) {
217+ val file = File (Paths .get(name).toAbsolutePath().toString())
218+ println (" Checking directory '${file.absolutePath} '" )
219+ if (! file.isDirectory) {
220+ val message = lazyMessage()
221+ throw FileNotFoundException (message.toString())
222+ }
154223}
155224
156225fun printHeader (header : String ) = println (
@@ -161,5 +230,5 @@ fun printHeader(header: String) = println(
161230)
162231
163232object Constants {
164- const val VERSION = " v1.0.0-alpha02 "
233+ const val VERSION = " v1.0.0-alpha03 "
165234}
0 commit comments