Package org.jpox.store.rdbms.mapping

Source Code of org.jpox.store.rdbms.mapping.CharRDBMSMapping

/**********************************************************************
Copyright (c) 2004 Erik Bengtson and others. All rights reserved.
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.

Contributors:
2004 Andy Jefferson - localised messages
2004 Andy Jefferson - added Currency
2005 Andy Jefferson - added control over TimeZone
2007 Andy Jefferson - add persist empty string as null, add support for char(XX) padding
    ...
**********************************************************************/
package org.jpox.store.rdbms.mapping;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.Calendar;

import org.jpox.ClassNameConstants;
import org.jpox.exceptions.JPOXDataStoreException;
import org.jpox.exceptions.JPOXUserException;
import org.jpox.store.exceptions.NullValueException;
import org.jpox.store.mapped.DatastoreField;
import org.jpox.store.mapped.MappedStoreManager;
import org.jpox.store.mapped.expression.ScalarExpression;
import org.jpox.store.mapped.mapping.JavaTypeMapping;
import org.jpox.store.mapped.mapping.SingleFieldMapping;
import org.jpox.store.rdbms.Column;
import org.jpox.store.rdbms.typeinfo.TypeInfo;
import org.jpox.util.JPOXLogger;
import org.jpox.util.TypeConversionHelper;

/**
* Mapping of a CHAR RDBMS type.
*
* @version $Revision: 1.53 $
*/
public class CharRDBMSMapping extends ColumnMapping
{
    /**
     * Constructor.
     * @param storeMgr Store Manager
     * @param mapping Java type mapping
     */
    protected CharRDBMSMapping(MappedStoreManager storeMgr, JavaTypeMapping mapping)
    {
        super(storeMgr, mapping);
    }
   
    /**
     * Constructor.
     * @param mapping Java type mapping
     * @param storeMgr Store Manager
     * @param field Field to be mapped
     */
    public CharRDBMSMapping(JavaTypeMapping mapping, MappedStoreManager storeMgr, DatastoreField field)
    {
    super(storeMgr, mapping);
    column = (Column) field;
    initialize();
  }

    /**
     * Method to initialise the column mapping.
     * Provides default length specifications for the CHAR column to fit the data being stored.
     */
    protected void initialize()
    {
        if (column != null)
        {
            // Default Length
            if (getJavaTypeMapping() instanceof SingleFieldMapping && column.getColumnMetaData().getLength() == null)
            {
                SingleFieldMapping m = (SingleFieldMapping)getJavaTypeMapping();
                if (m.getDefaultLength(0) > 0)
                {
                    // No column length provided by user and the type has a default length so use it
                    column.getColumnMetaData().setLength(m.getDefaultLength(0));
                }
            }

            column.getColumnMetaData().setJdbcType("CHAR");
            column.checkString();

            // Valid Values
            if (getJavaTypeMapping() instanceof SingleFieldMapping)
            {
                ScalarExpression[] validValues = ((SingleFieldMapping)getJavaTypeMapping()).getValidValues(0);
                if (validValues != null)
                {
                    String constraints = getDatabaseAdapter().getCheckConstraintForValues(column.getIdentifier(), validValues, column.isNullable());
                    column.setConstraints(constraints);
                }
            }
            if (getJavaTypeMapping().getJavaType().getName().equals(ClassNameConstants.JAVA_LANG_BOOLEAN))
            {
                // With a Boolean we'll store it as "Y", "N" (see setBoolean/getBoolean methods)
                column.getColumnMetaData().setLength(1);
                StringBuffer constraints = new StringBuffer("CHECK (" + column.getIdentifier() + " IN ('Y','N')");
                if (column.isNullable())
                {
                    constraints.append(" OR " + column.getIdentifier() + " IS NULL");
                }
                constraints.append(')');
                column.setConstraints(constraints.toString());
            }

            // Check on max length of the type against the length we have set
            int maxlength = getTypeInfo().precision;
            if (column.getColumnMetaData().getLength().intValue() <= 0 ||
                column.getColumnMetaData().getLength().intValue() > maxlength)
            {
                if (getTypeInfo().allowsPrecisionSpec)
                {
                    throw new JPOXUserException("String max length of " + column.getColumnMetaData().getLength() +
                        " is outside the acceptable range [0, " + maxlength + "] for column \"" + column.getIdentifier() + "\"");
                }
            }
        }
    initTypeInfo();
    }

