org.seasar.hibernate.jpa.metadata.HibernateAttributeDesc.java Source code

Java tutorial

Introduction

Here is the source code for org.seasar.hibernate.jpa.metadata.HibernateAttributeDesc.java

Source

/*
 * Copyright 2004-2010 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.hibernate.jpa.metadata;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.sql.Types;
import java.util.List;
import java.util.Map;

import org.hibernate.EntityMode;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.persister.entity.AbstractEntityPersister;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.type.AbstractComponentType;
import org.hibernate.type.CustomType;
import org.hibernate.type.EntityType;
import org.hibernate.type.Type;
import org.seasar.framework.util.ClassUtil;
import org.seasar.framework.util.tiger.CollectionsUtil;
import org.seasar.framework.util.tiger.ReflectionUtil;

/**
 * Hibernate????
 * 
 * @author koichik
 */
public class HibernateAttributeDesc extends AbstractHibernateAttributeDesc {

    /** {@link AbstractEntityPersister}?<code>propertySelectable</code> */
    protected static final Field PROPERTY_SELECTABLE_FIELD = ClassUtil
            .getDeclaredField(AbstractEntityPersister.class, "propertySelectable");
    static {
        PROPERTY_SELECTABLE_FIELD.setAccessible(true);
    }

    /** ? */
    protected final AbstractEntityPersister metadata;

    /** {@link Types SQL}??? */
    protected final int[] sqlTypes;

    /** ???? */
    protected final String[] tableNames;

    /** ????????? */
    protected final Map<String, String[]> columnNamesMap = CollectionsUtil.newHashMap();

    /** ????????? */
    protected final boolean readTarget;

    /** ??????????? */
    protected final boolean selectable;

    /**
     * ???
     * 
     * @param factory
     *            
     * @param metadata
     *            ?
     * @param name
     *            ??
     * @param id
     *            ???ID???????
     * @param version
     *            ????????????
     */
    public HibernateAttributeDesc(final SessionFactoryImplementor factory, final AbstractEntityPersister metadata,
            final String name, final boolean id, final boolean version) {
        super(factory, id ? metadata.getIdentifierType() : metadata.getPropertyType(name), name, id, version);

        this.metadata = metadata;
        sqlTypes = hibernateType.sqlTypes(factory);

        if (id) {
            readTarget = true;
        } else {
            readTarget = isReadTargetType(hibernateType);
        }

        selectable = isSelectableAttribute();
        tableNames = createTableNames();
        setupColumnNameMap();
    }

    /**
     * ????????
     * 
     * @return ????
     */
    protected String[] createTableNames() {
        if (id) {
            final String[] original = metadata.getConstraintOrderedTableNameClosure();
            final String[] tableNames = new String[original.length];
            System.arraycopy(original, 0, tableNames, 0, original.length);
            return tableNames;
        }
        return new String[] { metadata.getPropertyTableName(name) };
    }

    /**
     * ????????????
     */
    protected void setupColumnNameMap() {
        if (id) {
            for (int i = 0; i < getTableNameSize(); i++) {
                final String tableName = getTableName(i);
                final String[] originalColumnNames = metadata.getContraintOrderedTableKeyColumnClosure()[i];
                final String[] columnNames = new String[originalColumnNames.length];
                System.arraycopy(originalColumnNames, 0, columnNames, 0, originalColumnNames.length);
                columnNamesMap.put(tableName.toLowerCase(), columnNames);
            }
        } else {
            final String tableName = metadata.getPropertyTableName(name);
            final String[] originalColumnNames = metadata.getPropertyColumnNames(name);
            final String[] columnNames = new String[originalColumnNames.length];
            System.arraycopy(originalColumnNames, 0, columnNames, 0, originalColumnNames.length);
            columnNamesMap.put(tableName.toLowerCase(), columnNames);
        }
    }

    /**
     * ??<code>type</code>????<code>true</code>???
     * 
     * @param type
     *            Hibernate?
     * @return ??<code>type</code>????<code>true</code>????????<code>false</code>
     */
    protected boolean isReadTargetType(final Type type) {
        if (type.isCollectionType()) {
            return false;
        }
        if (type.isComponentType()) {
            if (AbstractComponentType.class.cast(type).isEmbedded()) {
                return false;
            }
        }
        if (type.isEntityType()) {
            if (EntityType.class.cast(type).isOneToOne()) {
                return false;
            }
        }
        return true;
    }

    /**
     * ????????<code>true</code>???
     * 
     * @return ????????<code>true</code>????????<code>false</code>
     */
    protected boolean isSelectableAttribute() {
        if (id) {
            return true;
        }
        final int index = metadata.getPropertyIndex(name);
        final boolean[] selectable = ReflectionUtil.getValue(PROPERTY_SELECTABLE_FIELD, metadata);
        return selectable[index];
    }

    public Object getValue(final Object entity) {
        if (id) {
            return metadata.getIdentifier(entity, EntityMode.POJO);
        }
        return metadata.getPropertyValue(entity, name, EntityMode.POJO);
    }

    public void setValue(final Object entity, final Object value) {
        if (id) {
            metadata.setIdentifier(entity, Serializable.class.cast(value), EntityMode.POJO);
        } else {
            metadata.setPropertyValue(entity, name, value, EntityMode.POJO);
        }
    }

    /**
     * {@link Types SQL}??????
     * 
     * @return {@link Types SQL}???
     */
    public int[] getSqlTypes() {
        return sqlTypes;
    }

    /**
     * ????????<code>true</code>???
     * 
     * @return ????????<code>true</code>????????<code>false</code>
     */
    public boolean isSelectable() {
        return selectable;
    }

