/* * codjo.net * * Common Apache License 2.0 */ package net.codjo.broadcast.server; import java.io.IOException; import java.io.PrintWriter; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.HashMap; import java.util.Map; import net.codjo.broadcast.common.BroadcastException; import net.codjo.broadcast.common.ComputedFieldGenerator; import net.codjo.broadcast.common.Context; import net.codjo.broadcast.common.Preferences; import net.codjo.broadcast.common.Selector; import net.codjo.broadcast.common.columns.FileColumnGenerator; import net.codjo.broadcast.common.columns.GenerationException; import net.codjo.broadcast.common.computed.ComputedField; import net.codjo.database.common.api.TransactionManager; import org.apache.log4j.Logger; /** * G�n�rateur de section par d�faut. * * @author $Author: galaber $ * @version $Revision: 1.3 $ */ class DefaultFileSectionGenerator implements FileSectionGenerator { private static final Logger APP = Logger.getLogger(DefaultFileSectionGenerator.class); private boolean columnHeader = false; private String columnSeparator = null; private FileColumnGenerator[] columns; private ComputedFieldGenerator computedField; private Preferences preference; private QueryBuilder queryBuilder; private String sectionHeader = null; private Selector selector; /** * @param sectionName Le nom de la section * @param selector Le selecteur de ligne a diffuser * @param queryBuilder Le constructeur de requete * @param columns Les generateur de colonnes */ DefaultFileSectionGenerator(Preferences preference, String sectionName, Selector selector, ComputedFieldGenerator computedField, QueryBuilder queryBuilder, FileColumnGenerator[] columns) { assertNotNull("preference null", preference); assertNotNull("Nom de section null", sectionName); assertNotNull("Type de selection null", selector); assertNotNull("Constructeur de requ�te null", queryBuilder); assertNotNull("Colonnes de diffusion null", columns); assertNotNull("Generateur de champ calcul�", computedField); this.columns = columns; this.queryBuilder = queryBuilder; this.selector = selector; this.computedField = computedField; this.preference = preference; } public int generate(final Context context, final Connection connection, final PrintWriter writer) throws IOException, SQLException, BroadcastException { final java.sql.Date today = context.getToday(); final TransactionManager<Integer> transactionManager = new TransactionManager<Integer>(connection) { @Override protected Integer runSql(Connection connection) throws Exception { computedField.createComputedTable(context, columns, connection); selector.proceed(context, connection, preference.getSelectionTableName(), today); computedField.fillComputedTable(context, connection); String query = queryBuilder.buildQuery(columns); if (context.getComputedTableWasCreated()) { addWarnings(context, connection); } return generateContent(context, connection, query, writer); } }; try { return transactionManager.run(connection); } catch (Exception ex) { throw new BroadcastException(ex); } finally { cleanupTemporaryTables(context, connection, today); } } private void addWarnings(Context context, Connection connection) throws SQLException { String sql = "select " + ComputedField.WARNINGS + " from " + preference.getComputedTableName(); sql = context.replaceVariables(sql); PreparedStatement s = connection.prepareStatement(sql); ResultSet rs = null; try { rs = s.executeQuery(); while (rs.next()) { String warningsStr = rs.getString(ComputedField.WARNINGS); if (warningsStr != null) { context.addWarning(warningsStr); } } } finally { if (rs != null) { rs.close(); } s.close(); } } void setColumnHeader(boolean displayHeader) { this.columnHeader = displayHeader; } void setColumnSeparator(String separator) { this.columnSeparator = separator; } void setSectionHeader(String displayHeader) { this.sectionHeader = displayHeader; } private void assertNotNull(String errorMsg, Object pointer) { if (pointer == null) { throw new IllegalArgumentException(errorMsg); } } private void cleanupTemporaryTables(Context ctxt, Connection con, java.sql.Date today) throws SQLException { try { selector.cleanup(ctxt, con, ctxt.replaceVariables(preference.getSelectionTableName()), today); } finally { dropComputedTable(con, ctxt.replaceVariables(preference.getComputedTableName())); } } private void dropComputedTable(Connection connection, String computedTableName) throws SQLException { Statement statement = connection.createStatement(); try { statement.executeUpdate("drop table " + computedTableName); } catch (SQLException ex) { ; // Erreur sans incidence } finally { statement.close(); } } private ResultSet executeQuery(final Statement stmt, final String query) throws SQLException { try { return stmt.executeQuery(query); } catch (SQLException ex) { APP.error("Erreur durant l'execution de la requ�te : \n\t " + query); throw ex; } } private void generateColumnHeader(PrintWriter writer) { boolean isBreak = false; if (!columnHeader) { return; } for (int i = 0; i < columns.length; i++) { if (!columns[i].isBreakField() && isBreak) { writer.println(); } else if (columnSeparator != null && i > 0) { writer.print(columnSeparator); } isBreak = columns[i].isBreakField(); writer.print(columns[i].buildColumnHeader()); } writer.println(); } private int generateContent(Context context, Connection connection, String query, PrintWriter writer) throws SQLException, GenerationException { boolean canWriteValue; boolean isPreviousColumnBreak = false; boolean applyBreakLine; Map<Integer, String> breakFields = new HashMap<Integer, String>(); int sectionLines = 0; generateSectionHeader(context, writer); generateColumnHeader(writer); Statement statement = connection.createStatement(); try { String query1 = context.replaceVariables(query); ResultSet rs = executeQuery(statement, query1); while (rs.next()) { sectionLines++; canWriteValue = false; applyBreakLine = checkBreak(breakFields, rs); for (int i = 0; i < columns.length; i++) { if (!columns[i].isBreakField() && isPreviousColumnBreak && applyBreakLine) { writer.println(); } else if (columnSeparator != null && canWriteValue) { writer.print(columnSeparator); } String value = columns[i].proceedField(rs); canWriteValue = checkWriteValue(value, applyBreakLine, breakFields, i); if (canWriteValue) { writer.print(value); } isPreviousColumnBreak = columns[i].isBreakField(); } writer.println(); } } finally { statement.close(); } return sectionLines; } private boolean checkWriteValue(String value, boolean applyBreakLine, Map<Integer, String> breakFields, int indexColumn) throws SQLException, GenerationException { boolean isWritable = false; if (columns[indexColumn].isBreakField()) { if (applyBreakLine) { isWritable = true; } } else { isWritable = true; } if (columns[indexColumn].isBreakField()) { breakFields.put(indexColumn, value); } return isWritable; } private boolean checkBreak(Map<Integer, String> breakFields, ResultSet rs) throws SQLException, GenerationException { Integer index = 0; for (FileColumnGenerator column : columns) { if (column.isBreakField()) { if (breakFields.isEmpty() || !breakFields.get(index).equals(column.proceedField(rs))) { return true; } } index++; } return false; } private void generateSectionHeader(Context ctxt, PrintWriter os) { if (sectionHeader == null) { return; } os.println(ctxt.replaceVariables(sectionHeader)); } }