/**
* @version $Id: LabelDic.java 997 2013-10-28 11:44:11Z yukihiro-kinjyo $
*
* 2013/10/28
* @author shingo-takahashi
*
* Copyright 2011-2014 TIDAコンソーシアム All Rights Reserved.
*/
package com.tida_okinawa.corona.io.dam.hibernate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import org.eclipse.core.runtime.IProgressMonitor;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import com.tida_okinawa.corona.io.bean.DicLabelBean;
import com.tida_okinawa.corona.io.bean.DicTableBean;
import com.tida_okinawa.corona.io.bean.LabelTreeBean;
import com.tida_okinawa.corona.io.bean.LabelTreePKBean;
import com.tida_okinawa.corona.io.bean.RelCommonLabelBean;
import com.tida_okinawa.corona.io.dam.hibernate.hql.CommonCreateQuery;
import com.tida_okinawa.corona.io.model.dic.ICoronaDic;
import com.tida_okinawa.corona.io.model.dic.IDicItem;
import com.tida_okinawa.corona.io.model.dic.ILabel;
import com.tida_okinawa.corona.io.model.dic.ITerm;
import com.tida_okinawa.corona.io.model.dic.IUserDic;
import com.tida_okinawa.corona.io.model.dic.abstraction.AbstractLabelDic;
import com.tida_okinawa.corona.io.model.dic.impl.LabelItem;
import com.tida_okinawa.corona.io.model.dic.impl.Term;
import com.tida_okinawa.corona.io.util.CoronaIoUtils;
/**
* ラベル辞書実装クラス
*
* @author yukihiro-kinjyo
*
*/
public final class LabelDic extends AbstractLabelDic {
static final int INSERT = 1;
static final int DELETE = 2;
/**
* アイテムの更新を行ったかどうかのフラグ
*/
private boolean bRefreshRecords = false;
/**
* @param id
* @param name
* @param lasted
*/
public LabelDic(int id, String name, Date lasted) {
super(id, name, lasted);
}
/**
* @param id
* @param name
* @param lasted
* @param parentId
*/
public LabelDic(int id, String name, Date lasted, Set<Integer> parentId) {
super(id, name, lasted, parentId);
}
/**
* ラベルの作成
*
* @param list
* @return 処理が完了するとTrueが返る
*/
public boolean commitLabel(List<ILabel> list) {
Session session = IoService.getInstance().getSession();
boolean result = true;
for (ILabel item : list) {
if (item.isDirty() || item.getId() == IDicItem.UNSAVED_ID) {
try {
/* トランザクション開始 */
session.beginTransaction();
DicLabelBean bean;
if (item.getId() == IDicItem.UNSAVED_ID) {
// 新規登録の場合
bean = new DicLabelBean();
bean.setDicId(getId());
} else {
// ラベル名変更の場合
bean = (DicLabelBean) CommonCreateQuery.getDicLabelQuery(item.getId()).uniqueResult();
}
if (bean != null) {
bean.setLabelName(item.getName());
bean.setInactive(false);
session.save(bean);
session.flush();
/* トランザクションコミット */
session.getTransaction().commit();
} else {
result = false;
}
item.setId(bean.getLabelId());
item.setDirty(false);
/* 子供チェック */
if (item.getChildren().size() > 0) {
commitLabel(item.getChildren());
}
} catch (HibernateException e) {
throw e;
} finally {
if (session.getTransaction().isActive()) {
/* トランザクションロールバック */
session.getTransaction().rollback();
}
}
}
}
return result;
}
/**
* ラベル削除
*
* @param list
* @return 処理が完了するとTrueが返る
*/
public boolean deleteLabel(List<ILabel> list) throws HibernateException {
Session session = IoService.getInstance().getSession();
for (ILabel item : list) {
boolean bflg = false;
/*
* ラベルを削除 (INACTIVE=trueに設定) ただし、label_id =
* 0のものは登録前に削除されているので削除処理を回避する
*/
if (item.getId() != IDicItem.UNSAVED_ID) {
try {
DicLabelBean dicLabelBean = (DicLabelBean) session.get(DicLabelBean.class, item.getId());
if (dicLabelBean != null) {
/* トランザクション開始 */
session.beginTransaction();
dicLabelBean.setInactive(true);
session.save(dicLabelBean);
session.flush();
/* トランザクションコミット */
session.getTransaction().commit();
bflg = true;
}
} catch (HibernateException e) {
throw e;
} finally {
if (session.getTransaction().isActive()) {
/* トランザクションロールバック */
session.getTransaction().rollback();
}
}
if (bflg) {
/* 用語とのリレーションを削除 */
List<ITerm> terms = item.getTerms();
StringBuilder strId = new StringBuilder(100);
if (terms.size() > 0) {
for (ITerm term : terms) {
if (term != null) {
strId.append(",").append(term.getId()); //$NON-NLS-1$
}
}
/* 紐づけを削除 */
/* DicLabelDao.deleteRelCommonLabelを置換する。 */
try {
/* トランザクション開始 */
session.beginTransaction();
String strTermId = strId.substring(1);
String strSQL = "DELETE FROM REL_COMMON_LABEL WHERE LABEL_ID = " + item.getId(); //$NON-NLS-1$
if (strTermId.length() > 0) {
strSQL = strSQL + " AND ITEM_ID IN (" + strTermId + ")"; //$NON-NLS-1$ //$NON-NLS-2$
}
session.createSQLQuery(strSQL).executeUpdate();
session.flush();
/* トランザクションコミット */
session.getTransaction().commit();
} catch (HibernateException e) {
throw e;
} finally {
if (session.getTransaction().isActive()) {
/* トランザクションロールバック */
session.getTransaction().rollback();
}
}
}
}
/* 子供チェック */
if (item.getChildren().size() > 0) {
deleteLabel(item.getChildren());
}
}
}
return true;
}
@Override
protected boolean doCommit(boolean bRecords, IProgressMonitor monitor) {
Session session = IoService.getInstance().getSession();
try {
/* 辞書情報の更新 */
// dic_tableの更新
DicTableBean dicTable = (DicTableBean) CommonCreateQuery.getDicTableQuery(this.getId()).uniqueResult();
if (dicTable != null) {
/* トランザクション開始 */
session.beginTransaction();
dicTable.setDicName(this.getName());
dicTable.setParentId(CoronaIoUtils.intListToString(this.getParentIds()));
session.save(dicTable);
session.flush();
/* トランザクションコミット */
session.getTransaction().commit();
} else {
return false;
}
if (!bRecords)
return true;
} catch (HibernateException e) {
e.printStackTrace();
return false;
} finally {
if (session.getTransaction().isActive()) {
/* トランザクションロールバック */
session.getTransaction().rollback();
}
}
try {
List<ILabel> tmpList = new ArrayList<ILabel>();
List<ILabel> tmpDelList = new ArrayList<ILabel>();
if (getItems().size() > 0) {
tmpList.addAll(getLabelsRecursive(getLabels()));
}
monitor.beginTask("辞書の更新", 4); //$NON-NLS-1$
boolean result;
result = commitLabel(getLabels());
if (!result)
return result;
/* ラベルに紐付く用語をコミット */
/* DicLabelDao.insertRecords を置換する。 */
for (ILabel label : tmpList) {
for (ITerm term : label.getTerms()) {
RelCommonLabelBean relComLabel = (RelCommonLabelBean) CommonCreateQuery.getRelCommonLabelQuery(label.getId(), getId(), term.getId())
.uniqueResult();
// rel_common_labelに無いラベルのみInsert
if (relComLabel == null) {
/* トランザクション開始 */
session.beginTransaction();
relComLabel = new RelCommonLabelBean();
relComLabel.setLabelId(label.getId());
relComLabel.setDicId(getId());
relComLabel.setItemId(term.getId());
relComLabel.setValue(0);
relComLabel.setMathFlag(false);
session.save(relComLabel);
session.flush();
/* トランザクションコミット */
session.getTransaction().commit();
relComLabel = (RelCommonLabelBean) CommonCreateQuery.getRelCommonLabelQuery(label.getId(), getId(), term.getId()).uniqueResult();
if (relComLabel == null) {
result = false;
}
} else {
// 「ON DUPLICATE KEY ...」に対応(UPDATE)
/* トランザクション開始 */
session.beginTransaction();
relComLabel.setValue(0);
relComLabel.setMathFlag(false);
session.save(relComLabel);
session.flush();
/* トランザクションコミット */
session.getTransaction().commit();
}
}
}
if (!result)
return result;
monitor.worked(1);
/* ラベルツリー構造をコミット */
for (ILabel label : tmpList) {
if (label.getChildren() == null) {
continue;
}
for (ILabel child : label.getChildren()) {
LabelTreePKBean pk = new LabelTreePKBean();
pk.setParentId(label.getId());
pk.setChildId(child.getId());
LabelTreeBean labelTree = (LabelTreeBean) session.get(LabelTreeBean.class, pk);
if (labelTree == null) {
/* トランザクション開始 */
session.beginTransaction();
labelTree = new LabelTreeBean();
labelTree.setPrimaryKeyBean(new LabelTreePKBean());
labelTree.getPrimaryKeyBean().setParentId(label.getId());
labelTree.getPrimaryKeyBean().setChildId(child.getId());
session.save(labelTree);
session.flush();
/* トランザクションコミット */
session.getTransaction().commit();
}
}
}
if (!result)
return result;
monitor.worked(1);
/* ラベルの紐付けを外した用語のリレーションを削除 */
result = deleteRelCommon(tmpList);
monitor.worked(1);
/* 削除対象のデータをコミット */
if (delItems.size() > 0) {
for (IDicItem item : delItems) {
if (item != null) {
tmpDelList.add((ILabel) item);
}
}
result = deleteLabel(tmpDelList);
}
monitor.worked(1);
/* 検索用Map作成 */
itemsForSearch.clear();
for (ILabel item : getLabelsRecursive(getLabels())) {
itemsForSearch.put(item.getId(), item);
}
delItems.clear();
monitor.done();
return result;
} catch (HibernateException e) {
e.printStackTrace();
return false;
} finally {
if (session.getTransaction().isActive()) {
/* トランザクションロールバック */
session.getTransaction().rollback();
}
}
}
/**
* リレーション削除
*
* @param list
* @return boolean
*/
private static boolean deleteRelCommon(List<ILabel> list) throws HibernateException {
boolean result = true;
try {
for (ILabel label : list) {
/* 用語とのリレーションを削除 */
List<ITerm> terms = ((LabelItem) label).getDelTerms();
StringBuilder strId = new StringBuilder(100);
if (terms.size() > 0) {
for (ITerm term : terms) {
if (term != null) {
strId.append(",").append(term.getId()); //$NON-NLS-1$
}
}
/* 紐づけを削除 */
String strSQL = "DELETE FROM REL_COMMON_LABEL WHERE LABEL_ID = " + label.getId(); //$NON-NLS-1$
if (strId.substring(1).length() > 0) {
strSQL = strSQL + " AND ITEM_ID IN (" + strId.substring(1) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
}
/* トランザクション開始 */
Session session = IoService.getInstance().getSession();
session.beginTransaction();
session.createSQLQuery(strSQL).executeUpdate();
session.flush();
/* トランザクションコミット */
session.getTransaction().commit();
((LabelItem) label).clearDelTerms();
}
}
} catch (HibernateException e) {
throw e;
} finally {
if (IoService.getInstance().getSession().getTransaction().isActive()) {
/* トランザクションロールバック */
IoService.getInstance().getSession().getTransaction().rollback();
}
}
return result;
}
/**
* ラベルリストを取得
*
* @param list
*/
@Override
public List<ILabel> getLabelsRecursive(List<ILabel> list) {
List<ILabel> outList = new ArrayList<ILabel>();
for (ILabel item : list) {
outList.add(item);
/* 子供チェック */
if (item.getChildren().size() > 0) {
outList.addAll(getLabelsRecursive(item.getChildren()));
}
}
return outList;
}
/**
* 辞書情報の更新
*
* @return 情報取得したらtrue、失敗したらfalse
*/
public boolean updateDicInformation() {
try {
DicTableBean dicTable = (DicTableBean) CommonCreateQuery.getDicTableQuery(this.getId()).uniqueResult();
if (dicTable != null) {
if (!dicTable.isInactive()) {
this._name = dicTable.getDicName();
this._creationTime = dicTable.getCreationTime();
this._lasted = dicTable.getDate();
this.setParentIds(CoronaIoUtils.stringToIntSet(dicTable.getParentId()));
this.setDirty(false);
}
} else {
/* 更新対象が無い場合、失敗と判定(jdbc版では成功としている) */
return false;
}
return true;
} catch (HibernateException e) {
e.printStackTrace();
return false;
}
}
@Override
public boolean update() {
updateDicInformation();
bRefreshRecords = false;
return true;
}
@Override
public boolean updateRecords() {
try {
// 取得した結果のインデックス
int labelIdNum = 0;
int dicIdNum = 1;
int labelNameNum = 2;
int parentIdNum = 4;
bRefreshRecords = true;
if (items == null) {
items = new ArrayList<IDicItem>();
itemsForSearch = new TreeMap<Integer, IDicItem>();
} else {
items.clear();
}
delItems.clear(); /* itemsが更新されるので、削除マークアイテムはクリアされるべき by Morishima */
/*
* 最後までここに残っていたものは、削除されたアイテム DBを複数人で使う場合以外には効力を発揮しないと思われる
*/
List<IDicItem> deletedItems = new ArrayList<IDicItem>(itemsForSearch.values());
@SuppressWarnings("unchecked")
List<Object[]> resultList = CommonCreateQuery.getDicLabelJoinLabelTreeQuery(getId()).list();
/* 取得結果編集 */
for (Object[] result : resultList) {
int labelId = result[labelIdNum] == null ? 0 : Integer.parseInt(result[labelIdNum].toString());
ILabel newLabel = findItem(labelId);
if (newLabel == null) {
newLabel = DicFactory.getInstance().createLabel((String) result[labelNameNum], null);
newLabel.setId(labelId);
itemsForSearch.put(newLabel.getId(), newLabel);
} else {
newLabel.setName((String) result[labelNameNum]);
newLabel.getChildren().clear();
deletedItems.remove(newLabel);
}
// 複数親は持たない
((LabelItem) newLabel).setParentId(result[parentIdNum] == null ? 0 : Integer.parseInt(result[parentIdNum].toString()));
((LabelItem) newLabel).setDicId((int) result[dicIdNum]);
newLabel.setDirty(false); // updateLabelTermでもやっているから冗長ではある
}
for (IDicItem label : deletedItems) {
itemsForSearch.remove(label.getId());
}
/* 親子関係の帳尻を合わせる */
for (IDicItem item : itemsForSearch.values()) {
/* 自身の親をマッピング */
LabelItem label = (LabelItem) item;
ILabel parent = findItem(label.getParentId());
if (parent == null) {
items.add(item);
} else {
label.setParent(parent);
}
item.setDirty(false);
}
/* 用語を更新 */
updateLabelTerms();
this.setDirty(false);
/* 更新日を最新へ設定 */
@SuppressWarnings("unchecked")
List<DicTableBean> dicTableList = CommonCreateQuery.getDicTableQuery(getId()).list();
if (dicTableList != null) {
for (DicTableBean dicTable : dicTableList) {
this.setLasted(dicTable.getDate());
}
}
return true;
} catch (HibernateException e) {
bRefreshRecords = false;
e.printStackTrace();
return false;
}
}
private boolean updateLabelTerms() {
/* 代表表記情報取得 */
List<ICoronaDic> parentDics = ((IoService) IoService.getInstance()).getDictionary(getParentIds());
try {
String para1 = "DIC_ID"; //$NON-NLS-1$
String hql = "FROM RelCommonLabelBean AS a, DicCommonBean AS b WHERE a.dicId=:"; //$NON-NLS-1$
hql += para1 + " AND a.itemId = b.itemId AND b.inactive = false"; //$NON-NLS-1$
Session session = IoService.getInstance().getSession();
@SuppressWarnings("unchecked")
List<Object[]> relComLabelList = session.createQuery(hql).setInteger(para1, getId()).list();
/* データ取得処理でエラー発生でない場合に、以下が実施される。 */
/* DBに保存されていない「ラベル-単語」のひもづけを消すためのSet */
for (Entry<Integer, IDicItem> e : itemsForSearch.entrySet()) {
((ILabel) e.getValue()).getTerms().clear();
}
for (Object[] rs : relComLabelList) {
RelCommonLabelBean relComLabel = (RelCommonLabelBean) rs[0];
ILabel label = findItem(relComLabel.getLabelId());
if (label != null) {
int itemId = relComLabel.getItemId();
Term term = null;
for (ICoronaDic pdic : parentDics) {
if (pdic instanceof IUserDic) {
term = (Term) ((UserDic) pdic).getItem(itemId);
if (term != null) {
break;
}
}
}
if (term != null) {
label.addTerm(term);
}
}
}
for (Entry<Integer, IDicItem> e : itemsForSearch.entrySet()) {
e.getValue().setDirty(false);
}
return true;
} catch (HibernateException e) {
e.printStackTrace();
return false;
}
}
@Override
public int getItemCount() {
if (items == null) {
try {
// DicCommonDao.getItemCount の機能を移設
String hql = "Select count(*) From DicLabelBean where dicId = :DIC_ID and inactive = false "; //$NON-NLS-1$
Object rs = IoService.getInstance().getSession().createQuery(hql).setInteger("DIC_ID", getId()).uniqueResult(); //$NON-NLS-1$
int ret = rs == null ? 0 : Integer.parseInt(rs.toString());
return ret;
} catch (HibernateException e) {
e.printStackTrace();
return 0;
}
}
return items.size();
}
@Override
public List<IDicItem> getItems() {
if (!bRefreshRecords) {
updateRecords();
}
return super.getItems();
}
@Override
public List<ILabel> getLabels() {
List<ILabel> list = new ArrayList<ILabel>();
if (!bRefreshRecords || (items == null)) {
updateRecords();
}
for (IDicItem item : items) {
list.add((ILabel) item);
}
return list;
}
@Override
public void addItem(IDicItem item) {
if (!bRefreshRecords || (items == null)) {
updateRecords();
}
super.addItem(item);
}
@Override
public void removeItem(IDicItem item) {
if (!bRefreshRecords || (items == null)) {
updateRecords();
}
super.removeItem(item);
}
/**
* ラベルを検索
*
* @param itemId
* @return itemIdに一致するラベルアイテムを返す
*/
private ILabel findItem(int itemId) {
if (itemId <= IDicItem.UNSAVED_ID) {
return null;
}
return (ILabel) itemsForSearch.get(itemId);
}
/**
* ラベルアイテムをセットする
*
* @param items
* @param bImpFlg
*/
public void setItems(List<IDicItem> items, boolean bImpFlg) {
/*
* TODO どうせitemsで上書きされるんだから、updateRecordsする意味はない.
* そして上書き後、flatLabelMapの更新、delItemsのクリアはしないといけない
* 現状では、このメソッドの直後にdoCommitが呼ばれ、そこで処理されているので何もしない
*/
bRefreshRecords = true;
super.setItems(items);
}
/**
* アイテム取得
*
* @param id
* @return ITerm
*/
@Override
public IDicItem getItem(int id) {
if (!bRefreshRecords) {
updateRecords();
}
return itemsForSearch.get(id);
}
@Override
public boolean isDicRelationDirty(int dicId) {
List<ILabel> tmpList = new ArrayList<ILabel>();
if (getItems().size() > 0) {
tmpList.addAll(getLabelsRecursive(getLabels()));
}
for (ILabel label : tmpList) {
LabelItem item = (LabelItem) label;
if (label.isDirty()) {
/* 追加のチェック */
for (ITerm term : label.getTerms()) {
if (term.getComprehensionDicId() == dicId) {
return true;
}
}
/* 削除のチェック */
for (ITerm term : item.getDelTerms()) {
if (term.getComprehensionDicId() == dicId) {
return true;
}
}
}
}
/* 削除ラベルのチェック */
for (IDicItem item : delItems) {
ILabel label = (ILabel) item;
for (ITerm term : label.getTerms()) {
if (term.getComprehensionDicId() == dicId) {
return true;
}
}
}
return false;
}
}