/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package com.eas.client; import com.eas.client.changes.JdbcChangeValue; import com.eas.client.dataflow.JdbcFlowProvider; import com.eas.client.dataflow.JdbcReader; import com.eas.client.metadata.Fields; import com.eas.client.metadata.Parameter; import com.eas.client.queries.ContextHost; import com.eas.client.sqldrivers.SqlDriver; import com.eas.script.Scripts; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.Wrapper; import java.util.function.Consumer; import java.util.logging.Level; import java.util.logging.Logger; import javax.sql.DataSource; /** * This flow provider implements transaction capability for standard * JdbcFlowProvider. It enqueues changes in transactional queue instead of * actual writing to underlying database. It relies on transactional assumption: * all enqueued changes will be actually applied at commmit or reverted at * rollback. * * @author mg */ public class PlatypusJdbcFlowProvider extends JdbcFlowProvider<String> { protected String entityName; protected DatabasesClient client; protected MetadataCache cache; protected SqlDriver sqlDriver; protected ContextHost contextHost; public PlatypusJdbcFlowProvider(DatabasesClient aClient, String aDataSourceName, String aEntityName, DataSource aDataSource, Consumer<Runnable> aDataPuller, MetadataCache aCache, String aClause, Fields aExpectedFields, ContextHost aContextHost) throws Exception { super(aDataSourceName, aDataSource, aDataPuller, aClause, aExpectedFields); entityName = aEntityName; client = aClient; cache = aCache; sqlDriver = cache.getDatasourceSqlDriver(); contextHost = aContextHost; } @Override public String getEntityName() { return entityName; } @Override protected JdbcReader obtainJdbcReader() { return new JdbcReader(expectedFields, (Wrapper aRsultSetOrCallableStatement, int aColumnIndex, Connection aConnection) -> { return sqlDriver.readGeometry(aRsultSetOrCallableStatement, aColumnIndex, aConnection); }, (int aJdbcType, String aRDBMSType) -> { return sqlDriver.getTypesResolver().toApplicationType(aJdbcType, aRDBMSType); }); } @Override protected int assignParameter(Parameter aParameter, PreparedStatement aStatement, int aParameterIndex, Connection aConnection) throws SQLException { if (Scripts.GEOMETRY_TYPE_NAME.equals(aParameter.getType())) { try { JdbcChangeValue jv = sqlDriver.convertGeometry(aParameter.getValue().toString(), aConnection); Object paramValue = jv.value; int jdbcType = jv.jdbcType; String sqlTypeName = jv.sqlTypeName; int assignedJdbcType = assign(paramValue, aParameterIndex, aStatement, jdbcType, sqlTypeName); checkOutParameter(aParameter, aStatement, aParameterIndex, jdbcType); return assignedJdbcType; } catch (Exception ex) { throw new SQLException(ex); } } else { return super.assignParameter(aParameter, aStatement, aParameterIndex, aConnection); } } @Override protected void acceptOutParameter(Parameter aParameter, CallableStatement aStatement, int aParameterIndex, Connection aConnection) throws SQLException { if (Scripts.GEOMETRY_TYPE_NAME.equals(aParameter.getType())) { try { String sGeometry = sqlDriver.readGeometry(aStatement, aParameterIndex, aConnection); aParameter.setValue(sGeometry); } catch (Exception ex) { Logger.getLogger(PlatypusJdbcFlowProvider.class.getName()).log(Level.SEVERE, null, ex); } } else { super.acceptOutParameter(aParameter, aStatement, aParameterIndex, aConnection); } } @Override protected void prepareConnection(Connection aConnection) throws Exception { if (contextHost != null && contextHost.preparationContext() != null && !contextHost.preparationContext().isEmpty()) { cache.getDatasourceSqlDriver().applyContextToConnection(aConnection, contextHost.preparationContext()); } } @Override protected void unprepareConnection(Connection aConnection) throws Exception { // In the following condition, _PR_eparation context is checked. It's right, because we need to cancel _PR_eparation // if it has been made. And so, condition checks a _PR_eparation context, but _UN_preparation context is applied. // If no preparation has been made, no unpreparation should occur! if (contextHost != null && contextHost.preparationContext() != null && !contextHost.preparationContext().isEmpty()) { cache.getDatasourceSqlDriver().applyContextToConnection(aConnection, contextHost.unpreparationContext()); } } }