    /**
     * Accessor for whether the mapping is string-based.
     * @return Whether the mapping is string based
     */
    public boolean isStringBased()
    {
        return true;
    }

    /**
     * Accessor for the JDBC type being stored here.
     * @return JDBC Types.CHAR
     */
    public TypeInfo getTypeInfo()
    {
        return getDatabaseAdapter().getTypeInfo(Types.CHAR);
    }

    /**
     * Method to set a character at the specified position in the JDBC PreparedStatement.
     * @param ps The PreparedStatement
     * @param param Parameter position
     * @param value The value to set
     */
    public void setChar(Object ps, int param, char value)
    {
        try
        {
            if (value == Character.UNASSIGNED && !getDatabaseAdapter().getSupportsPersistOfUnassignedChar())
            {
                // Some datastores (e.g Postgresql) dont allow persistence of 0x0 ("\0") so use a space
                value = ' ';
                JPOXLogger.DATASTORE.warn(LOCALISER.msg("055008"));
            }
            ((PreparedStatement) ps).setString(param, new Character(value).toString());
        }
        catch (SQLException e)
        {
            throw new JPOXDataStoreException(LOCALISER.msg("055001", "char",
                "" + value, column, e.getMessage()), e);
        }
    }

    /**
     * Method to extract a character from the ResultSet at the specified position
     * @param rs The Result Set
     * @param param The parameter position
     * @return the character
     */
    public char getChar(Object rs, int param)
    {
        char value;

        try
        {
            value = ((ResultSet) rs).getString(param).charAt(0);
        }
        catch (SQLException e)
        {
            throw new JPOXDataStoreException(LOCALISER.msg("055002","char","" + param, column, e.getMessage()), e);
        }
        return value;
    }

    /**
     * Method to set a String at the specified position in the JDBC PreparedStatement.
     * @param ps The PreparedStatement
     * @param param Parameter position
     * @param value The value to set
     */
    public void setString(Object ps, int param, String value)
    {
        try
        {
            if (value == null)
            {
                // Null string
                if (column.isDefaultable() && column.getDefaultValue() != null)
                {
                    ((PreparedStatement) ps).setString(param,column.getDefaultValue().toString().trim());
                }
                else
                {
                    ((PreparedStatement) ps).setNull(param,getTypeInfo().dataType);
                }
            }
            else if (value.length() == 0)
            {
                // Empty string
                if (storeMgr.getOMFContext().getPersistenceConfiguration().getBooleanProperty("org.jpox.rdbms.persistEmptyStringAsNull"))
                {
                    // Persist as null
                    ((PreparedStatement) ps).setString(param, null);
                }
                else
                {
                    if (getDatabaseAdapter().isNullEqualsEmptyStrings())
                    {
                        // Datastore doesnt support empty string so use special character
                        value = getDatabaseAdapter().getSurrogateForEmptyStrings();
                    }
                    ((PreparedStatement) ps).setString(param, value);
                }
            }
            else
            {
                if (column != null) // Column could be null if we have a query of something like an "enumClass.value"
                {
                    Integer colLength = column.getColumnMetaData().getLength();
                    if (colLength != null && colLength.intValue() < value.length())
                    {
                        // Data in field exceeds datastore column, so take required action
                        String action = storeMgr.getOMFContext().getPersistenceConfiguration().getStringProperty("org.jpox.rdbms.stringLengthExceededAction");
                        if (action.equals("EXCEPTION"))
                        {
                            throw new JPOXUserException(LOCALISER.msg("055007",
                                value, column.getIdentifier().toString(), "" + colLength.intValue())).setFatal();
                        }
                        else if (action.equals("TRUNCATE"))
                        {
                            value = value.substring(0, colLength.intValue());
                        }
                    }
                }
                ((PreparedStatement) ps).setString(param, value);
            }
        }
        catch (SQLException e)
        {
            throw new JPOXDataStoreException(LOCALISER.msg("055001","String","" + value, column, e.getMessage()), e);
        }
    }

    /**
     * Method to extract a String from the ResultSet at the specified position
     * @param rs The Result Set
     * @param param The parameter position
     * @return the String
     */
    public String getString(Object rs, int param)
    {
        try
        {
            String value = ((ResultSet) rs).getString(param);
            if (value == null)
            {
                return value;
            }
            else if (getDatabaseAdapter().isNullEqualsEmptyStrings() &&
                value.equals(getDatabaseAdapter().getSurrogateForEmptyStrings()))
            {
                // Special character simbolizing empty string
                return "";
            }
            else
            {
                if (column.getJdbcType() == Types.CHAR && getDatabaseAdapter().getCharColumnsPaddedWithSpaces())
                {
                    // String has likely been padded with spaces at the end by the datastore so trim trailing whitespace
                    int numPaddingChars = 0;
                    for (int i=value.length()-1;i>=0;i--)
                    {
                        if (value.charAt(i) == ' ') // Only allow for space currently
                        {
                            numPaddingChars++;
                        }
                        else
                        {
                            break;
                        }
                    }
                    if (numPaddingChars > 0)
                    {
                        value = value.substring(0, value.length()-numPaddingChars);
                    }
                }
                return value;
            }
        }
        catch (SQLException e)
        {
            throw new JPOXDataStoreException(LOCALISER.msg("RDBMS.Manager.UnableToGetParam","String","" + param, column, e.getMessage()), e);
        }
    }

    /**
     * Method to set a boolean at the specified position in the JDBC PreparedStatement.
     * @param ps The PreparedStatement
     * @param param Parameter position
     * @param value The value to set
     */
    public void setBoolean(Object ps, int param, boolean value)
    {
        try
        {
            ((PreparedStatement) ps).setString(param, value ? "Y" : "N");
        }
        catch (SQLException e)
        {
            throw new JPOXDataStoreException(LOCALISER.msg("055001","boolean","" + value, column, e.getMessage()), e);
        }
    }

    /**
     * Method to extract a boolean from the ResultSet at the specified position
     * @param rs The Result Set
     * @param param The parameter position
     * @return the boolean
     */
    public boolean getBoolean(Object rs, int param)
    {
        boolean value;

        try
        {
            String s = ((ResultSet) rs).getString(param);
            if (s == null)
            {
                if( column == null || column.getColumnMetaData() == null || !column.getColumnMetaData().isAllowsNull() )
                {
                    if (((ResultSet) rs).wasNull())
                    {
                        throw new NullValueException(LOCALISER.msg("055003",column));
                    }
                }
                return false;
            }

            if (s.equals("Y"))
            {
                value = true;
            }
            else if (s.equals("N"))
            {
                value = false;
            }
            else
            {
                throw new JPOXDataStoreException(LOCALISER.msg("055003",column));
            }
        }
        catch (SQLException e)
        {
            throw new JPOXDataStoreException(LOCALISER.msg("055002","boolean","" + param, column, e.getMessage()), e);
        }

        return value;
    }

    /**
     * Method to set an object at the specified position in the JDBC PreparedStatement.
     * @param ps The PreparedStatement
     * @param param Parameter position
     * @param value The value to set
     */
    public void setObject(Object ps, int param, Object value)
    {
        try
        {
            if (value == null)
            {
                ((PreparedStatement) ps).setNull(param, getTypeInfo().dataType);
            }
            else
            {
                if (value instanceof Boolean)
                {
                    ((PreparedStatement) ps).setString(param, ((Boolean) value).booleanValue() ? "Y" : "N");
                }
                else if (value instanceof java.sql.Time)
                {
                    ((PreparedStatement) ps).setString(param, ((java.sql.Time) value).toString());
                }
                else if (value instanceof java.sql.Date)
                {
                    ((PreparedStatement) ps).setString(param, ((java.sql.Date) value).toString());
                }
                else if (value instanceof java.util.Date)
                {
                    ((PreparedStatement) ps).setString(param, DateFormat.getInstance().format((java.util.Date) value));
                }
                else if (value instanceof java.sql.Timestamp)
                {
                    Calendar cal = storeMgr.getOMFContext().getPersistenceConfiguration().getCalendarForDateTimezone();

                    // pass the calendar to oracle makes it loses milliseconds
                    if (cal != null)
                    {
                        ((PreparedStatement) ps).setTimestamp(param, (Timestamp) value, cal);
                    }
                    else
                    {
                        ((PreparedStatement) ps).setTimestamp(param, (Timestamp) value);
                    }
                }
                else if (value instanceof String)
                {
                    ((PreparedStatement) ps).setString(param, ((String) value));
                }
                else
                {
                    // This caters for all non-string types. If any more need specific treatment, split them out above.
                    ((PreparedStatement) ps).setString(param, value.toString());
                }
            }
        }
        catch (SQLException e)
        {
            throw new JPOXDataStoreException(LOCALISER.msg("055001","Object","" + value, column, e.getMessage()), e);
        }
    }

    /**
     * Method to extract an object from the ResultSet at the specified position
     * @param rs The Result Set
     * @param param The parameter position
     * @return the object
     */
    public Object getObject(Object rs, int param)
    {
        Object value;

        try
        {
            String s = ((ResultSet) rs).getString(param);

            if (s == null)
            {
                value = null;
            }
            else
            {
                if (getJavaTypeMapping().getJavaType().getName().equals(ClassNameConstants.JAVA_LANG_BOOLEAN))
                {
                    if (s.equals("Y"))
                    {
                        value = Boolean.TRUE;
                    }
                    else if (s.equals("N"))
                    {
                        value = Boolean.FALSE;
                    }
                    else
                    {
                        throw new JPOXDataStoreException(LOCALISER.msg("055003",column));
                    }
                }
                else if (getJavaTypeMapping().getJavaType().getName().equals(ClassNameConstants.JAVA_LANG_CHARACTER))
                {
                    value = new Character(s.charAt(0));
                }
                else if (getJavaTypeMapping().getJavaType().getName().equals(ClassNameConstants.JAVA_SQL_TIME))
                {
                    value = java.sql.Time.valueOf(s);
                }
                else if (getJavaTypeMapping().getJavaType().getName().equals(ClassNameConstants.JAVA_SQL_DATE))
                {
                    value = java.sql.Date.valueOf(s);
                }
                else if (getJavaTypeMapping().getJavaType().getName().equals(ClassNameConstants.JAVA_UTIL_DATE))
                {
                    value = DateFormat.getInstance().parse(s);
                }
                else if (getJavaTypeMapping().getJavaType().getName().equals(ClassNameConstants.JAVA_SQL_TIMESTAMP))
                {
                    Calendar cal = storeMgr.getOMFContext().getPersistenceConfiguration().getCalendarForDateTimezone();
                    value = TypeConversionHelper.stringToTimestamp(s, cal);
                }
                else
                {
                  value = s;
                }
            }
        }
        catch (SQLException e)
        {
            throw new JPOXDataStoreException(LOCALISER.msg("055002","Object","" + param, column, e.getMessage()), e);
        }
    catch (ParseException e)
    {
            throw new JPOXDataStoreException(LOCALISER.msg("055002","Object","" + param, column, e.getMessage()), e);
    }

        return value;
    }
}
TOP

Related Classes of org.jpox.store.rdbms.mapping.CharRDBMSMapping

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.