    /**
     * Hibernate????
     * 
     * @return Hibernate?
     */
    public Type getHibernateType() {
        return hibernateType;
    }

    /**
     * ??????
     * 
     * @return ???
     */
    public int getTableNameSize() {
        return tableNames.length;
    }

    /**
     * ?????????
     * 
     * @param index
     *            
     * @return ??
     */
    public String getTableName(final int index) {
        return tableNames[index];
    }

    /**
     * ???????<code>true</code>???
     * 
     * @param tableName
     *            ??
     * @return ???????<code>true</code>????????<code>false</code>
     */
    public boolean hasTableName(final String tableName) {
        for (int i = 0; i < getTableNameSize(); i++) {
            if (getTableName(i).equalsIgnoreCase(tableName)) {
                return true;
            }
        }
        return false;
    }

    /**
     * ????????
     * 
     * @param tableName
     *            ??
     * @return ?????
     */
    public int getColumnNameSize(final String tableName) {
        return getColumnNames(tableName).length;
    }

    /**
     * ????????
     * 
     * @param index
     *            
     * @return ?
     */
    public int getColumnNameSize(final int index) {
        return getColumnNames(index).length;
    }

    /**
     * ?????????
     * 
     * @param tableName
     *            ??
     * @return ????
     */
    public String[] getColumnNames(final String tableName) {
        if (tableName == null) {
            return null;
        }
        return columnNamesMap.get(tableName.toLowerCase());
    }

    /**
     * ????????????
     * 
     * @param index
     *            
     * @return ????
     */
    public String[] getColumnNames(final int index) {
        return getColumnNames(getTableName(index));
    }

    /**
     * ??????<code>true</code>???
     * 
     * @return ??????<code>true</code>????????<code>false</code>
     */
    public boolean isReadTarget() {
        return readTarget;
    }

    /**
     * ??????????????
     * 
     * @param entity
     *            
     * @return ????????
     */
    public Object[] getAllValues(final Object entity) {
        final List<Object> allValues = CollectionsUtil.newArrayList();
        final Object value = getValue(entity);
        if (id) {
            gatherIdAttributeValues(allValues, hibernateType, value);
        } else {
            gatherAttributeValues(allValues, hibernateType, value);
        }
        return allValues.toArray();
    }

    /**
     * <code>value</code>?ID???<code>allValues</code>?????
     * 
     * @param allValues
     *            ID??
     * @param type
     *            Hibernate?
     * @param value
     *            ?ID???????ID?
     */
    protected void gatherIdAttributeValues(final List<Object> allValues, final Type type, final Object value) {

        if (type.isEntityType()) {
            final EntityType entityType = EntityType.class.cast(type);
            final String name = entityType.getAssociatedEntityName();
            final EntityPersister ep = factory.getEntityPersister(name);
            final Type idType = ep.getIdentifierType();
            final Serializable id = ep.getIdentifier(value, EntityMode.POJO);
            gatherIdAttributeValues(allValues, idType, id);

        } else if (type.isComponentType()) {
            final AbstractComponentType componentType = AbstractComponentType.class.cast(type);
            final Object[] subvalues = componentType.getPropertyValues(value, EntityMode.POJO);
            final Type[] subtypes = componentType.getSubtypes();
            for (int i = 0; i < subtypes.length; i++) {
                gatherIdAttributeValues(allValues, subtypes[i], subvalues[i]);
            }

        } else {
            allValues.add(convert(type, value));
        }
    }

    /**
     * <code>value</code>????<code>allValues</code>?????
     * 
     * @param allValues
     *            ??
     * @param type
     *            Hibernate?
     * @param value
     *            ????????
     */
    protected void gatherAttributeValues(final List<Object> allValues, final Type type, final Object value) {

        if (value == null) {
            allValues.add(null);
            return;
        }
        if (!isReadTargetType(type)) {
            return;
        }

        if (type.isEntityType()) {
            final EntityType entityType = EntityType.class.cast(type);

            if (entityType.isReferenceToPrimaryKey()) {
                gatherIdAttributeValues(allValues, entityType, value);
            } else {
                final String name = entityType.getAssociatedEntityName();
                final EntityPersister ep = factory.getEntityPersister(name);
                final Type[] subtypes = ep.getPropertyTypes();
                final Object[] subvalue = ep.getPropertyValues(value, EntityMode.POJO);
                for (int i = 0; i < subtypes.length; i++) {
                    gatherAttributeValues(allValues, subtypes[i], subvalue[i]);
                }
            }

        } else if (type.isComponentType()) {
            final AbstractComponentType componentType = AbstractComponentType.class.cast(type);
            final Object[] subvalues = componentType.getPropertyValues(value, EntityMode.POJO);
            final Type[] subtypes = componentType.getSubtypes();
            for (int i = 0; i < subtypes.length; i++) {
                gatherAttributeValues(allValues, subtypes[i], subvalues[i]);
            }

        } else {
            allValues.add(convert(type, value));
        }
    }

    /**
     * Hibernate?????????
     * 
     * @param type
     *            Hibernate?
     * @param value
     *            
     * @return ???
     */
    protected Object convert(final Type type, final Object value) {
        if (type instanceof CustomType) {
            if (type.getReturnedClass().isEnum()) {
                final Enum<?> e = Enum.class.cast(value);
                final int[] sqlTypeArray = type.sqlTypes(factory);

                switch (sqlTypeArray[0]) {
                case Types.INTEGER:
                case Types.NUMERIC:
                case Types.SMALLINT:
                case Types.TINYINT:
                case Types.BIGINT:
                case Types.DECIMAL:
                case Types.DOUBLE:
                case Types.FLOAT:
                    return e.ordinal();
                }
                return e.name();
            }
        }
        return value;
    }

}