package org.quickbundle.mda.gc;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Node;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Widget;
public class TableRelation {
GenerateCodeRule gcRule = null;
public TableRelation(GenerateCodeRule gcRule) {
this.gcRule = gcRule;
}
public List<String> getAvailableTables() {
return new ArrayList<String>(gcRule.getMTableDocs().keySet());
}
public List<String> getAvailableMiddleTables(String parentTable) throws SQLException {
List<String> result = new ArrayList<String>(gcRule.getMTableDocs().keySet());
List<String> parentTableChild = getChildTable(parentTable);
for(String tableName : parentTableChild) {
if(!result.contains(tableName)) {
result.add(tableName);
}
}
return result;
}
public List<String> getSmallAvaliableMiddleTables(List<String> avaliableMiddleTables, Combo comboParentTableInner, Combo middleTable) throws SQLException {
List<String> result = new ArrayList<String>(gcRule.getMTableDocs().keySet());
List<String> lMiddleTableInDb = new ArrayList<String>(avaliableMiddleTables);
lMiddleTableInDb.removeAll(gcRule.getMTableDocs().keySet());
Combo refTableOfMiddleTable = guessRefTableOfMiddleTable(middleTable);
if(refTableOfMiddleTable != null && !refTableOfMiddleTable.isDisposed()) {
String refTable = refTableOfMiddleTable.getText();
Map<String,String[]> mOneToMulti = getChildTableOneToMulti(gcRule.getConnection(), gcRule.getConfig1MainRuleWizardPage().getMContainerText("catalog"),
gcRule.getConfig1MainRuleWizardPage().getMContainerText("schemaPattern"),
refTable);
Set<String> sChild = mOneToMulti.keySet();
for(String middleTableInDb : lMiddleTableInDb) {
if(sChild.contains(middleTableInDb)) {
result.add(middleTableInDb);
}
}
}
return result;
}
public List<String> getMiddleTable(String parentTable, String refTable) throws SQLException {
List<String> result = new ArrayList<String>();
if((parentTable == null || parentTable.length() == 0)
&&(refTable == null || refTable.length() == 0)) {
return result;
} else if(parentTable == null || parentTable.length() == 0){
return getChildTable(refTable);
} else if(refTable == null || refTable.length() == 0) {
return getChildTable(parentTable);
} else {
List<String> parentTableChild = getChildTable(parentTable);
List<String> refTableChild = getChildTable(refTable);
for(String table : parentTableChild) {
if(refTableChild.contains(table)) {
result.add(table);
}
}
}
return result;
}
List<String> getChildTable(String parentTable) throws SQLException {
List<String> result = new ArrayList<String>();
Map<String,String[]> children = getChildTableOneToMulti(gcRule.getConnection(), gcRule.getConfig1MainRuleWizardPage().getMContainerText("catalog"),
gcRule.getConfig1MainRuleWizardPage().getMContainerText("schemaPattern"),
parentTable);
result.addAll(children.keySet());
return result;
}
private Combo guessRefTableOfMiddleTable(Combo middleTable) {
Control[] aWidgetMiddleRow = middleTable.getParent().getChildren();
boolean findMiddleTable = false;
int index = 0;
for(Control widget : aWidgetMiddleRow) {
if(widget == middleTable) {
findMiddleTable = true;
}
if(findMiddleTable && widget instanceof Combo) {
index ++;
if(index == 4) {
return (Combo) widget;
}
}
}
return null;
}
public List<String> getColumns(String table) {
List<String> lColumn = new ArrayList<String>();
Document docTable = (Document)gcRule.getMTableDocs().get(table);
if(docTable == null) {
return lColumn;
}
String pkColumn = docTable.valueOf("/meta/tables/table[@tableName='" + table + "']/@tablePk");
lColumn.add(pkColumn);
List<Element> tableColumns = docTable.selectNodes("/meta/tables/table[@tableName='" + table + "']/column");
for(Element column : tableColumns) {
if(pkColumn.equals(column.valueOf("@columnName"))) {
continue;
}
lColumn.add(column.valueOf("@columnName"));
}
return lColumn;
}
public String guessFkColomn(String parentTable, String childTable) {
String fkColumn = null;
try {
Map<String,String[]> mOneToMulti = getChildTableOneToMulti(gcRule.getConnection(), gcRule.getConfig1MainRuleWizardPage().getMContainerText("catalog"),
gcRule.getConfig1MainRuleWizardPage().getMContainerText("schemaPattern"),
parentTable);
if(mOneToMulti.get(childTable) != null) {
fkColumn = mOneToMulti.get(childTable)[7];
}
} catch (SQLException e) {
e.printStackTrace();
}
if(fkColumn == null) {
Document docTable = (Document)gcRule.getMTableDocs().get(childTable);
fkColumn = docTable.valueOf("/meta/tables/table[@tableName='" + childTable + "']/@statisticColumn");
}
return fkColumn;
}
public void buildTableRelationXml(List<List<Object>> relations) {
Map<String, Document> mTableDoc = gcRule.getMTableDocs();
Set<String> sHasRelationTable = new HashSet<String>();
for(List<Object> lRelationGroup : relations) {
List<List<Widget>> lRelationRow = (List<List<Widget>>)lRelationGroup.get(0);
if(lRelationRow.size() == 0) {
continue;
}
List<Combo> tableName_refColumn = getCombos(lRelationGroup);
if(tableName_refColumn.size() < 2) {
continue;
}
String mainTableName = tableName_refColumn.get(0).getText();
String mainRefColumn = tableName_refColumn.get(1).getText();
Document tableDoc = mTableDoc.get(mainTableName);
Element mainTable = (Element)tableDoc.selectSingleNode("/meta/relations/mainTable[@tableName='" + mainTableName + "']");
if(mainTable == null) {
Element eleRelations = (Element)tableDoc.selectSingleNode("/meta/relations");
mainTable = eleRelations.addElement("mainTable");
mainTable.addAttribute("tableName", mainTableName);
}
mainTable.addAttribute("refColumn", mainRefColumn);
mainTable.clearContent();
for(List<Widget> relationRow : lRelationRow) {
if(relationRow.get(0) instanceof Canvas) { //中间表
List<Combo> lMiddleTableRow = getCombos(relationRow);
if(lMiddleTableRow.size() > 4) {
Element refTable = mainTable.addElement("refTable");
refTable.addAttribute("tableName", lMiddleTableRow.get(3).getText());
refTable.addAttribute("refColumn", lMiddleTableRow.get(4).getText());
Element middleTable = refTable.addElement("middleTable");
middleTable.addAttribute("tableName", lMiddleTableRow.get(0).getText());
middleTable.addAttribute("mainColumn", lMiddleTableRow.get(1).getText());
middleTable.addAttribute("refColumn", lMiddleTableRow.get(2).getText());
sHasRelationTable.add(mainTableName);
}
} else { //子表
List<Combo> lChildTableRow = getCombos(relationRow);
if(lChildTableRow.size() > 1) {
Element refTable = mainTable.addElement("refTable");
refTable.addAttribute("tableName", lChildTableRow.get(0).getText());
refTable.addAttribute("refColumn", lChildTableRow.get(1).getText());
sHasRelationTable.add(mainTableName);
}
}
}
}
clearNotHasRelationTable(sHasRelationTable);
}
/**
* 清理掉没有体现关系的表
*
* @param sHasRelationTable
*/
private void clearNotHasRelationTable(Set<String> sHasRelationTable) {
Map<String, Document> mTableDoc = gcRule.getMTableDocs();
for(Map.Entry<String, Document> en : mTableDoc.entrySet()) {
String mainTableName = en.getKey();
if(sHasRelationTable.contains(mainTableName)) {
continue;
}
Document tableDoc = mTableDoc.get(mainTableName);
Element eleRelations = (Element)tableDoc.selectSingleNode("/meta/relations");
if(eleRelations != null) {
eleRelations.clearContent();
}
}
}
private List<Combo> getCombos(List objs) {
List<Combo> result = new ArrayList<Combo>();
for(Object obj : objs) {
if(obj instanceof Combo && !((Combo)obj).isDisposed() && ((Combo)obj).getText().length() > 0) {
result.add((Combo)obj);
}
}
return result;
}
@SuppressWarnings("unchecked")
public void mergeChildTable() {
Map<String, Document> mTableDoc = gcRule.getMTableDocs();
for(Map.Entry<String, Document> en : mTableDoc.entrySet()) {
String mainTable = en.getKey();
Document tableDoc = en.getValue();
Element eleTables = (Element)tableDoc.selectSingleNode("/meta/tables");
Element eleMainTable = (Element)tableDoc.selectSingleNode("/meta/relations/mainTable[@tableName='" + mainTable + "']");
if(eleMainTable == null) {
continue;
}
//合并子表、中间表的目标表
List<Element> lRefTableChild = eleMainTable.selectNodes("refTable"); //"refTable[count(middleTable)=0]"则表示只merge子表
if(lRefTableChild.size() == 0) {
continue;
}
for(Element eleRefTableChild : lRefTableChild) {
String refTableChild = eleRefTableChild.valueOf("@tableName");
Document docRefTableChild = mTableDoc.get(refTableChild);
if(docRefTableChild != null){
Element redundantRefTableInfo = (Element)tableDoc.selectSingleNode("/meta/tables/table[@tableName='" + refTableChild + "']");
if(redundantRefTableInfo != null) { //清理冗余的缓存
eleTables.remove(redundantRefTableInfo);
}
Element largeEleRefTableChild = (Element)docRefTableChild.selectSingleNode("/meta/tables/table[@tableName='" + refTableChild + "']");
eleTables.add(largeEleRefTableChild.createCopy());
//清理tableTos
Element eleTableTos = (Element)gcRule.getMainRule().selectSingleNode("/rules/database/tableTos");
Node eleTableTo = eleTableTos.selectSingleNode("tableTo[text()='" + refTableChild + "']");
if(eleTableTo != null && eleRefTableChild.selectNodes("middleTable").size() == 0) {
eleTableTos.remove(eleTableTo);
}
}
}
}
}
/**
* 找子表
* @param conn
* @param catalog
* @param schemaPattern
* @param tableName
* @return
* @throws SQLException
*/
public static Map<String,String[]> getChildTableOneToMulti(Connection conn, String catalog, String schemaPattern, String tableName) throws SQLException {
//key是子表name,value是主表和子表的关联信息
Map<String,String[]> mOneToMulti = new HashMap<String,String[]>();
ResultSet rsek1 = conn.getMetaData().getExportedKeys(catalog, schemaPattern, tableName);
if(!rsek1.next()) {
rsek1 = conn.getMetaData().getExportedKeys(catalog, schemaPattern, tableName.toLowerCase());
} else {
rsek1 = conn.getMetaData().getExportedKeys(catalog, schemaPattern, tableName);
}
while(rsek1.next()) {
String[] aRsReference = new String[14];
for (int j = 1; j <= 14; j++) {
aRsReference[j-1] = rsek1.getString(j);
}
mOneToMulti.put(aRsReference[6], aRsReference);
}
return mOneToMulti;
}
/**
* 根据conn分析主子表关系
* @param conn
* @param catalog
* @param schemaPattern
* @param tableName
* @return
*/
public static String getParentChildtableByConn(Connection conn, String catalog, String schemaPattern, String tableName) {
try {
//key是子表name,value是主表和子表的关联信息
Map<String,String[]> mOneToMulti = getChildTableOneToMulti(conn, catalog, schemaPattern, tableName);
//key是多对多的第3个表name,value是[主表和中间表的关联信息][第3个表和中间表的关联信息]
Map<String,String[][]> mMultiToMulti = new HashMap<String,String[][]>();
for (Iterator<String> itMOneToMulti = mOneToMulti.keySet().iterator(); itMOneToMulti.hasNext();) {
//子表此时作为中间表
String childTable = itMOneToMulti.next();
ResultSet rsik2 = conn.getMetaData().getImportedKeys(catalog, schemaPattern, childTable);
if(!rsik2.next()) {
rsik2 = conn.getMetaData().getImportedKeys(catalog, schemaPattern, childTable.toLowerCase());
} else {
rsik2 = conn.getMetaData().getImportedKeys(catalog, schemaPattern, childTable);
}
while(rsik2.next()) {
String[] aRsReference = new String[14];
for (int j = 1; j <= 14; j++) {
aRsReference[j-1] = rsik2.getString(j);
}
if(tableName.toUpperCase().endsWith(aRsReference[2].toUpperCase())) {
continue;
}
mMultiToMulti.put(aRsReference[2], new String[][]{mOneToMulti.get(childTable), aRsReference});
itMOneToMulti.remove();
break;
}
}
return buildParentChildTable(mOneToMulti, mMultiToMulti);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* @param mOneToMulti key是子表name,value是主表和子表的关联信息
* @param mMultiToMulti key是多对多的第3个表name,value是[主表和中间表的关联信息][第3个表和中间表的关联信息]
* @return
CmsArticle.ID=CmsArticleVersion.ARTICLE_ID,
CmsArticle.ID=CmsArticleColumn.ARTICLE_ID|TEMPLATE_ID=CmsTemplate.ID,
*/
private static String buildParentChildTable(Map<String,String[]> mOneToMulti, Map<String,String[][]> mMultiToMulti) {
StringBuilder sb = new StringBuilder();
for (Iterator<String> itMOneToMulti = mOneToMulti.keySet().iterator(); itMOneToMulti.hasNext();) {
String childTable1 = itMOneToMulti.next();
String[] aRsReference = mOneToMulti.get(childTable1);
sb.append(MetadataHelper.getFormatTableName(aRsReference[2]) + "." + aRsReference[3] + "=" + MetadataHelper.getFormatTableName(aRsReference[6]) + "." + aRsReference[7] + ",\r\n");
}
for (Iterator<String> itMMultiToMulti = mMultiToMulti.keySet().iterator(); itMMultiToMulti.hasNext();) {
String childTable1 = itMMultiToMulti.next();
String[][] aaRsReference = mMultiToMulti.get(childTable1);
sb.append(MetadataHelper.getFormatTableName(aaRsReference[0][2]) + "." + aaRsReference[0][3] +
"=" + aaRsReference[0][6] + "." + aaRsReference[0][7] + "|" + aaRsReference[1][7] +
"=" + MetadataHelper.getFormatTableName(aaRsReference[1][2]) + "." + aaRsReference[1][3] +
"(" + aaRsReference[1][2] + "." + aaRsReference[1][3] + "),\r\n");
}
System.out.println(sb.toString());
return sb.toString().replaceAll("[\\s,\\\\n\\\\r]+$", "");
}
}