Java tutorial
/* * This file is a part of the SchemaSpy project (http://schemaspy.org). * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 John Currier * * SchemaSpy is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * SchemaSpy is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ package org.schemaspy.view; import java.awt.*; import java.awt.font.FontRenderContext; import java.awt.geom.AffineTransform; import java.io.File; import java.text.NumberFormat; import java.util.HashSet; import java.util.List; import java.util.Set; import org.schemaspy.Config; import org.schemaspy.model.Table; import org.schemaspy.model.TableColumn; import org.schemaspy.model.TableIndex; import org.apache.commons.io.FilenameUtils; import java.net.URL; public class DotNode { private final Table table; private final DotNodeConfig config; private final String path; private final String outputDir; private final Set<TableColumn> excludedColumns = new HashSet<TableColumn>(); private final String lineSeparator = System.getProperty("line.separator"); private final boolean displayNumRows = Config.getInstance().isNumRowsEnabled(); /** * Create a DotNode that is a focal point of a diagram. * That is, all of its columns are displayed in addition to the details * of those columns. * * @param table Table * @param path String */ public DotNode(Table table, String path, File outputDir) { this(table, path, outputDir, new DotNodeConfig(true, true)); } public DotNode(Table table, String path, File outputDir, DotNodeConfig config) { this.table = table; this.path = path + (table.isRemote() ? ("../../" + table.getContainer() + "/tables/") : ""); this.outputDir = outputDir.toString(); this.config = config; } /** * Create a DotNode and specify whether it displays its columns. * The details of the optional columns (e.g. type, size) are not displayed. * * @param table Table * @param showColumns boolean * @param path String */ public DotNode(Table table, boolean showColumns, String path, File outputDir) { this(table, path, outputDir, showColumns ? new DotNodeConfig(true, false) : new DotNodeConfig()); } public void setShowImplied(boolean showImplied) { config.showImpliedRelationships = showImplied; } public Table getTable() { return table; } public void excludeColumn(TableColumn column) { excludedColumns.add(column); } @Override public String toString() { StyleSheet css = StyleSheet.getInstance(); StringBuilder buf = new StringBuilder(); String tableName = table.getName(); // fully qualified table name (optionally prefixed with schema) String fqTableName = (table.isRemote() ? table.getContainer() + "." : "") + tableName; String colspan = config.showColumnDetails ? "COLSPAN=\"2\" " : "COLSPAN=\"3\" "; String colspanHeader = config.showColumnDetails ? "COLSPAN=\"4\" " : "COLSPAN=\"3\" "; String tableOrView = table.isView() ? "view" : "table"; buf.append(" \"" + fqTableName + "\" [" + lineSeparator); buf.append(" label=<" + lineSeparator); buf.append(" <TABLE BORDER=\"" + (config.showColumnDetails ? "2" : "0") + "\" CELLBORDER=\"1\" CELLSPACING=\"0\" BGCOLOR=\"" + css.getTableBackground() + "\">" + lineSeparator); buf.append(" <TR>"); buf.append("<TD " + colspanHeader + " BGCOLOR=\"" + css.getTableHeadBackground() + "\">"); buf.append("<TABLE BORDER=\"0\" CELLSPACING=\"0\">"); buf.append("<TR>"); buf.append("<TD ALIGN=\"LEFT\"><B>" + fqTableName + "</B></TD>"); buf.append("<TD ALIGN=\"RIGHT\">[" + tableOrView + "]</TD>"); buf.append("</TR>"); buf.append("</TABLE>"); buf.append("</TD>"); buf.append("</TR>" + lineSeparator); boolean skippedTrivial = false; if (config.showColumns) { List<TableColumn> primaryColumns = table.getPrimaryColumns(); Set<TableColumn> indexColumns = new HashSet<TableColumn>(); for (TableIndex index : table.getIndexes()) { indexColumns.addAll(index.getColumns()); } indexColumns.removeAll(primaryColumns); int maxwidth = getColumnMaxWidth(); for (TableColumn column : table.getColumns()) { if (config.showTrivialColumns || config.showColumnDetails || column.isPrimary() || column.isForeignKey() || indexColumns.contains(column)) { buf.append(" <TR>"); buf.append("<TD PORT=\"" + column.getName() + "\" " + colspan); if (excludedColumns.contains(column)) buf.append("BGCOLOR=\"" + css.getExcludedColumnBackgroundColor() + "\" "); else if (indexColumns.contains(column)) buf.append("BGCOLOR=\"" + css.getIndexedColumnBackground() + "\" "); buf.append("ALIGN=\"LEFT\">"); buf.append("<TABLE BORDER=\"0\" CELLSPACING=\"0\" ALIGN=\"LEFT\">"); buf.append("<TR ALIGN=\"LEFT\">"); buf.append("<TD ALIGN=\"LEFT\" FIXEDSIZE=\"TRUE\" WIDTH=\"15\" HEIGHT=\"16\">"); if (column.isPrimary()) { buf.append("<IMG SRC=\"" + outputDir + "/images/primaryKeys.png\"/>"); } else if (column.isForeignKey()) { buf.append("<IMG SRC=\"" + outputDir + "/images/foreignKeys.png\"/>"); } buf.append("</TD>"); buf.append("<TD ALIGN=\"LEFT\" FIXEDSIZE=\"TRUE\" WIDTH=\"" + maxwidth + "\" HEIGHT=\"16\">"); buf.append(column.getName()); buf.append("</TD>"); buf.append("</TR>"); buf.append("</TABLE>"); buf.append("</TD>"); if (config.showColumnDetails) { buf.append("<TD PORT=\""); buf.append(column.getName()); buf.append(".type\" ALIGN=\"LEFT\">"); buf.append(column.getShortTypeName().toLowerCase()); buf.append("["); buf.append(column.getDetailedSize()); buf.append("]</TD>"); } buf.append("</TR>" + lineSeparator); } else { skippedTrivial = true; } } } if (skippedTrivial || !config.showColumns) { buf.append(" <TR><TD PORT=\"elipses\" COLSPAN=\"3\" ALIGN=\"LEFT\">...</TD></TR>" + lineSeparator); } if (!table.isView()) { buf.append(" <TR>"); buf.append("<TD ALIGN=\"LEFT\" BGCOLOR=\"" + css.getBodyBackground() + "\">"); int numParents = config.showImpliedRelationships ? table.getNumParents() : table.getNumNonImpliedParents(); if (numParents > 0 || config.showColumnDetails) buf.append("< " + numParents); else buf.append(" "); buf.append("</TD>"); buf.append("<TD ALIGN=\"RIGHT\" BGCOLOR=\"" + css.getBodyBackground() + "\">"); final long numRows = table.getNumRows(); if (displayNumRows && numRows >= 0) { buf.append(NumberFormat.getInstance().format(numRows)); buf.append(" row"); if (numRows != 1) buf.append('s'); } else { buf.append(" "); } buf.append("</TD>"); buf.append("<TD ALIGN=\"RIGHT\" BGCOLOR=\"" + css.getBodyBackground() + "\">"); int numChildren = config.showImpliedRelationships ? table.getNumChildren() : table.getNumNonImpliedChildren(); if (numChildren > 0 || config.showColumnDetails) buf.append(numChildren + " >"); else buf.append(" "); buf.append("</TD></TR>" + lineSeparator); } buf.append(" </TABLE>>" + lineSeparator); if (!table.isRemote() || Config.getInstance().isOneOfMultipleSchemas()) buf.append(" URL=\"" + path + HtmlFormatter.urlEncode(tableName) + ".html\"" + lineSeparator); buf.append(" tooltip=\"" + HtmlFormatter.urlEncode(fqTableName) + "\"" + lineSeparator); buf.append(" ];"); return buf.toString(); } private int getColumnMaxWidth() { int maxwidth = getTextWidth(table.getName()); for (TableColumn column : table.getColumns()) { int size = getTextWidth(column.getName()); if (maxwidth < size) { maxwidth = size; } } return maxwidth; } private int getTextWidth(String text) { AffineTransform affinetransform = new AffineTransform(); FontRenderContext frc = new FontRenderContext(affinetransform, true, true); int fontSize = Config.getInstance().getFontSize() + 1; Font font = new Font(Config.getInstance().getFont(), Font.BOLD, fontSize); int fontWidth = (int) (font.getStringBounds(text, frc).getWidth()); return fontWidth; } private String getFileSystemPath(String fileName) { URL keyPath = getClass().getResource(fileName); String filepath = FilenameUtils.separatorsToSystem(keyPath.getPath()); filepath = new File(filepath).getAbsoluteFile().toString(); return filepath; } public static class DotNodeConfig { private final boolean showColumns; private boolean showTrivialColumns; private final boolean showColumnDetails; private boolean showImpliedRelationships; /** * Nothing but table name and counts are displayed */ public DotNodeConfig() { showColumns = showTrivialColumns = showColumnDetails = showImpliedRelationships = false; } public DotNodeConfig(boolean showTrivialColumns, boolean showColumnDetails) { showColumns = true; this.showTrivialColumns = showTrivialColumns; this.showColumnDetails = showColumnDetails; } } }