001/*
002 * ModeShape (http://www.modeshape.org)
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *       http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.modeshape.jdbc.metadata;
017
018import java.sql.ResultSetMetaData;
019import java.sql.SQLException;
020import java.sql.Types;
021import org.modeshape.jdbc.JcrType;
022import org.modeshape.jdbc.JdbcLocalI18n;
023
024/**
025 * 
026 */
027public class ResultSetMetaDataImpl implements ResultSetMetaData {
028
029    private MetadataProvider provider;
030
031    public ResultSetMetaDataImpl( MetadataProvider provider ) {
032        this.provider = provider;
033    }
034
035    /**
036     * Adjust from 1-based to internal 0-based representation
037     * 
038     * @param index External 1-based representation
039     * @return Internal 0-based representation
040     */
041    private int adjustColumn( int index ) {
042        return index - 1;
043    }
044
045    @Override
046    public int getColumnCount() {
047        return provider.getColumnCount();
048    }
049
050    @Override
051    public boolean isAutoIncrement( int index ) {
052        return provider.getBooleanValue(adjustColumn(index), ResultsMetadataConstants.AUTO_INCREMENTING);
053    }
054
055    @Override
056    public boolean isCaseSensitive( int index ) {
057        return provider.getBooleanValue(adjustColumn(index), ResultsMetadataConstants.CASE_SENSITIVE);
058    }
059
060    @Override
061    public boolean isSearchable( int index ) {
062        Integer searchable = (Integer)provider.getValue(adjustColumn(index), ResultsMetadataConstants.SEARCHABLE);
063        return !(ResultsMetadataConstants.SEARCH_TYPES.UNSEARCHABLE.equals(searchable));
064    }
065
066    @Override
067    public boolean isCurrency( int index ) {
068        return provider.getBooleanValue(adjustColumn(index), ResultsMetadataConstants.CURRENCY);
069    }
070
071    @Override
072    public int isNullable( int index ) {
073        Object nullable = provider.getValue(adjustColumn(index), ResultsMetadataConstants.NULLABLE);
074        if (nullable.equals(ResultsMetadataConstants.NULL_TYPES.NULLABLE)) {
075            return columnNullable;
076        } else if (nullable.equals(ResultsMetadataConstants.NULL_TYPES.NOT_NULL)) {
077            return columnNoNulls;
078        } else {
079            return columnNullableUnknown;
080        }
081    }
082
083    @Override
084    public boolean isSigned( int index ) {
085        return provider.getBooleanValue(adjustColumn(index), ResultsMetadataConstants.SIGNED);
086    }
087
088    @Override
089    public int getColumnDisplaySize( int index ) {
090        return provider.getIntValue(adjustColumn(index), ResultsMetadataConstants.DISPLAY_SIZE);
091    }
092
093    @Override
094    public String getColumnLabel( int index ) {
095        return provider.getStringValue(adjustColumn(index), ResultsMetadataConstants.COLUMN_LABEL);
096    }
097
098    @Override
099    public String getColumnName( int index ) {
100        return provider.getStringValue(adjustColumn(index), ResultsMetadataConstants.COLUMN);
101    }
102
103    @Override
104    public String getSchemaName( int index ) {
105        String name = provider.getStringValue(adjustColumn(index), ResultsMetadataConstants.SCHEMA);
106        if (name != null) {
107            int dotIndex = name.indexOf('.');
108            if (dotIndex != -1) {
109                return name.substring(0, dotIndex);
110            }
111        }
112        return null;
113    }
114
115    @Override
116    public int getPrecision( int index ) {
117        return provider.getIntValue(adjustColumn(index), ResultsMetadataConstants.PRECISION);
118    }
119
120    @Override
121    public int getScale( int index ) {
122        return provider.getIntValue(adjustColumn(index), ResultsMetadataConstants.SCALE);
123    }
124
125    @Override
126    public String getTableName( int index ) {
127        String name = provider.getStringValue(adjustColumn(index), ResultsMetadataConstants.TABLE);
128        if (name != null) {
129            int dotIndex = name.indexOf('.');
130            if (dotIndex != -1) {
131                return name.substring(dotIndex + 1);
132            }
133        }
134        return name;
135    }
136
137    @Override
138    public String getCatalogName( int index ) {
139        return provider.getStringValue(adjustColumn(index), ResultsMetadataConstants.CATALOG);
140    }
141
142    @Override
143    public int getColumnType( int index ) {
144        String runtimeTypeName = provider.getStringValue(adjustColumn(index), ResultsMetadataConstants.DATA_TYPE);
145
146        JcrType typeInfo = JcrType.typeInfo(runtimeTypeName);
147        return typeInfo != null ? typeInfo.getJdbcType() : Types.VARCHAR;
148    }
149
150    @Override
151    public String getColumnTypeName( int index ) {
152        return provider.getStringValue(adjustColumn(index), ResultsMetadataConstants.DATA_TYPE);
153    }
154
155    @Override
156    public boolean isReadOnly( int index ) {
157        return !provider.getBooleanValue(adjustColumn(index), ResultsMetadataConstants.WRITABLE);
158    }
159
160    @Override
161    public boolean isWritable( int index ) {
162        return provider.getBooleanValue(adjustColumn(index), ResultsMetadataConstants.WRITABLE);
163    }
164
165    @Override
166    public boolean isDefinitelyWritable( int index ) {
167        return provider.getBooleanValue(adjustColumn(index), ResultsMetadataConstants.WRITABLE);
168    }
169
170    @Override
171    public String getColumnClassName( int index ) {
172        JcrType typeInfo = JcrType.typeInfo(getColumnTypeName(index));
173        return typeInfo != null ? typeInfo.getRepresentationClass().getName() : String.class.getName();
174    }
175
176    @Override
177    public boolean isWrapperFor( Class<?> iface ) {
178        return iface.isInstance(this);
179    }
180
181    @Override
182    public <T> T unwrap( Class<T> iface ) throws SQLException {
183        if (iface.isInstance(this)) {
184            return iface.cast(this);
185        }
186
187        throw new SQLException(JdbcLocalI18n.classDoesNotImplementInterface.text());
188    }
189
190}