/*
* codjo.net
*
* Common Apache License 2.0
*/
package net.codjo.broadcast.server;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import net.codjo.broadcast.common.ComputedContextAdapter;
import net.codjo.broadcast.common.ComputedFieldGenerator;
import net.codjo.broadcast.common.Context;
import net.codjo.broadcast.common.Preferences;
import net.codjo.broadcast.common.columns.FileColumnGenerator;
import net.codjo.broadcast.common.computed.ComputedField;
import net.codjo.database.common.api.DatabaseFactory;
import net.codjo.database.common.api.DatabaseQueryHelper;
import net.codjo.database.common.api.confidential.DatabaseTranscoder;
import net.codjo.database.common.api.structure.SqlTable;
import net.codjo.variable.TemplateInterpreter;
import net.codjo.variable.UnknownVariableException;
import static net.codjo.broadcast.common.computed.ComputedField.WARNINGS;
/**
* DOCUMENT ME!
*
* @author $Author: galaber $
* @version $Revision: 1.3 $
*/
class DefaultComputedFieldGenerator implements ComputedFieldGenerator {
private Map computedField = new HashMap();
private Preferences preference;
private Set fieldList;
DefaultComputedFieldGenerator(Preferences preference) {
this(preference, preference.getComputedFields());
}
protected DefaultComputedFieldGenerator(Preferences preference, ComputedField[] fields) {
if (fields == null || fields.length == 0) {
throw new IllegalArgumentException("Le tableau de ComputedField n'a pas ete initialise");
}
for (ComputedField field : fields) {
if (WARNINGS.equals(field.getName())) {
throw new IllegalArgumentException(WARNINGS + " is a reserved column name");
}
computedField.put(field.getName(), field);
}
this.preference = preference;
}
public void createComputedTable(Context ctxt, FileColumnGenerator[] fileColumnGenerator, Connection con)
throws SQLException {
if (fileColumnGenerator == null || fileColumnGenerator.length == 0) {
throw new IllegalArgumentException("Le tableau de 'FileColumnGenerator'"
+ " n'a pas ete initialise");
}
if (con == null) {
throw new IllegalArgumentException("La connexion n'a pas ete initialise");
}
fieldList = determineFieldList(fileColumnGenerator);
ctxt.setComputedTableWasCreated(false);
if (!fieldList.isEmpty()) {
createComputedTable(ctxt, con, fieldList);
ctxt.setComputedTableWasCreated(true);
}
}
public void fillComputedTable(Context ctxt, Connection con)
throws SQLException {
if (con == null) {
throw new IllegalArgumentException("La connexion n'a pas ete initialise");
}
if (!fieldList.isEmpty()) {
fillComputedTableKey(ctxt, con);
updateComputedField(ctxt, con, fieldList);
}
}
/**
* DOCUMENT ME!
*
* @param ctxt -
* @param con -
* @param fields -
*
* @throws SQLException -
*/
protected void createComputedTable(Context ctxt, Connection con, Set fields)
throws SQLException {
dropComputedTable(ctxt, con);
Statement stmt = con.createStatement();
String createTableQueryString = "SELECTION_ID numeric(18) not null, "
+ "$warningsField$ $warningsFieldType$ null, "
+ " $computedTable.fields$"
+ " constraint PK_TMP_COMPUTED primary key (SELECTION_ID)";
try {
TemplateInterpreter interpreter = new TemplateInterpreter();
interpreter.add("computedTable.name", preference.getComputedTableName());
interpreter.add("computedTable.fields", getComputedFieldDef(fields));
interpreter.add("warningsField", ComputedField.WARNINGS);
interpreter.add("warningsFieldType", getClobType());
interpreter.addAsVariable(ctxt.getParameters());
SqlTemplate sqlTemplate = new SqlTemplate(createTableQueryString) {
@Override
public String buildQuery(TemplateInterpreter interpret, String sqlQuery) {
return buildCreateTableQuery(interpret, sqlQuery);
}
};
sqlTemplate.executeUpdate(con, interpreter);
}
finally {
stmt.close();
}
}
private String getClobType() {
return new DatabaseFactory().createDatabaseTranscoder().transcodeSqlFieldType(DatabaseTranscoder.LONGVARCHAR);
}
/**
* Drop de la table de calcul.
*
* @param ctxt -
* @param con -
*
* @throws SQLException -
*/
protected void dropComputedTable(Context ctxt, Connection con)
throws SQLException {
String dropQuery = "drop table " + preference.getComputedTableName();
TemplateInterpreter interpreter = new TemplateInterpreter();
interpreter.add("computedTable.name", preference.getComputedTableName());
interpreter.addAsVariable(ctxt.getParameters());
SqlTemplate sqlTemplate = new SqlTemplate(dropQuery);
try {
sqlTemplate.executeUpdate(con, interpreter);
}
catch (SQLException e) {
; //Erreur sans incidence
}
}
/**
* Mise � jour des champs calcules.
*
* @param ctxt Le contexte
* @param con La connexion
* @param fields Description of the Parameter
*
* @throws SQLException Erreur d'acces a la base de donn�es
*/
protected void updateComputedField(Context ctxt, Connection con, Set fields)
throws SQLException {
ComputedContextAdapter adapter = new ComputedContextAdapter(preference, ctxt);
for (Object aFieldList : fields) {
ComputedField field = (ComputedField)aFieldList;
field.compute(adapter, con);
}
}
private String buildCreateTableQuery(TemplateInterpreter interpreter, String createTableQueryString) {
try {
DatabaseQueryHelper queryHelper = new DatabaseFactory().getDatabaseQueryHelper();
String tableName = interpreter.evaluate("$computedTable.name$");
String tableScript = queryHelper.buildCreateTableQuery(SqlTable.temporaryTable(tableName),
createTableQueryString);
return interpreter.evaluate(tableScript);
}
catch (UnknownVariableException error) {
throw new IllegalArgumentException("La chaine " + createTableQueryString
+ " contient des variables inconnues : " + error.getMessage());
}
}
/**
* Determine la liste des champs calcules.
*
* @param fileColumnGenerator La liste des colonnes du fichier a generer
*
* @return La liste des champs
*
* @throws IllegalArgumentException Nom de champ inconnue.
*/
private Set determineFieldList(FileColumnGenerator[] fileColumnGenerator) {
Set set = new HashSet();
for (FileColumnGenerator aFileColumnGenerator : fileColumnGenerator) {
if (isComputedField(aFileColumnGenerator)) {
if (isKnownComputedField(aFileColumnGenerator)) {
set.add(computedField.get(aFileColumnGenerator.getFieldInfo().getDBFieldName()));
}
else {
throw new IllegalArgumentException("Le nom du champ calcule : "
+ aFileColumnGenerator.getFieldInfo() + " est inconnu");
}
}
}
return set;
}
/**
* Insertion de la cle de selection dans la table de calcul
*
* @param context -
* @param con -
*/
private void fillComputedTableKey(Context context, Connection con)
throws SQLException {
TemplateInterpreter interpreter = new TemplateInterpreter();
interpreter.add("computed.name", preference.getComputedTableName());
interpreter.add("selection.name", preference.getSelectionTableName());
interpreter.addAsVariable(context.getParameters());
new SqlTemplate("insert into $computed.name$ (SELECTION_ID) "
+ "select SELECTION_ID from $selection.name$").executeUpdate(con, interpreter);
}
private String getComputedFieldDef(Set fields) {
StringBuilder buffer = new StringBuilder();
for (Object aFieldList : fields) {
ComputedField field = (ComputedField)aFieldList;
buffer.append(field.getSqlDefinition()).append(" null,");
}
return buffer.toString();
}
private boolean isComputedField(final FileColumnGenerator columnGenerator) {
return preference.getComputedTableName().equals(columnGenerator.getFieldInfo()
.getDBTableName());
}
private boolean isKnownComputedField(final FileColumnGenerator fileColumnGenerator) {
return computedField.containsKey(fileColumnGenerator.getFieldInfo()
.getDBFieldName());
}
}