/******************************************************************************* * Copyright (c) 2013 hangum. * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Lesser Public License v2.1 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html * * Contributors: * hangum - initial API and implementation ******************************************************************************/ package com.hangum.tadpole.mongodb.erd.core.relation; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.eclipse.emf.common.util.EList; import com.hangum.tadpole.engine.manager.TadpoleSQLManager; import com.hangum.tadpole.engine.query.dao.mysql.ReferencedTableDAO; import com.hangum.tadpole.engine.query.dao.system.UserDBDAO; import com.hangum.tadpole.mongodb.erd.core.utils.MongodbUtils; import com.hangum.tadpole.mongodb.model.Column; import com.hangum.tadpole.mongodb.model.DB; import com.hangum.tadpole.mongodb.model.MongodbFactory; import com.hangum.tadpole.mongodb.model.Relation; import com.hangum.tadpole.mongodb.model.RelationKind; import com.hangum.tadpole.mongodb.model.Table; import com.ibatis.sqlmap.client.SqlMapClient; /** * ERD 출력시 Table relation 관련 코드 * * <pre> 컬럼 설명 constraint_name : 인덱스 이름 table_name : 소스 테이블 이름 column_name : 소스 테이블 컬럼 referenced_table_name : 타켓 테이블 이름 referenced_column_name : 타켓 테이블 컬럼 * </pre> * * @author hangum * */ public class RelationUtil { private static final Logger logger = Logger.getLogger(RelationUtil.class); /** * <pre> * 특정 테이블 관계를 조회합니다. * * object type이 org.bson.types.ObjectId 이거나 field이름이 _id로 시작하지 않고 _id로 끝나야 레퍼런스 컬럼으로 인식합니다. * </pre> * * @param userDB * @param mapDBTables * @param db * @param refTableNames * @throws Exception */ public static void calRelation(UserDBDAO userDB, Map<String, Table> mapDBTables, DB db, String refTableNames) throws Exception { List<ReferencedTableDAO> listRealRefTableDAO = new ArrayList<ReferencedTableDAO>(); Set<String> keySet = mapDBTables.keySet(); for (String keyTable : keySet) { Table table = mapDBTables.get(keyTable); EList<Column> listColumn = table.getColumns(); for (Column column : listColumn) { String strField = column.getField(); if(MongodbUtils.isReferenceKey(column.getType(), strField)) { String strRefName = StringUtils.remove(strField, "_id"); ReferencedTableDAO refTableDao = new ReferencedTableDAO(); refTableDao.setTable_name(table.getName()); refTableDao.setColumn_name(strRefName); refTableDao.setReferenced_table_name(strRefName); refTableDao.setReferenced_column_name(table.getName()); refTableDao.setConstraint_name(strRefName); listRealRefTableDAO.add(refTableDao); } } } calRelation(userDB, mapDBTables, db, listRealRefTableDAO); } /** * 모든 테이블을 조회합니다. * * @param userDB * @param mapDBTables * @param db * @throws Exception */ public static void calRelation(UserDBDAO userDB, Map<String, Table> mapDBTables, DB db) throws Exception { List<ReferencedTableDAO> listRealRefTableDAO = new ArrayList<ReferencedTableDAO>(); Set<String> keySet = mapDBTables.keySet(); for (String keyTable : keySet) { Table table = mapDBTables.get(keyTable); EList<Column> listColumn = table.getColumns(); for (Column column : listColumn) { String strField = column.getField(); if(MongodbUtils.isReferenceKey(column.getType(), strField)) { ReferencedTableDAO refTableDao = new ReferencedTableDAO(); refTableDao.setTable_name(table.getName()); refTableDao.setColumn_name(strField); refTableDao.setReferenced_table_name(StringUtils.remove(strField, "_id")); refTableDao.setReferenced_column_name(strField); refTableDao.setConstraint_name(strField); listRealRefTableDAO.add(refTableDao); } } } calRelation(userDB, mapDBTables, db, listRealRefTableDAO); } /** * 테이블 관계를 구성합니다. * * @param userDB * @param mapDBTables * @param db * @throws Exception */ public static void calRelation(UserDBDAO userDB, Map<String, Table> mapDBTables, DB db, List<ReferencedTableDAO> referenceTableList) throws Exception { MongodbFactory tadpoleFactory = MongodbFactory.eINSTANCE; // 디비에서 관계 정보를 찾아서 넣어준다. for (ReferencedTableDAO refTabDAO : referenceTableList) { Table soTabMod = mapDBTables.get( refTabDAO.getTable_name() ); Table tarTabMod = mapDBTables.get( refTabDAO.getReferenced_table_name() ); // 소스테이블에 인덱스가 없고, 타겟 테이블이 있으면 추가한다. if(soTabMod != null && tarTabMod != null) { // 이미 추가된 relation인지 검사합니다. boolean isAlrealyAppend = false; for(Relation relation : soTabMod.getOutgoingLinks()) { if( relation.getConstraint_name() != null && refTabDAO.getConstraint_name() != null ) { if (relation.getConstraint_name().equals(refTabDAO.getConstraint_name())) { isAlrealyAppend = true; break; } } } for (Relation relation : soTabMod.getIncomingLinks()) { if( relation.getConstraint_name() != null && refTabDAO.getConstraint_name() != null ) { if (relation.getConstraint_name().equals(refTabDAO.getConstraint_name())) { isAlrealyAppend = true; break; } } } // TODO 현재 자신의 테이블을 키로 가자고 있는 항목은 다음과 같은 이유로 제거 합니다. // java.lang.RuntimeException: Cycle detected in graph if(refTabDAO.getTable_name().equals(refTabDAO.getReferenced_table_name())) continue; // 이미 추가 되어 있는가? if(isAlrealyAppend) continue; // 새롭게 추가될 요소 이면. Relation relation = tadpoleFactory.createRelation(); /* 저장시 아래와 같은 오류가 발생하여 추가한 코드 * 여유를 가지고 디버깅을 해봐야 하는코드 * * org.eclipse.emf.ecore.resource.Resource$IOWrappedException: * The object 'com.hangum.tadpole.model.impl.RelationImpl@5e44efa0 (source_kind: ONLY_ONE, target_kind: ONE_MANY, column_name: country_id, referenced_column_name: country_id, bendpoint: [], constraint_name: null)' * is not contained in a resource. */ relation.setDb(db); relation.setConstraint_name(refTabDAO.getConstraint_name()); relation.setColumn_name(refTabDAO.getColumn_name()); relation.setReferenced_column_name(refTabDAO.getReferenced_column_name()); relation.setSource_kind( RelationKind.ONLY_ONE ); relation.setTarget_kind( RelationKind.ONLY_ONE ); // 관계형성 soTabMod.getIncomingLinks().add(relation); tarTabMod.getOutgoingLinks().add(relation); relation.setSource(soTabMod); relation.setTarget(tarTabMod); }// if(souceModel != null && targetModel != null } // for } /** * 테이블의 참조 목록 정보를 리턴합니다. * * @return * @throws Exception */ public static List<ReferencedTableDAO> getReferenceTable(UserDBDAO userDB) throws Exception { SqlMapClient sqlClient = TadpoleSQLManager.getInstance(userDB); return sqlClient.queryForList("referencedTableListALL", userDB.getSchema()); } }