Skip to content

Instantly share code, notes, and snippets.

@TAJD
Created May 8, 2023 19:55
Show Gist options
  • Save TAJD/a5e25500ea9db9555c4d2b30433bfd23 to your computer and use it in GitHub Desktop.
Save TAJD/a5e25500ea9db9555c4d2b30433bfd23 to your computer and use it in GitHub Desktop.
package org.tajd
package metaprogramming
import java.nio.file.{Files, Path, Paths}
import org.scalafmt.interfaces.Scalafmt
import scala.jdk.CollectionConverters._
import scala.meta.{Term, _}
import scala.util.Try
object CreateACaseClass extends App {
private case class ColumnSpecification(
colName: String,
colType: String
)
private case class CaseClass(
name: String,
fields: Seq[ColumnSpecification]
)
private case class ScalaFile(
name: String,
filePath: Path,
scalaCode: Source
)
private def createFields(fields: Seq[ColumnSpecification]): Seq[Term.Param] =
for {
field <- fields
} yield Term.Param(
Nil,
Term.Name(field.colName),
Some(Type.Name(field.colType)),
None
)
private def generateCode(caseClass: CaseClass): Source = {
val packageName =
Term.Select(Term.Name("metaprogramming"), Term.Name("generatedCode"))
val name = Type.Name(caseClass.name)
val fields = List(createFields(caseClass.fields).toList)
val parameters = Ctor.Primary(
Nil,
Name(""),
fields
)
val template = Template(Nil, Nil, Self(Name(""), None), Nil, Nil)
Source(
List(
Pkg(
packageName,
List(
Defn.Class(
List(Mod.Final(), Mod.Case()),
name,
Nil,
parameters,
template
)
)
)
)
)
}
private def readFile(filePath: Path): Seq[String] =
Files.readAllLines(Paths.get(filePath.toUri)).asScala.toSeq
private def writeScalaFile(scalaFile: ScalaFile): Try[Unit] = {
val path: Path = scalaFile.filePath.resolve(scalaFile.name ++ ".scala")
val rawContent = scalaFile.scalaCode.syntax
val config =
Paths.get(".scalafmt.conf")
val formattedContent = Scalafmt.create(this.getClass.getClassLoader).format(config, path, rawContent)
for {
_ <- Try(Files.createDirectories(path.getParent))
_ <- Try(Files.write(path, formattedContent.getBytes))
} yield ()
}
private def getDataSourceSpec(lines: Seq[String]): Seq[ColumnSpecification] =
for {
line <- lines
} yield {
val values = line.split(",")
ColumnSpecification(values(0), values(1))
}
private def generateCaseClassFile(filePath: String): Unit = {
val path = Paths.get(filePath)
val fileName = path.getFileName.toString
.replace(".csv", "")
val lines = readFile(path)
val dataSourceSpecification = getDataSourceSpec(lines)
val caseClassDefinition = CaseClass(
fileName,
dataSourceSpecification
)
val generatedClassAst = generateCode(caseClassDefinition)
val scalaFilePreGeneration = ScalaFile(
name = fileName,
filePath = path.getParent,
scalaCode = generatedClassAst
)
writeScalaFile(scalaFilePreGeneration)
}
generateCaseClassFile(
"""C:\Users\User\IdeaProjects\scalaSnippets\data\testData.csv"""
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment