Groovyで、テーブル一覧、テーブル定義をHTML出力してみる2
前回作成した Groovyで、テーブル一覧、テーブル定義をHTML出力してみる の改良版。
もう少しテーブル定義を見やすくしてみました。
- 左側にテーブル一覧が表示される
- 右側にテーブル定義が表示される
- テーブル一覧、テーブル定義それぞれ日本語名称を表示できる
- 簡単なSelect SQLを作ってくれる
ソースは以下のとおり。
MarkupBuilder拡張クラス
#!/usr/bin/env groovy
/**
* @author genzou
*/
class XhtmlBuilder extends groovy.xml.MarkupBuilder {
def charset = "UTF8"
def lang = "ja"
def title = ""
def cssList = ["style.css"]
public XhtmlBuilder(map, writer) {
super(writer)
map.keySet().each {
this."$it" = map."$it"
}
}
def body = { closure ->
delegate.print("""n""")
delegate.print("""n""")
html(lang: "${this.lang}", "xml:lang": "${this.lang}") {
head() {
meta("http-equiv": "Content-Type", content: "text/html;charset=${this.charset}")
meta("http-equiv": "Content-Style-Type", content: "text/css;charset=${this.charset}")
title("${this.title}")
cssList.each {
link(rel: "stylesheet", href: it)
}
}
body closure
}
}
}
日本語名称マッパークラス
#!/usr/bin/env groovy
/**
* @author genzou
*/
public class Mapper {
// テーブルID(大文字)と日本語名称の対応を記述(IDがキー)
public static def tables = [:]
// カラムID(大文字)と日本語名称の対応を記述(IDがキー)
public static def columns = [:]
}
メイン処理
#!/usr/bin/env groovy
def props = [
user : "ゆーざーめい!",
password: "ぱすわーど!",
] as Properties
def url = "JDBCのURL!"
def driver = "てきとうなどらいば!"
def dir = new File("entities")
if (!dir.exists() || dir.file)
dir.mkdirs()
def gsql
try {
gsql = Sql.newInstance(
url
, props
, driver)
def rs = gsql.connection.metaData.getColumns(null, props.user, "%", "%")
def rows = []
while (rs.next()) {
rows << rs.toRowResult()
}
rs.close()
def entities = rows.groupBy { it.TABLE_NAME }.findAll { !(it.key =~ /.*BIN$.*/) }
println entities
// 出力処理
new File("$dir/index.html").withWriter("UTF8") {
new XhtmlBuilder(it, title: "テーブル定義").body() {
div(class: "container") {
div(class: "left") {
h2("テーブル一覧")
table() {
tr() {
th "ID"
th "名称"
}
def i = 0
entities.keySet().sort().each { tableName ->
tr('class': (i++ % 2) ? "odd" : "") {
td() {
a(href: "${tableName}.html", tableName)
}
td Mapper.tables[tableName]
}
}
}
}
div(class: "right") {
}
}
}
}
entities.each { entity ->
def columns = entity.value
new File("$dir/${entity.key}.html").withWriter("UTF8") {
new XhtmlBuilder(it, title: "テーブル定義 - ${entity.key}").body() {
div(class: "container") {
div(class: "left") {
h2("テーブル一覧")
table() {
tr() {
th "ID"
th "名称"
}
def i = 0
entities.keySet().sort().each { tableName ->
tr('class': (i++ % 2) ? "odd" : "") {
td() {
a(href: "${tableName}.html", tableName)
}
td Mapper.tables[tableName]
}
}
}
}
div(class: "right") {
h1 "テーブル定義"
h2 "ID"
p "${entity.key}"
h2 "名称"
p "${Mapper.tables[entity.key]}"
h2 "カラム情報"
table() {
tr() {
th "ID"
th "名称"
th "型"
th "サイズ"
th "NOT NULL"
}
def i = 0
columns.each { column ->
tr('class': (i++ % 2) ? "odd" : "") {
td column.COLUMN_NAME
td(Mapper.columns[column.COLUMN_NAME])
td column.TYPE_NAME
td(class: "num", column.COLUMN_SIZE)
td(column.IS_NULLABLE?.toString())
}
}
}
h2 "sql"
def sql = """
SELECT
*
FROM
${entity.key}
-- WHERE""" + columns.collect { "n-- " + it.COLUMN_NAME + " = '' " }.join("AND")
textarea(sql)
}
}
}
}
}
} finally {
gsql?.close()
}
new File("$dir/style.css").write("""
div.container
{
width:99%;
}
h2
{
border:2px solid gray;
border-left:10px solid gray;
padding-left:20px;
}
body
{
background-color:#fbfbfb;
}
div.left
{
float:left;
width:30%;
border-right:2px double gray;
padding-right:0;
margin-right:5px;
height:800px;
overflow:scroll;
}
div.left table
{
font-size:75%;
}
div.right
{
width: 65%;
float:left;
}
div.right p
{
padding-left:40px;
}
div.left td
{
word-break:break-all;
word-wrap:break-word;
}
div.right th,div.right td
{
white-space:nowrap;
}
table
{
width:90%;
border:2px solid gray;
border-collapse:collapse;
margin:1px auto;
}
tr th
{
background:#d7dbff;
}
th,td
{
border-bottom:1px solid #c5cfc8;
border-left:1px solid #e5eff8;
padding:1px;
}
tr.odd td
{
background:#f7fbe0;
}
textarea{
width: 450px;
height:200px;
} """, "UTF8")
結構長くなってしまった。
わからなかったこと1
MarkupBuilderの拡張クラスとしてXhtmlBuilderというクラスを作成したけれども、 body というクロージャを作成しそいつを呼び出したときにbuilder処理が行われる作りにしたけれども、 body ではなく任意のメソッド名でも実行されるようにしたかった。
わからなかったこと2
index.htmlとエンティティ名.htmlの両方で、左側のテーブル一覧出力処理は同じにも関わらず、同一の処理を記述している。
ここをうまいこと共通化できないものかなぁ。
作ってみてよかったこと
すごくビルダーの勉強になった。
ちなみにアンカー出力の処理は以下のような記述方法があるみたい。
a(href:"url"){ yield "テキスト" }
a(href:"url", "テキスト")
いずれも テキスト
になるぽい。
ディスカッション
コメント一覧
まだ、コメントがありません