All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.goyeau.mill.avro.AvroModule.scala Maven / Gradle / Ivy

package com.goyeau.mill.avro

import avrohugger.Generator
import avrohugger.filesorter.{AvdlFileSorter, AvscFileSorter}
import avrohugger.format.Standard
import avrohugger.format.abstractions.SourceFormat
import avrohugger.types.AvroScalaTypes
import java.io.File
import java.util.UUID
import mill.*
import mill.api.PathRef
import mill.scalalib.ScalaModule
import mill.scalalib.api.ZincWorkerUtil.scalaBinaryVersion
import os.Path
import upickle.default.ReadWriter

trait AvroModule extends ScalaModule {
  implicit def sourceFormatRW[F <: SourceFormat]: ReadWriter[F] = upickle.default
    .readwriter[String]
    .bimap[F](_ => UUID.randomUUID().toString, _ => ???)
  implicit val avroScalaTypesRW: ReadWriter[AvroScalaTypes] = upickle.default
    .readwriter[String]
    .bimap[AvroScalaTypes](_ => UUID.randomUUID().toString, _ => ???)

  def avroSources: T[Seq[PathRef]]                     = T.sources(millSourcePath / "avro")
  def avroScalaCustomNamespace: T[Map[String, String]] = Map.empty[String, String]
  def avroScalaFormat: T[SourceFormat]                 = Standard
  def avroScalaCustomTypes: T[AvroScalaTypes]          = avroScalaFormat().defaultTypes

  override def generatedSources: T[Seq[PathRef]] = super.generatedSources() :+ generateScalaFromAvro(
    Generator(
      format = avroScalaFormat(),
      avroScalaCustomTypes = Some(avroScalaCustomTypes()),
      avroScalaCustomNamespace = avroScalaCustomNamespace(),
      targetScalaPartialVersion = scalaBinaryVersion(scalaVersion())
    ),
    avroSources(),
    T.dest / "avro"
  )

  private def generateScalaFromAvro(generator: Generator, avroSources: Seq[PathRef], out: Path) = {
    AvscFileSorter.sortSchemaFiles(filesFor(avroSources, "avsc")).foreach { avroFile =>
      println(s"Generating case classes from AVSC $avroFile")
      generator.fileToFile(avroFile, out.toString)
    }

    AvdlFileSorter.sortSchemaFiles(filesFor(avroSources, "avdl")).foreach { avroFile =>
      println(s"Generating case classes from Avro IDL $avroFile")
      generator.fileToFile(avroFile, out.toString)
    }

    filesFor(avroSources, "avro").foreach { avroFile =>
      println(s"Compiling case classes from Avro datafile $avroFile")
      generator.fileToFile(avroFile, out.toString)
    }

    filesFor(avroSources, "avpr").foreach { avroFile =>
      println(s"Compiling case classes from Avro protocol $avroFile")
      generator.fileToFile(avroFile, out.toString)
    }

    PathRef(out)
  }

  private def filesFor(sources: Seq[PathRef], extension: String): Seq[File] =
    for {
      path <- sources.map(_.path)
      if os.exists(path)
      file <-
        if (os.isDir(path)) os.walk(path).filter(file => os.isFile(file) && (file.ext == extension))
        else Seq(path)
    } yield file.toIO
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy