Created
December 24, 2013 09:36
-
-
Save Arakaki/8110863 to your computer and use it in GitHub Desktop.
Skinny reverse engineer task support.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package skinny.task.generator | |
import scalikejdbc.config.{ DBsWithEnv, TypesafeConfigReaderWithEnv } | |
import scalikejdbc._ | |
import java.sql.{ Types => JavaSqlTypes } | |
import scalikejdbc.mapper._ | |
import java.util.Locale.{ ENGLISH => en } | |
object ReverseEngineering extends ReverseEngineering | |
/** | |
* Reverse Engineering Task. | |
*/ | |
trait ReverseEngineering { | |
private[this] def showUsage = { | |
println(""" Usage: sbt "task/run db:reverse_engineering env db_name scheme table_name view_template_name resources resource" """) | |
println("") | |
} | |
def run(args: List[String]) { | |
args match { | |
case env :: dbName :: scheme :: tableName :: viewTemplate :: resources :: resource :: Nil => scaffold(env, dbName, scheme, tableName, viewTemplate, resources, resource) | |
case env :: dbName :: scheme :: tableName :: resources :: resource :: Nil => scaffold(env, dbName, scheme, tableName, "ssp", resources, resource) | |
case _ => showUsage | |
} | |
} | |
def scaffold(env: String, dbName: String, scheme: String, tableName: String, viewTemplate: String, resources: String, resource: String) { | |
val settings = loadDbSettings(env, dbName) | |
settings match { | |
case Some(settings) => | |
Class.forName(settings.driverName) | |
val model = Model(settings.url, settings.user, settings.password) | |
val table = model.table(scheme, tableName).orElse(None) | |
table match { | |
case Some(table) => | |
val params = (resources :: resource :: Nil) ++ columnParameter(table) | |
viewTemplate match { | |
case "ssp" => ScaffoldSspGenerator.run(params) | |
case "scaml" => ScaffoldScamlGenerator.run(params) | |
case "jade" => ScaffoldJadeGenerator.run(params) | |
case _ => showUsage | |
} | |
case None => showUsage | |
} | |
case None => showUsage | |
} | |
} | |
def columnParameter(table: Table) = { | |
table.allColumns.map { column => | |
val columnInScala = ColumnInScala(column) | |
s"${columnInScala.nameInScala}:${columnInScala.typeInScala}" | |
} | |
} | |
def loadDbSettings(env: String, dbName: String): Option[JDBCSettings] = { | |
DBsWithEnv(env).setupAll() | |
if (!TypesafeConfigReaderWithEnv(env).dbNames.isEmpty) { | |
Some(TypesafeConfigReaderWithEnv(env).readJDBCSettings(Symbol(dbName))) | |
} else { | |
None | |
} | |
} | |
case class ColumnInScala(underlying: Column) { | |
lazy val nameInScala: String = { | |
val camelCase: String = toCamelCase(underlying.name) | |
camelCase.head.toLower + camelCase.tail | |
} | |
private def toCamelCase(s: String): String = s.split("_").toList.foldLeft("") { | |
(camelCaseString, part) => | |
camelCaseString + toProperCase(part) | |
} | |
private def toProperCase(s: String): String = { | |
if (s == null || s.trim.size == 0) "" | |
else s.substring(0, 1).toUpperCase(en) + s.substring(1).toLowerCase(en) | |
} | |
object TypeName { | |
val Any = "Any" | |
val AnyArray = "Array[Any]" | |
val ByteArray = "Array[Byte]" | |
val Long = "Long" | |
val Boolean = "Boolean" | |
val DateTime = "DateTime" | |
val LocalDate = "LocalDate" | |
val LocalTime = "LocalTime" | |
val String = "String" | |
val Byte = "Byte" | |
val Int = "Int" | |
val Short = "Short" | |
val Float = "Float" | |
val Double = "Double" | |
val Blob = "Blob" | |
val Clob = "Clob" | |
val Ref = "Ref" | |
val Struct = "Struct" | |
val BigDecimal = "BigDecimal" // scala.math.BigDecimal | |
} | |
lazy val rawTypeInScala: String = underlying.dataType match { | |
case JavaSqlTypes.ARRAY => TypeName.AnyArray | |
case JavaSqlTypes.BIGINT => TypeName.Long | |
case JavaSqlTypes.BINARY => TypeName.ByteArray | |
case JavaSqlTypes.BIT => TypeName.Boolean | |
case JavaSqlTypes.BLOB => TypeName.Blob | |
case JavaSqlTypes.BOOLEAN => TypeName.Boolean | |
case JavaSqlTypes.CHAR => TypeName.String | |
case JavaSqlTypes.CLOB => TypeName.Clob | |
case JavaSqlTypes.DATALINK => TypeName.Any | |
case JavaSqlTypes.DATE => TypeName.LocalDate | |
case JavaSqlTypes.DECIMAL => TypeName.BigDecimal | |
case JavaSqlTypes.DISTINCT => TypeName.Any | |
case JavaSqlTypes.DOUBLE => TypeName.Double | |
case JavaSqlTypes.FLOAT => TypeName.Float | |
case JavaSqlTypes.INTEGER => TypeName.Int | |
case JavaSqlTypes.JAVA_OBJECT => TypeName.Any | |
case JavaSqlTypes.LONGVARBINARY => TypeName.ByteArray | |
case JavaSqlTypes.LONGVARCHAR => TypeName.String | |
case JavaSqlTypes.NULL => TypeName.Any | |
case JavaSqlTypes.NUMERIC => TypeName.BigDecimal | |
case JavaSqlTypes.OTHER => TypeName.Any | |
case JavaSqlTypes.REAL => TypeName.Float | |
case JavaSqlTypes.REF => TypeName.Ref | |
case JavaSqlTypes.SMALLINT => TypeName.Short | |
case JavaSqlTypes.STRUCT => TypeName.Struct | |
case JavaSqlTypes.TIME => TypeName.LocalTime | |
case JavaSqlTypes.TIMESTAMP => TypeName.DateTime | |
case JavaSqlTypes.TINYINT => TypeName.Byte | |
case JavaSqlTypes.VARBINARY => TypeName.ByteArray | |
case JavaSqlTypes.VARCHAR => TypeName.String | |
case _ => TypeName.Any | |
} | |
lazy val typeInScala: String = { | |
if (underlying.isNotNull) rawTypeInScala | |
else "Option[" + rawTypeInScala + "]" | |
} | |
lazy val extractorName: String = underlying.dataType match { | |
case JavaSqlTypes.ARRAY => "array" | |
case JavaSqlTypes.BIGINT => "long" | |
case JavaSqlTypes.BINARY => "bytes" | |
case JavaSqlTypes.BIT => "boolean" | |
case JavaSqlTypes.BLOB => "blob" | |
case JavaSqlTypes.BOOLEAN => "boolean" | |
case JavaSqlTypes.CHAR => "string" | |
case JavaSqlTypes.CLOB => "clob" | |
case JavaSqlTypes.DATALINK => "any" | |
case JavaSqlTypes.DATE => "date" | |
case JavaSqlTypes.DECIMAL => "bigDecimal" | |
case JavaSqlTypes.DISTINCT => "any" | |
case JavaSqlTypes.DOUBLE => "double" | |
case JavaSqlTypes.FLOAT => "float" | |
case JavaSqlTypes.INTEGER => "int" | |
case JavaSqlTypes.JAVA_OBJECT => "any" | |
case JavaSqlTypes.LONGVARBINARY => "bytes" | |
case JavaSqlTypes.LONGVARCHAR => "string" | |
case JavaSqlTypes.NULL => "any" | |
case JavaSqlTypes.NUMERIC => "bigDecimal" | |
case JavaSqlTypes.OTHER => "any" | |
case JavaSqlTypes.REAL => "float" | |
case JavaSqlTypes.REF => "ref" | |
case JavaSqlTypes.SMALLINT => "short" | |
case JavaSqlTypes.STRUCT => "any" | |
case JavaSqlTypes.TIME => "time" | |
case JavaSqlTypes.TIMESTAMP => "timestamp" | |
case JavaSqlTypes.TINYINT => "byte" | |
case JavaSqlTypes.VARBINARY => "bytes" | |
case JavaSqlTypes.VARCHAR => "string" | |
case _ => "any" | |
} | |
} | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package skinny.task | |
import skinny.task.generator._ | |
import skinny.dbmigration.DBMigration | |
import skinny.SkinnyEnv | |
/** | |
* Task launcher. | |
*/ | |
object TaskLauncher { | |
/** | |
* Registered tasks. | |
*/ | |
private[this] val tasks = new scala.collection.mutable.HashMap[String, (List[String]) => Unit] | |
// built-in tasks | |
register("generate:controller", (params) => ControllerGenerator.run(params)) | |
register("generate:model", (params) => ModelGenerator.run(params)) | |
register("generate:migration", (params) => DBMigrationFileGenerator.run(params)) | |
register("generate:scaffold", (params) => ScaffoldSspGenerator.run(params)) | |
register("generate:scaffold:ssp", (params) => ScaffoldSspGenerator.run(params)) | |
register("generate:scaffold:scaml", (params) => ScaffoldScamlGenerator.run(params)) | |
register("generate:scaffold:jade", (params) => ScaffoldJadeGenerator.run(params)) | |
register("db:migrate", { | |
case env :: dbName :: rest => DBMigration.migrate(env, dbName) | |
case params => DBMigration.migrate(params.headOption.getOrElse(SkinnyEnv.Development)) | |
}) | |
register("db:reverse_engineering", (params) => ReverseEngineering.run(params)) | |
def register(name: String, runner: (List[String]) => Unit) = tasks.update(name, runner) | |
def showUsage = { | |
println( | |
s""" | |
| Usage: sbt "task/run [task] [options...] | |
| | |
|${tasks.map(t => " " + t._1).mkString("\n")} | |
| | |
|""".stripMargin) | |
} | |
def main(args: Array[String]) { | |
args.toList match { | |
case name :: parameters => | |
tasks.get(name).map(_.apply(parameters)).getOrElse(println(s"Task for ${name} not found.")) | |
case _ => showUsage | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment