jrubyの最近のブログ記事
JUDE 5.3には編集APIのサンプルとしてDBリバースのプログラムが付属しています。
サンプルといっても十分便利。DB接続可能なときはこれを利用している。
何かしらのシステムやアプリを引き継ぐと、DDLすら提示されず、「テーブル定義書」「テーブル設計書」といった名称のxlsブックだけ出てくる場合がある。困ったことによくある。
目視でぽちぽちjudeにエントリしてもいいのだけど、編集APIのプラクティスを兼ねてインポートツールを書いた。
要するにCSVで記述したERエンティティをjudeモデルとして一括登録、というもの。
※注意:judeファイルになんらか問題が発生しても責任を負いかねます。自己責任で。そしてバックアップ or リビジョン管理重要。
judeユーティリティ
OS: CentOS 5.2 i386
JRE: Sun Java 1.6.0_07
jruby: 1.1.4
JUDE-Pro: 5.3.0
モデル編集APIは、「図要素」を編集できるようになるとうれしい。図中のモデルの位置だとか大きさ。GUIの自動レイアウトがもうひとつだなぁと感じている。何かしらのレイアウトエンジンを使って独自の整列ができるようになったらかなり素敵だと思うんだけどな。
サンプルといっても十分便利。DB接続可能なときはこれを利用している。
何かしらのシステムやアプリを引き継ぐと、DDLすら提示されず、「テーブル定義書」「テーブル設計書」といった名称のxlsブックだけ出てくる場合がある。困ったことによくある。
目視でぽちぽちjudeにエントリしてもいいのだけど、編集APIのプラクティスを兼ねてインポートツールを書いた。
要するにCSVで記述したERエンティティをjudeモデルとして一括登録、というもの。
※注意:judeファイルになんらか問題が発生しても責任を負いかねます。自己責任で。そしてバックアップ or リビジョン管理重要。
judeユーティリティ
- xlsからCSVを作成する
- 記述例はアーカイブ同梱のsamp1.xlsを参照
- 「テーブル定義書」のレイアウトは様々。それに合わせて以下のようなCSVファイルを出力するようマクロを調整のこと
- 1CSVファイル=1エンティティ
- 1行=1属性
- CSVファイル内の最初の列が「#」で始まる行はメタ情報行
- #@entity行
- 1列目:エンティティの論理名
- 2列目:エンティティの物理名
- 次に#で始まる行は各列の値の意味を指定するヘッダ。認識するヘッダは以下の通り
logicalname 属性の論理名 physicalname 属性の物理名 domain 属性のドメイン(の論理名)
更新対象judeファイル内に同名の論理名を持つドメインがない場合は作成されるtype 属性のデータ型
更新対象judeファイル内に同名のデータ型がない場合は作成されるlength 属性の長さ nn NOT NULLかどうか
非空文字ならNOT NULL指定default 属性のデフォルト値 pk PRIMARY KEY制約をつけるかどうか
非空文字ならPRIMARY KEY指定 - excelがインストールされたwindows上で同梱のmake_csv.jsマクロ実行し、全シートをCSV出力します
- 出力ファイル名は"シート名.csv"になります。
シートごとに別ファイルに出力されます
> cscript.exe make_csv.js samp1.xls - 編集APIの仕様で以下の点に注意
- 論理名のないエンティティは登録できない
- 論理名のない属性は登録できない
- 同じ論理名を持つエンティティが既に存在すると登録できない
- データ型に英小文字を指定しても英大文字になる
- GUIでは英小文字名称のデータ型を登録できるけど、編集APIでcreateすると大文字になる。
- 出来たCSVをjudeファイルにインポートする
- 実行例
※インポートのデフォルトのフィールド区切りは「HT」です。--fsでカンマを指定しています。
$ env CLASSPATH=./jude-pro.jar jruby ./import_ermodel.rb --fs=, -o new.jude samp2.csv
※jude-pro.jarがカレントにある前提 - 存在しないjudeファイルを指定してもよいし、既存のjudeファイルを指定してもよいです。
存在しないjudeファイルを指定するとjudeファイルが作成されます。
新規judeファイルに出力しインポート後の内容を確認して問題なさそうならマージするという手順がいいと思う。 - 本スクリプトは日本語環境で作成されたjudeファイルを前提としています。
編集APIサンプルのように createERModel(project, "ER Model");でIERModelを作成すると、日本語環境GUIでマージできなかった。日本語環境GUIで作ったjudeファイルの場合、IERModelの名称が"ERモデル"(これはエクスポートするとわかる)となっていることに関係するのではないかと想像している。
OS: CentOS 5.2 i386
JRE: Sun Java 1.6.0_07
jruby: 1.1.4
JUDE-Pro: 5.3.0
モデル編集APIは、「図要素」を編集できるようになるとうれしい。図中のモデルの位置だとか大きさ。GUIの自動レイアウトがもうひとつだなぁと感じている。何かしらのレイアウトエンジンを使って独自の整列ができるようになったらかなり素敵だと思うんだけどな。
モデリングツールにJUDEを利用している。
このツールを選んだポイントの1つはjavaを使ったAPIがあること。
5.3になって、モデル編集のAPIも追加された。
で、テーブル設計。
過去に「楽々ERDレッスン (CodeZine BOOKS) 」を読み、「Identifier」の有用さに心打たれて以来、いつもID列を設けるようにしている。
要求・要望・要件の断片からざっとエンティティを見出し、ID属性を付与、リレーションを付けて多重度を設定して・・・という手順でやっているのだけど、エンティティの数が多いと、ID属性を追加するのも結構手間。。。。
ということで、モデル編集APIを扱うプラクティスも兼ねて、JUDEプロジェクト内のERエンティティにID属性を追加するスクリプトを書いてみた。
judeユーティリティ
ちょこちょことスクリプトを書くときは、screen+viな環境でやると調子がいい(僕は)。なので、linux上でしか確認してない。
■実行環境
OS: CentOS 5.2 i386
JRE: Sun Java 1.6.0_05
jruby: 1.1.3
JUDE-Pro: 5.3.0
■実行例
アーカイブを展開し、jude-pro.jarを展開先ディレクトリに置いてある前提。
○ERエンティティ、「ID」という論理名でSMALLINT型の属性を追加する
○ERエンティティに、「ID」という名前・INT型のERドメインで、「ID」という論理名の属性を追加する
○ERエンティティに、「ID」という名前・SMALLINT型のERドメインで、「エンティティ論理名_ID」という論理名の属性を追加する
作成された属性にはPK指定が付きます
■注意
このツールを選んだポイントの1つはjavaを使ったAPIがあること。
5.3になって、モデル編集のAPIも追加された。
で、テーブル設計。
過去に「楽々ERDレッスン (CodeZine BOOKS) 」を読み、「Identifier」の有用さに心打たれて以来、いつもID列を設けるようにしている。
要求・要望・要件の断片からざっとエンティティを見出し、ID属性を付与、リレーションを付けて多重度を設定して・・・という手順でやっているのだけど、エンティティの数が多いと、ID属性を追加するのも結構手間。。。。
ということで、モデル編集APIを扱うプラクティスも兼ねて、JUDEプロジェクト内のERエンティティにID属性を追加するスクリプトを書いてみた。
judeユーティリティ
ちょこちょことスクリプトを書くときは、screen+viな環境でやると調子がいい(僕は)。なので、linux上でしか確認してない。
■実行環境
OS: CentOS 5.2 i386
JRE: Sun Java 1.6.0_05
jruby: 1.1.3
JUDE-Pro: 5.3.0
■実行例
アーカイブを展開し、jude-pro.jarを展開先ディレクトリに置いてある前提。
○ERエンティティ、「ID」という論理名でSMALLINT型の属性を追加する
% env CLASSPATH=./jude-pro.jar jruby add_identifier.rb --attr-name=ID --datatype=SMALLINT judeファイルのパス
○ERエンティティに、「ID」という名前・INT型のERドメインで、「ID」という論理名の属性を追加する
% env CLASSPATH=./jude-pro.jar jruby add_identifier.rb --attr-name=ID --domain=ID judeファイルのパス
○ERエンティティに、「ID」という名前・SMALLINT型のERドメインで、「エンティティ論理名_ID」という論理名の属性を追加する
% env CLASSPATH=./jude-pro.jar jruby add_identifier.rb --attr-name=%e_ID --domain=ID --domain-datatype=SMALLINT judeファイルのパス指定したデータ型、ドメインが存在しない場合は作成します。
作成された属性にはPK指定が付きます
■注意
- READMEにも書いてありますが無保証です
- judeファイルを書き換えますので、バックアップ必須です。ファイルが壊れても責任持てません。
- (JUDEの機能による)ロックがかかりますので、更新対象JUDEファイルをGUIで編集していない状態で実行します
- 既に主キーがついているエンティティには属性追加しません。
- 唯一の主キーが作成しようとしてる属性論理名が同じ場合はデータ型/ドメインを更新します
- 既にERモデルが作成されているJUDEファイル前提です。日本語環境以外で作成されたものがどうなるかは不明です。
以前、libxml-rubyで [BUG] object allocation during garbage collection phase で、元々libxml-rubyを使って書いてたコードをjavaのDOM/XPath APIに置き換えるために、ラッパを書いた。
のだけど、
「JRuby徹底入門」という本を読んだら、javaのクラス(のproxy)にメソッドを後付けするにはJavaUtilities.extend_proxyを使う、という例が載ってた。
なるほど便利。
なんでも実行時に決定できるってすごいことだな。
jruby:1.1.3
Sun Java: 1.6.0_05
OS:CentOS 5.2
$KCODE='u'
require 'java'
# org.w3c.dom.Documentにlibxml-ruby風I/F追加
JavaUtilities.extend_proxy('org.w3c.dom.Document') do
def root
self.documentElement
end
end
# org.w3c.dom.Nodeにlibxml-ruby風I/F追加
JavaUtilities.extend_proxy('org.w3c.dom.Node') do
@@xpath = nil
def to_s
self.nodeValue.to_s
end
def next
self.nextSibling
end
def text?
self.nodeType == org.w3c.dom.Node::TEXT_NODE
end
def [](name)
self.getAttribute(name)
end
def parent
self.parentNode
end
def child
self.firstChild
end
# XPathオブジェクトを返す
#
# TODO: XPathオブジェクト1つで使いまわしてみたが・・・
# evaluateの都度生成よりはいいような気がするがどうだろう
def get_xpath
if !@@xpath
factory = javax.xml.xpath.XPathFactory.newInstance()
@@xpath = factory.newXPath()
end
@@xpath
end
# 指定されたノードに対するxpath式のクエリ結果を返す
#
# expr::
# XPath式
def find(expr)
nodelist = self.get_xpath.evaluate(expr, self, javax.xml.xpath.XPathConstants::NODESET)
ret = []
for i in 0..(nodelist.length - 1)
ret.push(nodelist.item(i))
end
ret
end
end
# 指定されたファイルをopenしてXML文書を返す
#
# fn_in::
# ファイル名。nilの場合、stdinを適用
def build_doc(fn_in)
st = java.lang.System.in
if fn_in
st = java.io.FileInputStream.new(fn_in)
end
factory = javax.xml.parsers.DocumentBuilderFactory.newInstance()
builder = factory.newDocumentBuilder()
builder.parse(st)
end
doc = build_doc("test.xml")
doc.find("//entity").each { |e|
puts e["name"]
}

