/*******************************************************************************
* Copyright (c) 2012-2015 INRIA.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Youenn Corre - initial API and implementation
******************************************************************************/
package fr.inria.soctrace.lib.storage.updater;
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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.inria.soctrace.lib.model.utils.SoCTraceException;
import fr.inria.soctrace.lib.storage.SystemDBObject;
import fr.inria.soctrace.lib.storage.utils.SQLConstants.FramesocTable;
/**
* Abstract class that handles the update from a system DB model to another
*
* @author "Youenn Corre <youenn.corre@inria.fr>"
*/
public abstract class DBModelRebuilder {
private static final Logger logger = LoggerFactory.getLogger(DBModelRebuilder.class);
public static final Integer MISSING_PARAMETER_VALUE = -1;
private static final String UNSUPPORTED_MISSING_VALUE_MSG = "Updater encountered a non-updatable missing value";
// Current table being updated
protected FramesocTable table;
// Query to get the info on the table
protected String getTableQuery;
/**
* Contains the list of differences between current DB model and older one.
* It should contain parameters that are no longer in the table, or that are
* at a different position. Parameters of the current DB model but that are
* not in the ancient one, have their position set to
* MISSING_PARAMETER_VALUE
*/
protected Map<String, Integer> oldModelDiff;
// The old updated system DB model
protected SystemDBObject oldSysDB;
// The newly filled system DB model
protected SystemDBObject newSysDB;
public DBModelRebuilder() {
oldModelDiff = new HashMap<String, Integer>();
}
/**
* Set system database objects
*
* @param oldDB
* the old system object DB
* @param newDB
* the new system object DB
*/
public void setDBs(SystemDBObject oldDB, SystemDBObject newDB) {
oldSysDB = oldDB;
newSysDB = newDB;
}
/**
* Copy the value of a table
*
* @param statement
* the statement in which the new values are stored
* @param rs
* the result set of the query of the updated table
* @throws SoCTraceException
*/
protected abstract void copyValues(PreparedStatement statement, ResultSet rs)
throws SoCTraceException;
/**
* Get the name of the column at the position pos
*
* @param pos
* the index of the column we want to get
* @return the name of the column
*/
public abstract String getValueAt(int pos);
/**
* Get the number of columns in a given table
*
* @return the number of columns
*/
public abstract int getColumnNumber();
/**
* Factory to instantiate DBModelRebuiltder for each table
*
* @param modelName
* the name of the table
* @return an instance of the a Model rebuilder corresponding to the given
* table name
*/
public static DBModelRebuilder DBModelRebuilderFactory(FramesocTable framesocTable) {
switch (framesocTable) {
case TRACE:
return new TraceModelRebuilder();
case TRACE_TYPE:
return new TraceTypeModelRebuilder();
case TRACE_PARAM:
return new TraceParamModelRebuilder();
case TRACE_PARAM_TYPE:
return new TraceParamTypeModelRebuilder();
case TOOL:
return new ToolModelRebuilder();
default:
return null;
}
}
/**
* Copy at table from the old system db into the new one
*/
public void copyTable() {
try {
// Get all traces
Statement stm = oldSysDB.getConnection().createStatement();
ResultSet rs = stm.executeQuery("SELECT * FROM " + table);
// For each trace
while (rs.next()) {
PreparedStatement statement = newSysDB.getConnection()
.prepareStatement(getTableQuery);
// Copy each value
copyValues(statement, rs);
// Save into new DB
statement.addBatch();
statement.executeBatch();
statement.close();
}
stm.close();
newSysDB.commit();
} catch (SoCTraceException | SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* Build a statement with from the result of a query from the old DB
*
* @param statement
* the built statement
* @param rs
* the result set from which we copy the value
* @param destPos
* the column index of the destination DB
* @param srcPos
* the column index of the source DB
* @param type
* the type of the value
* @throws SoCTraceException
*/
protected void addToStatement(PreparedStatement statement, ResultSet rs,
int destPos, int srcPos, String type) throws SoCTraceException {
try {
switch (type) {
case "String":
statement.setString(destPos, rs.getString(srcPos));
break;
case "Integer":
statement.setInt(destPos, rs.getInt(srcPos));
break;
case "Long":
statement.setLong(destPos, rs.getLong(srcPos));
break;
case "Boolean":
statement.setBoolean(destPos, rs.getBoolean(srcPos));
break;
case "Float":
statement.setFloat(destPos, rs.getFloat(srcPos));
break;
case "Double":
statement.setDouble(destPos, rs.getDouble(srcPos));
break;
case "Short":
statement.setShort(destPos, rs.getShort(srcPos));
break;
default:
logger.error("Unsupported type {}", type);
}
} catch (SQLException e) {
throw new SoCTraceException(e.getMessage());
}
}
/**
* Build the statement with a specific value
*
* @param statement
* the built statement
* @param value
* Specific value to be added
* @param destPos
* the column index of the destination DB
* @param type
* the type of the value
* @throws SoCTraceException
*/
protected void addToStatement(PreparedStatement statement, Object value,
int destPos, String type) throws SoCTraceException {
// Unsupported missing value
if(value == null)
throw new SoCTraceException(UNSUPPORTED_MISSING_VALUE_MSG);
try {
switch (type) {
case "String":
statement.setString(destPos, (String) value);
break;
case "Integer":
statement.setInt(destPos, (Integer) value);
break;
case "Long":
statement.setLong(destPos, (Long) value);
break;
case "Boolean":
statement.setBoolean(destPos, (Boolean) value);
break;
case "Float":
statement.setFloat(destPos, (Float) value);
break;
case "Double":
statement.setDouble(destPos, (Double) value);
break;
case "Short":
statement.setShort(destPos, (Short) value);
break;
default:
logger.error("Unsupported type {}", type);
}
} catch (SQLException e) {
throw new SoCTraceException(e.getMessage());
}
}
public Map<String, Integer> getOldModelMapDiff() {
return oldModelDiff;
}
public void setOldModelMapDiff(Map<String, Integer> oldModelMapDiff) {
this.oldModelDiff = oldModelMapDiff;
}
public FramesocTable getTable() {
return table;
}
public void setTable(FramesocTable table) {
this.table = table;
}
public String getGetTableQuery() {
return getTableQuery;
}
public void setGetTableQuery(String getTableQuery) {
this.getTableQuery = getTableQuery;
}
}