001/* 
002 * JKNIV, whinstone one contract to access your database.
003 * 
004 * Copyright (C) 2017, the original author or authors.
005 *
006 * This library is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU Lesser General Public
008 * License as published by the Free Software Foundation; either
009 * version 2.1 of the License.
010 * 
011 * This library is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014 * Lesser General Public License for more details.
015 * 
016 * You should have received a copy of the GNU Lesser General Public
017 * License along with this library; if not, write to the Free Software Foundation, Inc., 
018 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
019 */
020package net.sf.jkniv.whinstone.jdbc;
021
022import java.sql.ResultSet;
023import java.sql.SQLException;
024
025import net.sf.jkniv.reflect.beans.ObjectProxy;
026import net.sf.jkniv.reflect.beans.ObjectProxyFactory;
027import net.sf.jkniv.reflect.beans.PropertyAccess;
028import net.sf.jkniv.whinstone.JdbcColumn;
029import net.sf.jkniv.whinstone.JdbcColumnMapper;
030import net.sf.jkniv.whinstone.UnderscoreToCamelCaseMapper;
031import net.sf.jkniv.whinstone.types.ColumnType;
032import net.sf.jkniv.whinstone.types.Convertible;
033import net.sf.jkniv.whinstone.types.JdbcType;
034import net.sf.jkniv.whinstone.types.RegisterType;
035
036public class DefaultJdbcColumn implements JdbcColumn<ResultSet>
037{
038    private final int                     columnIndex;
039    private final String                  columnName;
040    private final String                  methodName;
041    private final ColumnType              columnType;
042    private final boolean nestedAttribute;
043    private final PropertyAccess propertyAccess;
044    private final RegisterType registerType;
045    
046    // TODO design property to config UnderscoreToCamelCaseMapper
047    private final static JdbcColumnMapper JDBC_COLUMN_MAPPER = new UnderscoreToCamelCaseMapper();
048    
049    public DefaultJdbcColumn(int columnIndex, String columnName, int jdbcTypeValue, RegisterType registerType, Class<?> classTarget)
050    {
051        super();
052        this.columnIndex = columnIndex;
053        this.columnName = columnName;
054        this.propertyAccess = new PropertyAccess(JDBC_COLUMN_MAPPER.map(columnName), classTarget);
055        this.columnType = JdbcType.valueOf(jdbcTypeValue);
056        this.registerType = registerType;
057        if(columnName.indexOf(".") > 0)
058        {
059            this.nestedAttribute = true;
060            this.methodName = columnName;
061        }
062        else
063        {
064            this.nestedAttribute = false;
065            this.methodName = propertyAccess.getWriterMethodName();
066        }
067    }
068    
069    @Override
070    public PropertyAccess getPropertyAccess()
071    {
072        return propertyAccess;
073    }
074    
075    @Override
076    public String getAttributeName()
077    {
078        return propertyAccess.getFieldName();
079    }
080    
081    @Override
082    public String getMethodName()
083    {
084        return methodName;
085    }
086    
087    @Override
088    public String getName()
089    {
090        return this.columnName;
091    }
092    
093    @Override
094    public int getIndex()
095    {
096        return this.columnIndex;
097    }
098    
099    @Override
100    public boolean isBinary()
101    {
102        return this.columnType.isBinary();
103    }
104    
105    @Override
106    public boolean isNestedAttribute()
107    {
108        return nestedAttribute;
109    }
110    
111    @Override
112    public Object getValue(ResultSet rs) throws SQLException
113    {
114        Object value = rs.getObject(columnIndex);
115        ObjectProxy<?> proxy = ObjectProxyFactory.of(this.propertyAccess.getTargetClass());
116        Convertible<Object, Object> convertible = registerType.toAttribute(this, proxy);
117        if (!convertible.getType().isInstance(value))
118            value = convertible.toAttribute(value);
119        return value;
120    }
121    
122    @Override
123    public Object getBytes(ResultSet rs) throws SQLException
124    {
125        return rs.getBytes(columnIndex);
126    }
127    
128    @Override
129    public ColumnType getType()
130    {
131        return this.columnType;
132    }
133
134    @Override
135    public String toString()
136    {
137        return "DefaultJdbcColumn [index=" + columnIndex + ", columnName=" + columnName + ", jdbcType=" + columnType
138                + "]";
139    }
140}