Created
April 1, 2011 04:17
-
-
Save monzou/897719 to your computer and use it in GitHub Desktop.
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 scripts; | |
import org.apache.poi.hssf.usermodel.HSSFCellStyle | |
import org.apache.poi.hssf.usermodel.HSSFFont | |
import org.apache.poi.hssf.usermodel.HSSFRichTextString | |
import org.apache.poi.hssf.usermodel.HSSFWorkbook | |
import org.apache.poi.ss.usermodel.CellStyle | |
import org.apache.poi.ss.usermodel.IndexedColors | |
/** | |
* usage: ReverseHbmToEntityExcel [target.dir] [dist.path] | |
* | |
* @author monzou | |
*/ | |
class Utils { | |
static def prop(self, path, name) { | |
def p = path["@${name}"] | |
p == "" ? null : p | |
} | |
static def exp(self, path, name, prefix="") { | |
def p = prop(self, path, name) | |
p == null ? null : "${prefix}${name}: ${p}" | |
} | |
static def append(self, s1, s2, junction="") { | |
s2 == null ? s1 : (s1 + junction + s2) | |
} | |
} | |
@Mixin(Utils) | |
class IdentifierProperty { | |
private path | |
def type() { | |
prop(path, "type") | |
} | |
def name() { | |
prop(path, "name") | |
} | |
def remarks() { | |
def remarks = prop(path, "column").text() | |
append(remarks, exp(path.generator, "class", "\ngenerator.")) | |
} | |
} | |
@Mixin(Utils) | |
class SimpleProperty { | |
private path | |
def type() { | |
prop(path, "type") | |
} | |
def name() { | |
prop(path, "name") | |
} | |
def remarks() { | |
prop(path, "column").text() | |
} | |
} | |
@Mixin(Utils) | |
class OneToOneProperty { | |
private path | |
def type() { | |
prop(path, "class") | |
} | |
def name() { | |
prop(path, "name") | |
} | |
def remarks() { | |
def remarks = "one-to-one" | |
remarks = append(remarks, exp(path, "cascade"), "\n") | |
remarks = append(remarks, exp(path, "outer-join"), "\n") | |
remarks = append(remarks, exp(path, "lazy"), "\n") | |
remarks = append(remarks, exp(path, "property-ref"), "\n") | |
remarks = append(remarks, exp(path, "constrained"), "\n") | |
remarks = append(remarks, exp(path.column, "name", "\njoinColumn.")) | |
} | |
} | |
@Mixin(Utils) | |
class ManyToOneProperty { | |
private path | |
def type() { | |
prop(path, "class") | |
} | |
def name() { | |
prop(path, "name") | |
} | |
def remarks() { | |
def remarks = "many-to-one" | |
remarks = append(remarks, exp(path, "not-found"), "\n") | |
remarks = append(remarks, exp(path, "lazy"), "\n") | |
remarks = append(remarks, exp(path, "cascade"), "\n") | |
remarks = append(remarks, exp(path, "unique"), "\n") | |
remarks = append(remarks, exp(path, "property-ref"), "\n") | |
remarks = append(remarks, exp(path.column, "name", "\njoinColumn.")) | |
} | |
} | |
@Mixin(Utils) | |
class OneToManyProperty { | |
private path | |
def type() { | |
"java.util.Set<${prop(path, 'class')}>" | |
} | |
def name() { | |
prop(path.parent(), "name") | |
} | |
def remarks() { | |
def remarks = "one-to-many" | |
remarks = append(remarks, exp(path.parent(), "table"), "\n") | |
remarks = append(remarks, exp(path.parent(), "cascade"), "\n") | |
remarks = append(remarks, exp(path.parent(), "outer-join"), "\n") | |
remarks = append(remarks, exp(path.parent(), "lazy"), "\n") | |
remarks = append(remarks, exp(path.parent(), "inverse"), "\n") | |
remarks = append(remarks, exp(path.parent(), "mutable"), "\n") | |
remarks = append(remarks, exp(path.parent(), "where"), "\n") | |
remarks = append(remarks, exp(path.parent().key.column, "name", "\njoinColumn.")) | |
} | |
} | |
@Mixin(Utils) | |
class ManyToManyProperty { | |
private path | |
def type() { | |
"java.util.Set<${prop(path, 'class')}>" | |
} | |
def name() { | |
prop(path.parent(), "name") | |
} | |
def remarks() { | |
def remarks = "many-to-many" | |
remarks = append(remarks, exp(path.parent(), "table"), "\n") | |
remarks = append(remarks, exp(path.parent(), "cascade"), "\n") | |
remarks = append(remarks, exp(path.parent(), "outer-join"), "\n") | |
remarks = append(remarks, exp(path.parent(), "lazy"), "\n") | |
remarks = append(remarks, exp(path.parent(), "inverse"), "\n") | |
remarks = append(remarks, exp(path.parent(), "mutable"), "\n") | |
remarks = append(remarks, exp(path.parent(), "where"), "\n") | |
remarks = append(remarks, exp(path.parent().key.column, "name", "\njoinColumn.")) | |
remarks = append(remarks, exp(path.column, "name", "\nassociationColumn.")) | |
} | |
} | |
class Parser { | |
def delegate | |
Parser() { | |
delegate = new XmlSlurper() | |
delegate.setFeature "http://apache.org/xml/features/nonvalidating/load-external-dtd", false | |
} | |
def parse(target) { | |
delegate.parse(target).children()[0] | |
} | |
} | |
class BaseWriter { | |
def book | |
def sheet | |
def style | |
def headerStyle | |
def borderStyle | |
def bottomStyle | |
def boldBottomStyle | |
def BaseWriter() { | |
book = new HSSFWorkbook() | |
setupFont(book.getFontAt ((short) 0)) | |
sheet = book.createSheet() | |
sheet.setZoom 85, 100 | |
book.setSheetName 0, "entity" | |
style = style() | |
headerStyle = headerStyle() | |
borderStyle = borderStyle() | |
bottomStyle = bottomStyle() | |
boldBottomStyle = boldBottomStyle() | |
} | |
def flush(path) { | |
println "output ${path}" | |
new File(path).withOutputStream { book.write(it) } | |
} | |
private def borderStyle() { | |
def style = style() | |
style.setBorderTop HSSFCellStyle.BORDER_THIN | |
style.setBorderRight HSSFCellStyle.BORDER_THIN | |
style.setBorderBottom HSSFCellStyle.BORDER_THIN | |
style.setBorderLeft HSSFCellStyle.BORDER_THIN | |
style | |
} | |
private def headerStyle() { | |
def style = borderStyle() | |
def font = setupFont(book.createFont()) | |
font.setColor IndexedColors.WHITE.getIndex() | |
style.setFillForegroundColor IndexedColors.GREY_80_PERCENT.getIndex() | |
style.setFillPattern CellStyle.SOLID_FOREGROUND | |
style.setFont font | |
style | |
} | |
private def boldBottomStyle() { | |
def style = bottomStyle() | |
def font = setupFont(book.createFont()) | |
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD) | |
style.setFont font | |
style | |
} | |
private def bottomStyle() { | |
def style = style() | |
style.setVerticalAlignment HSSFCellStyle.VERTICAL_BOTTOM | |
style | |
} | |
def style() { | |
def style = book.createCellStyle() | |
style.setWrapText true | |
style.setVerticalAlignment HSSFCellStyle.VERTICAL_TOP | |
style.setAlignment HSSFCellStyle.ALIGN_LEFT | |
style | |
} | |
private def setupFont(font) { | |
font.setFontName "メイリオ" | |
font.setFontHeightInPoints((short) 11) | |
font | |
} | |
} | |
class Writer extends BaseWriter { | |
def propertyMapping = [ | |
"description" : ["column": 1, "header": "属性"], | |
"type" : ["column": 2, "header" :"型"], "name": [ "column": 3, "header":"プロパティ"] , "remarks":["column":4, "header":"備考"]] | |
def Writer() { | |
super() | |
sheet.setColumnWidth 0, 256 * 5 | |
sheet.setColumnWidth 1, 256 * 25 | |
sheet.setColumnWidth 2, 256 * 70 | |
sheet.setColumnWidth 3, 256 * 25 | |
sheet.setColumnWidth 4, 256 * 70 | |
} | |
def write(rowNumber, node) { | |
writeClassHeader(rowNumber++, node) | |
writePropertyHeader(rowNumber++) | |
writeProperties(rowNumber++, node) | |
} | |
private def writeClassHeader(rowNumber, node) { | |
def row = sheet.createRow(rowNumber) | |
use(Utils) { | |
writeCell(row, 1, truncatePackage(prop(node, "name")?.text()), boldBottomStyle) | |
writeCell(row, 2, exp(node, "extends"), bottomStyle) | |
writeCell(row, 3, node.name(), bottomStyle) | |
def info = exp(node, "table") | |
info = append(info, exp(node, "discriminator-value", "\n")) | |
writeCell(row, 4, info, bottomStyle) | |
} | |
rowNumber | |
} | |
private def writePropertyHeader(rowNumber) { | |
def row = sheet.createRow(rowNumber) | |
propertyMapping.keySet().each { key -> | |
def cell = row.createCell(propertyMapping[key]["column"]) | |
cell.setCellStyle headerStyle | |
cell.setCellValue propertyMapping[key]["header"] | |
} | |
rowNumber | |
} | |
private def writeProperties(rowNumber, node) { | |
node.id.each { p -> | |
writeProperty(sheet.createRow(rowNumber++), node, new IdentifierProperty(path:p)) | |
} | |
node.property.each { p -> | |
writeProperty(sheet.createRow(rowNumber++), node, new SimpleProperty(path:p)) | |
} | |
node.version.each { p -> | |
writeProperty(sheet.createRow(rowNumber++), node, new SimpleProperty(path:p)) | |
} | |
node.'**'.findAll { | |
it.name() == "one-to-one" | |
}.each { p -> | |
writeProperty(sheet.createRow(rowNumber++), node, new OneToOneProperty(path:p)) | |
} | |
node.'**'.findAll { | |
it.name() == "many-to-one" | |
}.each { p -> | |
writeProperty(sheet.createRow(rowNumber++), node, new ManyToOneProperty(path:p)) | |
} | |
node.'**'.findAll { | |
it.name() == "one-to-many" | |
}.each { p -> | |
writeProperty(sheet.createRow(rowNumber++), node, new OneToManyProperty(path:p)) | |
} | |
node.'**'.findAll { | |
it.name() == "many-to-many" | |
}.each { p -> | |
writeProperty(sheet.createRow(rowNumber++), node, new ManyToManyProperty(path:p)) | |
} | |
rowNumber | |
} | |
private def writeProperty(row, node, property) { | |
propertyMapping.keySet().each { key -> | |
def columnNumber = propertyMapping[key]["column"] | |
def text = null | |
try { | |
text = property.invokeMethod(key, null)?.toString() | |
} catch (MissingMethodException ignore) { | |
} | |
writeCell(row, columnNumber, text, borderStyle) | |
} | |
} | |
private def writeCell(row, columnNumber, text, style=this.style) { | |
def cell = row.createCell(columnNumber) | |
cell.setCellStyle style | |
cell.setCellValue new HSSFRichTextString(text) | |
} | |
private def truncatePackage(type) { | |
type?.replaceAll(/.*\./, '') | |
} | |
} | |
class ClassNode { | |
def fqn | |
def parentFqn | |
def path | |
def children = [:] | |
} | |
// クラスツリーを組み立てる | |
def parser = new Parser() | |
def nodes = [:] | |
def adjustParent(nodes, removeNodes, fqn) { | |
def node = nodes[fqn] | |
if (node != null) { | |
def parentFqn = node.parentFqn | |
if (parentFqn != null) { | |
removeNodes << fqn | |
def parentNode = nodes[parentFqn] | |
parentNode.children[fqn] = node | |
adjustParent(nodes, removeNodes, parentFqn) | |
} | |
} | |
} | |
if (args.length != 2) { | |
throw new IllegalArgumentException("usage: ReverseHbmToEntityExcel [target.dir] [dist.path]") | |
} | |
use(Utils) { | |
new File(args[0]).eachFileRecurse { file -> | |
if (file.name =~ /.*\.hbm\.xml$/) { | |
def path = parser.parse(file) | |
def parentFqn = prop(path, "extends")?.text() | |
def classFqn = prop(path, "name")?.text() | |
def node = new ClassNode(fqn:classFqn, parentFqn: parentFqn, path:path) | |
nodes[classFqn] = node | |
} | |
} | |
def removeNodes = [] | |
nodes.each { | |
adjustParent(nodes, removeNodes, it.key) | |
} | |
removeNodes.each { nodes.remove(it) } | |
} | |
def writeNode(node, writer, rowNumber, prefix = "") { | |
println "${prefix}${node.fqn}" | |
def number = writer.write(++rowNumber, node.path) | |
node.children.each { | |
number = writeNode(it.value, writer, number, prefix << "\t") | |
} | |
number | |
} | |
def writer = new Writer() | |
def rowNumber = 0 | |
nodes.sort { a, b -> | |
a.key <=> b.key | |
}.each { | |
rowNumber = writeNode(it.value, writer, rowNumber) | |
} | |
writer.flush(args[1]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment