Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
S2JDBC-GenのTableDescFactoryImplのJava7対応。 ソートのロジックが変わったことによる影響を回避。 http://seasarproject.g.hatena.ne.jp/halflite/20130305/s2jdbcgen3
/*
* Copyright 2004-2013 the Seasar Foundation and the Others.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package org.seasar.extension.jdbc.gen.internal.desc;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import org.seasar.extension.jdbc.EntityMeta;
import org.seasar.extension.jdbc.PropertyMeta;
import org.seasar.extension.jdbc.TableMeta;
import org.seasar.extension.jdbc.gen.desc.ColumnDesc;
import org.seasar.extension.jdbc.gen.desc.ColumnDescFactory;
import org.seasar.extension.jdbc.gen.desc.ForeignKeyDesc;
import org.seasar.extension.jdbc.gen.desc.ForeignKeyDescFactory;
import org.seasar.extension.jdbc.gen.desc.IdTableDescFactory;
import org.seasar.extension.jdbc.gen.desc.PrimaryKeyDesc;
import org.seasar.extension.jdbc.gen.desc.PrimaryKeyDescFactory;
import org.seasar.extension.jdbc.gen.desc.SequenceDesc;
import org.seasar.extension.jdbc.gen.desc.SequenceDescFactory;
import org.seasar.extension.jdbc.gen.desc.TableDesc;
import org.seasar.extension.jdbc.gen.desc.TableDescFactory;
import org.seasar.extension.jdbc.gen.desc.UniqueKeyDesc;
import org.seasar.extension.jdbc.gen.desc.UniqueKeyDescFactory;
import org.seasar.extension.jdbc.gen.dialect.GenDialect;
import org.seasar.extension.jdbc.gen.internal.util.AnnotationUtil;
import org.seasar.extension.jdbc.gen.internal.util.EntityMetaUtil;
import org.seasar.extension.jdbc.gen.internal.util.TableUtil;
/**
* {@link TableDescFactory}の実装クラスです。
*
* @author taedium
*/
public class TableDescFactoryImpl implements TableDescFactory {
/** テーブルの完全修飾名をキー、テーブル記述を値とするマップ */
protected ConcurrentMap<String, TableDesc> tableDescMap = new ConcurrentHashMap<String, TableDesc>(
200);
/** 方言 */
protected GenDialect dialect;
/** カラム記述のファクトリ */
protected ColumnDescFactory columnDescFactory;
/** 主キー記述のファクトリ */
protected PrimaryKeyDescFactory primaryKeyDescFactory;
/** 外部キー記述のファクトリ */
protected ForeignKeyDescFactory foreignKeyDescFactory;
/** 一意キー記述のファクトリ */
protected UniqueKeyDescFactory uniqueKeyDescFactory;
/** シーケンス記述のファクトリ */
protected SequenceDescFactory sequenceDescFactory;
/** 識別子生成用のテーブル記述のファクトリ */
protected IdTableDescFactory idTableDescFactory;
/**
* インスタンスを構築します。
*
* @param dialect
* 方言
* @param columnDescFactory
* カラム記述のファクトリ
* @param primaryKeyDescFactory
* 主キー記述のファクトリ
* @param uniqueKeyDescFactory
* 一意キー記述のファクトリ
* @param foreignKeyDescFactory
* 外部キー記述のファクトリ
* @param sequenceDescFactory
* シーケンス記述のファクトリ
* @param idTableDescFactory
* 識別子生成用のテーブル記述のファクトリ
*/
public TableDescFactoryImpl(GenDialect dialect,
ColumnDescFactory columnDescFactory,
PrimaryKeyDescFactory primaryKeyDescFactory,
UniqueKeyDescFactory uniqueKeyDescFactory,
ForeignKeyDescFactory foreignKeyDescFactory,
SequenceDescFactory sequenceDescFactory,
IdTableDescFactory idTableDescFactory) {
if (dialect == null) {
throw new NullPointerException("dialect");
}
if (columnDescFactory == null) {
throw new NullPointerException("columnDescFactory");
}
if (primaryKeyDescFactory == null) {
throw new NullPointerException("primaryKeyDescFactory");
}
if (uniqueKeyDescFactory == null) {
throw new NullPointerException("uniqueKeyDescFactory");
}
if (foreignKeyDescFactory == null) {
throw new NullPointerException("foreignKeyDescFactory");
}
if (sequenceDescFactory == null) {
throw new NullPointerException("sequenceDescFactory");
}
if (idTableDescFactory == null) {
throw new NullPointerException("idTableDescFactory");
}
this.dialect = dialect;
this.columnDescFactory = columnDescFactory;
this.primaryKeyDescFactory = primaryKeyDescFactory;
this.uniqueKeyDescFactory = uniqueKeyDescFactory;
this.foreignKeyDescFactory = foreignKeyDescFactory;
this.sequenceDescFactory = sequenceDescFactory;
this.idTableDescFactory = idTableDescFactory;
}
public TableDesc getTableDesc(EntityMeta entityMeta) {
String fullName = entityMeta.getTableMeta().getFullName().toLowerCase();
TableDesc tableDesc = tableDescMap.get(fullName);
if (tableDesc != null) {
return tableDesc;
}
tableDesc = createTableDesc(entityMeta);
tableDescMap.put(fullName, tableDesc);
return tableDesc;
}
/**
* テーブル記述を作成します。
*
* @param entityMeta
* エンティティメタデータ
* @return テーブル記述
*/
protected TableDesc createTableDesc(EntityMeta entityMeta) {
Table table = getTable(entityMeta);
TableDesc tableDesc = new TableDesc();
doName(entityMeta, tableDesc, table);
doComment(entityMeta, tableDesc, table);
doPrimaryKeyDesc(entityMeta, tableDesc, table);
doColumnDesc(entityMeta, tableDesc, table);
doForeignKeyDesc(entityMeta, tableDesc, table);
doUniqueKeyDesc(entityMeta, tableDesc, table);
doSequenceDesc(entityMeta, tableDesc, table);
doIdTableDesc(entityMeta, tableDesc, table);
return tableDesc;
}
/**
* 名前を処理します。
*
* @param entityMeta
* エンティティメタデータ
* @param tableDesc
* テーブル記述
* @param table
* テーブル
*/
protected void doName(EntityMeta entityMeta, TableDesc tableDesc,
Table table) {
TableMeta tableMeta = entityMeta.getTableMeta();
tableDesc.setCatalogName(tableMeta.getCatalog());
tableDesc.setSchemaName(tableMeta.getSchema());
tableDesc.setName(tableMeta.getName());
tableDesc.setCanonicalName(buildCanonicalName(tableMeta));
}
/**
* コメントを処理します。
*
* @param entityMeta
* エンティティメタデータ
* @param tableDesc
* テーブル記述
* @param table
* テーブル
*/
protected void doComment(EntityMeta entityMeta, TableDesc tableDesc,
Table table) {
String comment = EntityMetaUtil.getComment(entityMeta);
tableDesc.setComment(comment);
}
/**
* 標準名を組み立てます。
*
* @param tableMeta
* テーブルメタデータ
* @return 標準名
*/
protected String buildCanonicalName(TableMeta tableMeta) {
return TableUtil.buildCanonicalTableName(dialect,
tableMeta.getCatalog(), tableMeta.getSchema(),
tableMeta.getName());
}
/**
* カラム記述を処理します。
*
* @param entityMeta
* エンティティメタデータ
* @param tableDesc
* テーブル記述
* @param table
* テーブル
*/
protected void doColumnDesc(EntityMeta entityMeta,
final TableDesc tableDesc, Table table) {
List<ColumnDescRef> columnDescRefList = new ArrayList<ColumnDescRef>();
for (int i = 0; i < entityMeta.getColumnPropertyMetaSize(); i++) {
PropertyMeta propertyMeta = entityMeta.getColumnPropertyMeta(i);
ColumnDesc columnDesc = columnDescFactory.getColumnDesc(entityMeta,
propertyMeta);
if (columnDesc != null) {
columnDescRefList.add(new ColumnDescRef(i, columnDesc));
}
}
Collections.sort(columnDescRefList,
createColumnDescRefComparator(tableDesc));
for (ColumnDescRef columnDescRef : columnDescRefList) {
tableDesc.addColumnDesc(columnDescRef.columnDesc);
}
}
/**
* 主キー記述を処理します。
*
* @param entityMeta
* エンティティメタデータ
* @param tableDesc
* テーブル記述
* @param table
* テーブル
*/
protected void doPrimaryKeyDesc(EntityMeta entityMeta, TableDesc tableDesc,
Table table) {
PrimaryKeyDesc primaryKeyDesc = primaryKeyDescFactory
.getPrimaryKeyDesc(entityMeta);
if (primaryKeyDesc != null) {
tableDesc.setPrimaryKeyDesc(primaryKeyDesc);
}
}
/**
* 外部キー記述を処理します。
*
* @param entityMeta
* エンティティメタデータ
* @param tableDesc
* テーブル記述
* @param table
* テーブル
*/
protected void doForeignKeyDesc(EntityMeta entityMeta, TableDesc tableDesc,
Table table) {
for (int i = 0; i < entityMeta.getPropertyMetaSize(); i++) {
PropertyMeta propertyMeta = entityMeta.getPropertyMeta(i);
ForeignKeyDesc foreignKeyDesc = foreignKeyDescFactory
.getForeignKeyDesc(entityMeta, propertyMeta);
if (foreignKeyDesc != null) {
tableDesc.addForeignKeyDesc(foreignKeyDesc);
}
}
}
/**
* 一意キー記述を処理します。
*
* @param entityMeta
* エンティティメタデータ
* @param tableDesc
* テーブル記述
* @param table
* テーブル
*/
protected void doUniqueKeyDesc(EntityMeta entityMeta, TableDesc tableDesc,
Table table) {
String singlePkColumnName = null;
PrimaryKeyDesc primaryKeyDesc = tableDesc.getPrimaryKeyDesc();
if (primaryKeyDesc != null
&& primaryKeyDesc.getColumnNameList().size() == 1) {
singlePkColumnName = primaryKeyDesc.getColumnNameList().get(0);
}
for (ColumnDesc columnDesc : tableDesc.getColumnDescList()) {
if (columnDesc.getName().equals(singlePkColumnName)) {
continue;
}
UniqueKeyDesc uniqueKeyDesc = uniqueKeyDescFactory
.getSingleUniqueKeyDesc(columnDesc);
if (uniqueKeyDesc != null) {
tableDesc.addUniqueKeyDesc(uniqueKeyDesc);
}
}
for (UniqueConstraint uc : table.uniqueConstraints()) {
UniqueKeyDesc uniqueKeyDesc = uniqueKeyDescFactory
.getCompositeUniqueKeyDesc(uc);
if (uniqueKeyDesc != null) {
tableDesc.addUniqueKeyDesc(uniqueKeyDesc);
}
}
}
/**
* シーケンス記述を処理します。
*
* @param entityMeta
* エンティティメタデータ
* @param tableDesc
* テーブル記述
* @param table
* テーブル
*/
protected void doSequenceDesc(EntityMeta entityMeta, TableDesc tableDesc,
Table table) {
for (PropertyMeta propertyMeta : entityMeta.getIdPropertyMetaList()) {
SequenceDesc sequenceDesc = sequenceDescFactory.getSequenceDesc(
entityMeta, propertyMeta);
if (sequenceDesc != null) {
tableDesc.addSequenceDesc(sequenceDesc);
}
}
}
/**
* 識別子生成用のテーブル記述を処理します。
*
* @param entityMeta
* エンティティメタデータ
* @param tableDesc
* テーブル記述
* @param table
* テーブル
*/
protected void doIdTableDesc(EntityMeta entityMeta, TableDesc tableDesc,
Table table) {
for (PropertyMeta propertyMeta : entityMeta.getIdPropertyMetaList()) {
TableDesc idTableDesc = idTableDescFactory.getTableDesc(entityMeta,
propertyMeta);
if (idTableDesc == null) {
continue;
}
tableDesc.addIdTableDesc(idTableDesc);
String fullName = idTableDesc.getFullName().toLowerCase();
TableDesc cache = tableDescMap.get(fullName);
if (cache == null) {
tableDescMap.put(fullName, idTableDesc);
} else {
cache.setCatalogName(idTableDesc.getCatalogName());
cache.setSchemaName(idTableDesc.getSchemaName());
cache.setName(idTableDesc.getName());
cache.setPrimaryKeyDesc(idTableDesc.getPrimaryKeyDesc());
for (ColumnDesc columnDesc : idTableDesc.getColumnDescList()) {
cache.addColumnDesc(columnDesc);
}
for (UniqueKeyDesc uniqueKeyDesc : idTableDesc
.getUniqueKeyDescList()) {
cache.addUniqueKeyDesc(uniqueKeyDesc);
}
}
}
}
/**
* テーブルを取得します。
*
* @param entityMeta
* エンティティメタデータ
* @return テーブル
*/
protected Table getTable(EntityMeta entityMeta) {
Class<?> clazz = entityMeta.getEntityClass();
Table table = clazz.getAnnotation(Table.class);
return table != null ? table : AnnotationUtil.getDefaultTable();
}
/**
* カラム記述の{@link Comparator}を作成します。
*
* @param tableDesc
* テーブル記述
* @return カラム記述の{@link Comparator}
*/
protected Comparator<ColumnDescRef> createColumnDescRefComparator(
TableDesc tableDesc) {
final List<String> pkColumnNameList = new ArrayList<String>();
if (tableDesc.getPrimaryKeyDesc() != null) {
PrimaryKeyDesc primaryKeyDesc = tableDesc.getPrimaryKeyDesc();
pkColumnNameList.addAll(primaryKeyDesc.getColumnNameList());
}
return new Comparator<ColumnDescRef>() {
@Override
public int compare(ColumnDescRef o1, ColumnDescRef o2) {
int index1 = pkColumnNameList.indexOf(o1.columnDesc.getName());
int index2 = pkColumnNameList.indexOf(o2.columnDesc.getName());
int ret = 0;
if (index1 < 0) {
if (index2 < 0) {
ret = o1.index - o2.index;
} else {
ret = 1;
}
} else {
if (index2 < 0) {
ret = -1;
} else {
ret = index1 - index2;
}
}
return ret;
}
};
}
private static class ColumnDescRef {
int index = 0;
ColumnDesc columnDesc;
ColumnDescRef(int index, ColumnDesc columnDesc) {
this.index = index;
this.columnDesc = columnDesc;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment