All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.modeshape.jdbc.JcrResultSetMetaData Maven / Gradle / Ivy

Go to download

JDBC driver to allow clients to use JCR-SQL2 to query a ModeShape JCR repository within the same JVM process.

There is a newer version: 5.4.1.Final
Show newest version
/*
 * ModeShape (http://www.modeshape.org)
 *
 * 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.modeshape.jdbc;

import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.nodetype.NodeType;
import javax.jcr.nodetype.PropertyDefinition;
import javax.jcr.query.QueryResult;
import org.modeshape.jdbc.JcrType.DefaultDataTypes;

/**
 * This driver's {@link ResultSetMetaData} implementation that obtains the metadata information from the JCR query result and
 * (where possible) the column's corresponding property definitions.
 */
public class JcrResultSetMetaData implements ResultSetMetaData {

    private final JcrConnection connection;
    private final QueryResult results;
    private int[] nullable;

    protected JcrResultSetMetaData( JcrConnection connection,
                                    QueryResult results ) {
        this.connection = connection;
        this.results = results;
    }

    /**
     * {@inheritDoc}
     * 

* All columns come from the same repository (i.e., catalog). *

* * @see java.sql.ResultSetMetaData#getCatalogName(int) */ @Override public String getCatalogName( int column ) { return connection.info().getRepositoryName(); } @Override public String getColumnClassName( int column ) { return getJcrType(column).getRepresentationClass().getName(); } @Override public int getColumnCount() throws SQLException { try { return results.getColumnNames().length; } catch (RepositoryException e) { throw new SQLException(e.getLocalizedMessage(), e); } } /** * {@inheritDoc} *

* This method returns the nominal display size based upon the column's type. Therefore, the value may not reflect the optimal * display size for any given value. *

* * @see java.sql.ResultSetMetaData#getColumnDisplaySize(int) */ @Override public int getColumnDisplaySize( int column ) { return getJcrType(column).getNominalDisplaySize(); } @Override public String getColumnLabel( int column ) throws SQLException { try { return results.getColumnNames()[column - 1]; // column value is 1-based } catch (RepositoryException e) { throw new SQLException(e.getLocalizedMessage(), e); } } @Override public String getColumnName( int column ) throws SQLException { return getColumnLabel(column); } @Override public int getColumnType( int column ) { return getJcrType(column).getJdbcType(); } @Override public String getColumnTypeName( int column ) { return getJcrType(column).getJdbcTypeName(); } /** * {@inheritDoc} *

* This method always returns the nominal display size for the type. *

* * @see java.sql.ResultSetMetaData#getPrecision(int) */ @Override public int getPrecision( int column ) { return getJcrType(column).getNominalDisplaySize(); } /** * {@inheritDoc} *

* This method returns the number of digits behind the decimal point, which is assumed to be 3 if the type is * {@link PropertyType#DOUBLE} or 0 otherwise. *

* * @see java.sql.ResultSetMetaData#getScale(int) */ @Override public int getScale( int column ) { JcrType typeInfo = getJcrType(column); if (typeInfo.getJcrType() == PropertyType.DOUBLE) { return 3; // pulled from thin air } return 0; } /** * {@inheritDoc} *

* This method always returns the workspace name. *

* * @see java.sql.ResultSetMetaData#getSchemaName(int) */ @Override public String getSchemaName( int column ) { return connection.info().getWorkspaceName(); } @Override public String getTableName( int column ) throws SQLException { try { return results.getSelectorNames()[column - 1]; // column value is 1-based } catch (RepositoryException e) { throw new SQLException(e.getLocalizedMessage(), e); } } /** * {@inheritDoc} *

* This method always returns false, since this JCR property types don't represent auto-incremented values. *

* * @see java.sql.ResultSetMetaData#isAutoIncrement(int) */ @Override public boolean isAutoIncrement( int column ) { return false; } @Override public boolean isCaseSensitive( int column ) { return getJcrType(column).isCaseSensitive(); } /** * {@inheritDoc} *

* This method always returns false, since no JCR property types (directly) represent currency. *

* * @see java.sql.ResultSetMetaData#isCurrency(int) */ @Override public boolean isCurrency( int column ) { return false; } /** * {@inheritDoc} *

* This method always returns false, since this JDBC driver does not support writes. *

* * @see java.sql.ResultSetMetaData#isDefinitelyWritable(int) */ @Override public boolean isDefinitelyWritable( int column ) { return false; } @Override public int isNullable( int column ) throws SQLException { if (nullable == null) { int length = getColumnCount(); nullable = new int[length]; for (int i = 0; i != length; ++i) { nullable[i] = -1; } } else { int result = nullable[column - 1]; if (result != -1) { // Already found this value, so return it ... return result; } } // Find the node type for the column (given that the column name is the property name and // the table name is the node type), and determine if the property definition is multi-valued or not mandatory. String nodeTypeName = getTableName(column); if (nodeTypeName.length() == 0) { // There is no table for the column, so therefore we don't know the node type ... return ResultSetMetaData.columnNullableUnknown; } String propertyName = getColumnName(column); boolean singleProp = false; boolean singleResidual = false; boolean multiResidual = false; NodeType type = connection.nodeType(nodeTypeName); for (PropertyDefinition defn : type.getPropertyDefinitions()) { if (defn.getName().equals(propertyName)) { if (defn.isMultiple() || defn.isMandatory()) { // We know this IS nullable return ResultSetMetaData.columnNullable; } // Otherwise this is a single-valued property that is mandatory, // but we can't return columnNotNullable because we may not have found the multi-valued property ... singleProp = true; } else if (defn.getName().equals("*")) { // Residual if (defn.isMultiple() || defn.isMandatory()) multiResidual = true; else singleResidual = true; } } int result = ResultSetMetaData.columnNullableUnknown; if (multiResidual) result = ResultSetMetaData.columnNullable; else if (singleProp || singleResidual) result = ResultSetMetaData.columnNoNulls; nullable[column - 1] = result; return result; } /** * {@inheritDoc} *

* Even though the value may be writable in the JCR repository, this JDBC driver does not support writes. Therefore, this * method always returns true. *

* * @see java.sql.ResultSetMetaData#isReadOnly(int) */ @Override public boolean isReadOnly( int column ) { return true; } /** * {@inheritDoc} *

* In JCR-SQL2, every property can be used in a WHERE clause. Therefore, this method always returns true. *

* * @see java.sql.ResultSetMetaData#isSearchable(int) */ @Override public boolean isSearchable( int column ) { return true; } /** * {@inheritDoc} *

* This method returns true if the column is a {@link PropertyType#DOUBLE}, {@link PropertyType#LONG} or * {@link PropertyType#DATE}. *

* * @see java.sql.ResultSetMetaData#isSigned(int) */ @Override public boolean isSigned( int column ) { return getJcrType(column).isSigned(); } /** * {@inheritDoc} *

* Even though the value may be writable in the JCR repository, this JDBC driver does not support writes. Therefore, this * method always returns false. *

* * @see java.sql.ResultSetMetaData#isWritable(int) */ @Override public boolean isWritable( int column ) { return false; } @Override public boolean isWrapperFor( Class iface ) /*throws SQLException*/{ return iface.isInstance(results); } @Override public T unwrap( Class iface ) throws SQLException { if (iface.isInstance(results)) { return iface.cast(results); } throw new SQLException(JdbcLocalI18n.classDoesNotImplementInterface.text(ResultSetMetaData.class.getSimpleName(), iface.getName())); } private JcrType getJcrType( int column ) { JcrType typeInfo = null; if (results instanceof org.modeshape.jcr.api.query.QueryResult) { final String typeName = ((org.modeshape.jcr.api.query.QueryResult)results).getColumnTypes()[column - 1]; typeInfo = JcrType.typeInfo(typeName); } /** * If no type is matched, then default to STRING */ return (typeInfo != null ? typeInfo : JcrType.typeInfo(DefaultDataTypes.STRING)); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy