/* * Copyright 2004-2015 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; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import org.seasar.extension.jdbc.exception.ColumnDuplicatedRuntimeException; import org.seasar.extension.jdbc.exception.EntityColumnNotFoundRuntimeException; import org.seasar.extension.jdbc.exception.PropertyDuplicatedRuntimeException; import org.seasar.extension.jdbc.exception.PropertyNotFoundRuntimeException; import org.seasar.framework.util.ArrayMap; import org.seasar.framework.util.CaseInsensitiveMap; /** * エンティティのメタデータです。 * * @author higa * */ public class EntityMeta { /** * 名前です。 */ protected String name; /** * エンティティクラスです。 */ protected Class<?> entityClass; /** * テーブルメタデータです。 */ protected TableMeta tableMeta; /** * プロパティメタデータの配列マップです。 */ protected CaseInsensitiveMap propertyMetaMap = new CaseInsensitiveMap(); /** * 追加情報の配列マップです。 */ protected ArrayMap additionalInfoMap = new ArrayMap(); /** * 識別子になっているプロパティメタデータのリストです。 */ protected List<PropertyMeta> idPropertyMetaList = new ArrayList<PropertyMeta>(); /** * バージョンを表すプロパティメタデータです。 */ protected PropertyMeta versionPropertyMeta; /** * MappedByで注釈されているプロパティメタデータのマップです。 */ protected CaseInsensitiveMap mappedByPropertyMetaMap = new CaseInsensitiveMap(); /** * カラム名をキーにしたプロパティメタデータの配列マップです。 */ protected CaseInsensitiveMap columnPropertyMetaMap = new CaseInsensitiveMap(); /** * 関連が解決されたかどうかです。 */ protected volatile boolean relationshipResolved = false; /** * {@link EntityMeta}を作成します。 */ public EntityMeta() { } /** * {@link EntityMeta}を作成します。 * * @param name * 名前 */ public EntityMeta(String name) { setName(name); } /** * 名前を返します。 * * @return 名前 */ public String getName() { return name; } /** * 名前を設定します。 * * @param name * 名前 */ public void setName(String name) { this.name = name; } /** * エンティティクラスを返します。 * * @return エンティティクラス */ public Class<?> getEntityClass() { return entityClass; } /** * エンティティクラスを設定します。 * * @param entityClass * エンティティクラス */ public void setEntityClass(Class<?> entityClass) { this.entityClass = entityClass; } /** * テーブルメタデータを返します。 * * @return テーブルメタデータ */ public TableMeta getTableMeta() { return tableMeta; } /** * テーブルメタデータを設定します。 * * @param tableMeta * テーブルメタデータ */ public void setTableMeta(TableMeta tableMeta) { this.tableMeta = tableMeta; } /** * プロパティメタデータを返します。 * * @param propertyName * プロパティ名 * @return プロパティメタデータ * @throws PropertyNotFoundRuntimeException * プロパティメタデータが見つからない場合 * */ public PropertyMeta getPropertyMeta(String propertyName) throws PropertyNotFoundRuntimeException { PropertyMeta meta = (PropertyMeta) propertyMetaMap.get(propertyName); if (meta == null) { throw new PropertyNotFoundRuntimeException(name, propertyName); } return meta; } /** * カラムに結びつくプロパティメタデータを返します。 * * @param columnName * カラム名 * @return プロパティメタデータ * @throws EntityColumnNotFoundRuntimeException * カラム用のプロパティメタデータが見つからない場合 * */ public PropertyMeta getColumnPropertyMeta(String columnName) throws EntityColumnNotFoundRuntimeException { PropertyMeta meta = (PropertyMeta) columnPropertyMetaMap .get(columnName); if (meta == null) { throw new EntityColumnNotFoundRuntimeException(name, columnName); } return meta; } /** * プロパティメタデータがあるかどうかを返します。 * * @param propertyName * プロパティ名 * @return プロパティメタデータがあるかどうか */ public boolean hasPropertyMeta(String propertyName) { return propertyMetaMap.containsKey(propertyName); } /** * カラムに結びつくプロパティメタデータがあるかどうかを返します。 * * @param columnName * カラム名 * @return プロパティメタデータがあるかどうか */ public boolean hasColumnPropertyMeta(String columnName) { return columnPropertyMetaMap.containsKey(columnName); } /** * プロパティメタデータの数を返します。 * * @return プロパティメタデータの数 */ public int getPropertyMetaSize() { return propertyMetaMap.size(); } /** * カラムに結びつくプロパティメタデータの数を返します。 * * @return カラムに結びつくプロパティメタデータの数 */ public int getColumnPropertyMetaSize() { return columnPropertyMetaMap.size(); } /** * プロパティメタデータを返します。 * * @param index * インデックス * @return プロパティメタデータ */ public PropertyMeta getPropertyMeta(int index) { return (PropertyMeta) propertyMetaMap.get(index); } /** * 全てのプロパティメタデータの{@link Iterable}を返します。 * * @return 全てのプロパティメタデータの{@link Iterable} */ public Iterable<PropertyMeta> getAllPropertyMeta() { return new Iterable<PropertyMeta>() { public Iterator<PropertyMeta> iterator() { return new Iterator<PropertyMeta>() { private int i; public boolean hasNext() { return i < propertyMetaMap.size(); } public PropertyMeta next() { return PropertyMeta.class .cast(propertyMetaMap.get(i++)); } public void remove() { throw new UnsupportedOperationException(); } }; } }; } /** * カラムに結びつくプロパティメタデータを返します。 * * @param index * カラムインデックス * @return プロパティメタデータ */ public PropertyMeta getColumnPropertyMeta(int index) { return (PropertyMeta) columnPropertyMetaMap.get(index); } /** * カラムに結びつく全てのプロパティメタデータの{@link Iterable}を返します。 * * @return カラムに結びつく全てのプロパティメタデータの{@link Iterable} */ public Iterable<PropertyMeta> getAllColumnPropertyMeta() { return new Iterable<PropertyMeta>() { public Iterator<PropertyMeta> iterator() { return new Iterator<PropertyMeta>() { private int i; public boolean hasNext() { return i < columnPropertyMetaMap.size(); } public PropertyMeta next() { return PropertyMeta.class.cast(columnPropertyMetaMap .get(i++)); } public void remove() { throw new UnsupportedOperationException(); } }; } }; } /** * 識別子になっているプロパティメタデータのリストを返します。 * * @return 識別子になっているプロパティメタデータのリスト */ public List<PropertyMeta> getIdPropertyMetaList() { return idPropertyMetaList; } /** * バージョンを表すプロパティメタデータがあれば<code>true</code>を返します。 * * @return バージョンを表すプロパティメタデータがあれば<code>true</code> */ public boolean hasVersionPropertyMeta() { return versionPropertyMeta != null; } /** * バージョンを表すプロパティメタデータを返します。 * * @return バージョンを表すプロパティメタデータ */ public PropertyMeta getVersionPropertyMeta() { return versionPropertyMeta; } /** * MappedByで注釈されているプロパティメタデータを返します。 * * @param mappedBy * 関連の所有者側のプロパティ名 * @param relationshipClass * 関連クラス * @return MappedByで注釈されているプロパティメタデータ */ @SuppressWarnings("unchecked") public PropertyMeta getMappedByPropertyMeta(String mappedBy, Class<?> relationshipClass) { Map m = (Map) mappedByPropertyMetaMap.get(mappedBy); if (m == null) { return null; } return (PropertyMeta) m.get(relationshipClass.getName()); } /** * プロパティメタデータを追加します。 * * @param propertyMeta * プロパティメタデータ */ public void addPropertyMeta(PropertyMeta propertyMeta) { if (propertyMetaMap.put(propertyMeta.getName(), propertyMeta) != null) { throw new PropertyDuplicatedRuntimeException(name, propertyMeta .getName()); } if (propertyMeta.isId()) { idPropertyMetaList.add(propertyMeta); } if (propertyMeta.isVersion()) { versionPropertyMeta = propertyMeta; } if (propertyMeta.getMappedBy() != null) { CaseInsensitiveMap m = (CaseInsensitiveMap) mappedByPropertyMetaMap .get(propertyMeta.getMappedBy()); if (m == null) { m = new CaseInsensitiveMap(); mappedByPropertyMetaMap.put(propertyMeta.getMappedBy(), m); } m.put(propertyMeta.getRelationshipClass().getName(), propertyMeta); } if (propertyMeta.getColumnMeta() != null) { String columnName = propertyMeta.getColumnMeta().getName(); PropertyMeta pm2 = (PropertyMeta) columnPropertyMetaMap.put( columnName, propertyMeta); if (pm2 != null) { throw new ColumnDuplicatedRuntimeException(name, pm2.getName(), propertyMeta.getName(), columnName); } } } /** * 関連が解決されたかどうかを返します。 * * @return 関連が解決されたかどうか */ public boolean isRelationshipResolved() { return relationshipResolved; } /** * 関連が解決されたかどうかを設定します。 * * @param relationshipResolved * 関連が解決されたかどうか */ public void setRelationshipResolved(boolean relationshipResolved) { this.relationshipResolved = relationshipResolved; } /** * 名前に対応した追加情報を返します。 * * @param name * 名前 * @return 追加情報 */ public Object getAdditionalInfo(String name) { return additionalInfoMap.get(name); } /** * 追加情報のサイズを返します。 * * @return 追加情報のサイズ */ public int getAdditionalInfoSize() { return additionalInfoMap.size(); } /** * インデックスに対応した追加情報を返します。 * * @param index * インデックス * @return 追加情報 */ public Object getAdditionalInfo(int index) { return additionalInfoMap.get(index); } /** * 追加情報を追加します。 * * @param name * 名前 * @param additionalInfo * 追加情報 */ public void addAdditionalInfo(String name, Object additionalInfo) { additionalInfoMap.put(name, additionalInfo); } }