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

org.tresql.compiling.CompilerMetadata.scala Maven / Gradle / Ivy

The newest version!
package org.tresql.compiling

import java.sql._

import org.tresql.Metadata
import org.tresql.metadata.JDBCMetadata

trait CompilerMetadata {
  def metadata: Metadata
  def extraMetadata: Map[String, Metadata]
  def macros: Any
}

/** Implementation must have empty constructor so can be instantiated with {{{Class.newInstance}}} */
trait CompilerMetadataFactory {
  def create(conf: Map[String, String]): CompilerMetadata
}

private[tresql] object MetadataCache {
  def create(
    conf: Map[String, String],
    factory: CompilerMetadataFactory,
    verbose: Boolean
): CompilerMetadata = {
    if (md == null) md = factory match {
      case f: CompilerJDBCMetadataFactory => f.create(conf, verbose)
      case f => f.create(conf)
    } else {
      if (verbose) println(s"Returning cached metadata")
    }
    md
  }
  private[this] var md: CompilerMetadata = null
}

class CompilerJDBCMetadataFactory extends CompilerMetadataFactory {

  case class Conf(driverClassName: String,
                  url: String,
                  user: String,
                  password: String,
                  dbCreateScript: String)

  def create(conf: Map[String, String]): CompilerMetadata = create(conf, false)
  def create(conf: Map[String, String], verbose: Boolean): CompilerMetadata = {
    val macrosClazz = conf.get("macros_class").map(Class.forName)
    val jdbc_metadata = {
      def createMetadata(mdConf: Conf) = {
        import mdConf._
        if (verbose) println(s"Creating database metadata from: $url")

        Class.forName(driverClassName)
        val connection =
          if (user == null) DriverManager.getConnection(url)
          else DriverManager.getConnection(url, user, password)
        if (verbose) println(s"Compiling using jdbc connection: $connection")
        if (dbCreateScript != null) {
          if (verbose) println(s"Creating database for compiler from script $dbCreateScript...")
          new scala.io.BufferedSource(
            Option(this.getClass
              .getResourceAsStream(dbCreateScript))
              .getOrElse(new java.io.FileInputStream(dbCreateScript)))
            .mkString
            .split("//")
            .foreach { sql =>
              val st = connection.createStatement
              st.execute(sql)
              st.close
            }
          if (verbose) println("Success")
        }
        new JDBCMetadata {
          override def conn = connection
          override def macrosClass: Class[_] = macrosClazz.orNull
        }
      }
      def createConf(c: Map[String, String]) = {
        Conf(
          c.getOrElse("jdbc_driver_class" , null),
          c.getOrElse("jdbc_url"          , null),
          c.getOrElse("jdbc_user"         , null),
          c.getOrElse("jdbc_password"     , null),
          c.getOrElse("db_create_script"  , null),
        )
      }
      def param(k: String) = {
        val i = k.indexOf(".")
        if (i == -1) k else k.substring(0, i)
      }
      def db(k: String) = {
        val i = k.indexOf(".")
        if (i == -1) "" else k.substring(i + 1)
      }
      conf
        //.groupMapReduce { case (k, _) => db(k) } { case (k, v) => Map(param(k) -> v) } (_ ++ _) // scala 2.13.x
        .groupBy { case (k, _) => db(k) }
        .mapValues(_.map { case (k, v) => Map(param(k) -> v) }.reduce(_ ++ _))
        .map { case (k, c) => (k, createMetadata(createConf(c))) }
        .toMap
    }

    new CompilerMetadata {
      override def metadata: Metadata = jdbc_metadata("")
      /** Currently no extra metadata are supported */
      override def extraMetadata: Map[String, Metadata] = jdbc_metadata.filterNot(_._1 == "")
      override def macros: Any = {
        macrosClazz.map(_.getDeclaredConstructor().newInstance()).orNull
      }
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy