package nl.ipo.cds.etl.generalization; import java.io.IOException; import java.sql.Connection; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Executor; import java.util.concurrent.SynchronousQueue; import javax.sql.DataSource; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.jdbc.datasource.DataSourceUtils; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.io.InputStreamInStream; import com.vividsolutions.jts.io.WKBReader; public class GeneralizeReader implements ApplicationContextAware { private static final Log logger = LogFactory.getLog(GeneralizeReader.class); private ApplicationContext applicationContext; private DataSource dataSource; private Executor executer; private GeneralizerConfig generalizerConfig; public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } public void setGeneralizerConfig(GeneralizerConfig generalizerConfig) { this.generalizerConfig = generalizerConfig; } public void setExecuter(Executor executer) { this.executer = executer; } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } protected <T> boolean arrayEquals(T[] a, T[] b) { for(int i = 0; i < a.length; i++) { if(a[i] == null && b[i] == null) { continue; } if(a[i] != null && b[i] != null && a[i].equals(b[i])) { continue; } return false; } return true; } @Transactional(propagation=Propagation.MANDATORY) public void delete() throws SQLException, IOException { Connection connection = DataSourceUtils.getConnection(dataSource); Statement stmt = connection.createStatement(); for(GeneralizeJob job : generalizerConfig.getGeneralizeJobs()) { String destination = job.getDestination(); logger.debug("" + stmt.executeUpdate("delete from " + destination) + " features deleted from " + destination); } stmt.close(); DataSourceUtils.releaseConnection(connection, dataSource); } @Transactional(propagation=Propagation.MANDATORY) public void populate() throws SQLException, IOException, InterruptedException { logger.debug("started"); Connection connection = DataSourceUtils.getConnection(dataSource); WKBReader wkbReader = new WKBReader(); Statement stmt = connection.createStatement(); for(GeneralizeJob job : generalizerConfig.getGeneralizeJobs()) { String destination = job.getDestination(); BlockingQueue<Event> eventQueue = new SynchronousQueue<Event>(); ResultSet rs = stmt.executeQuery(job.getQuery()); ResultSetMetaData rsMd = rs.getMetaData(); String[] columnNames = new String[rsMd.getColumnCount() - 3]; for(int i = 0; i < columnNames.length; i++) { String columnValue = rsMd.getColumnName(i + 4); columnNames[i] = columnValue; } GeneralizeWriter writer = applicationContext.getBean(GeneralizeWriter.class); writer.setDestination(destination); writer.setEventQueue(eventQueue); writer.setConnection(connection); writer.setColumnNames(columnNames); executer.execute(writer); int lastX = Integer.MIN_VALUE, lastY = Integer.MIN_VALUE; String[] lastColumnValues = new String[rsMd.getColumnCount() - 3]; ArrayList<Geometry> geometries = new ArrayList<Geometry>(); int counter = 0; try { while(rs.next()) { Geometry geometry = wkbReader.read(new InputStreamInStream(rs.getBinaryStream(1))); int x = rs.getInt(2), y = rs.getInt(3); String[] columnValues = new String[rsMd.getColumnCount() - 3]; for(int i = 0; i < columnValues.length; i++) { String columnValue = rs.getString(i + 4); columnValues[i] = columnValue; } if(x != lastX || y != lastY || !arrayEquals(columnValues, lastColumnValues)) { lastX = x; lastY = y; lastColumnValues = columnValues; if(geometries.size() > 0) { Generalizer generalizer = applicationContext.getBean(Generalizer.class); generalizer.setGeometries(geometries); generalizer.setEventQueue(eventQueue); generalizer.setColumnValues(columnValues); executer.execute(generalizer); logger.debug("generalizer constructed"); geometries = new ArrayList<Geometry>(); counter++; } } geometries.add(geometry); } rs.close(); } catch(Exception e) { logger.debug("exception during generalization", e); throw new IOException("exception during generalization", e); } finally { writer.join(counter); eventQueue.put(new Finalize()); writer.join(); } } stmt.close(); DataSourceUtils.releaseConnection(connection, dataSource); logger.debug("finished"); } }