/*******************************************************************************
* 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.utils;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import fr.inria.soctrace.lib.model.utils.SoCTraceException;
import fr.inria.soctrace.lib.storage.DBObject;
import fr.inria.soctrace.lib.storage.SystemDBObject;
import fr.inria.soctrace.lib.storage.DBObject.DBMode;
import fr.inria.soctrace.lib.storage.dbmanager.DBManager;
import fr.inria.soctrace.lib.storage.updater.DBModelRebuilder;
import fr.inria.soctrace.lib.storage.utils.SQLConstants.FramesocTable;
import fr.inria.soctrace.lib.utils.Configuration;
import fr.inria.soctrace.lib.utils.Configuration.SoCTraceProperty;
/**
* Class checking that an existing database system model is similar to the
* current one. If automatically try to update and import the from the old data
* model into the new one.
*
* @author "Youenn Corre <youenn.corre@inria.fr>"
*/
public class DBModelChecker {
// List of the tables that need to be updated
private final static FramesocTable[] checkedTableModel = {
FramesocTable.TRACE, FramesocTable.TRACE_TYPE,
FramesocTable.TRACE_PARAM_TYPE, FramesocTable.TRACE_PARAM,
FramesocTable.TOOL };
public static final String NEW_SYSTEM_DB_SUFFIX = "_tmp";
/**
* List of the table model rebuilders
*/
private List<DBModelRebuilder> dbModelRebuilders = new ArrayList<DBModelRebuilder>();
/**
* Find and store all the differences between the systemdbObject and the
* current DB model in Framesoc
*
* @param systemDB
* the tested systemDb object
* @param modelBuilder
* a model builder for a given table of the systemDB
* @return true if they are similar, false otherwise
* @throws SoCTraceException
*/
public void getDatabaseModelDifferences(SystemDBObject systemDB,
DBModelRebuilder modelBuilder) throws SoCTraceException {
boolean tableHasDifference = false;
int cpt = 1;
FramesocTable framesocTable = modelBuilder.getTable();
dbModelRebuilders.add(modelBuilder);
try {
Statement stm = systemDB.getConnection().createStatement();
String query = systemDB.getTraceInfoQuery(framesocTable);
Map<String, Integer> oldModel = new HashMap<String, Integer>();
tableHasDifference = false;
cpt = 1;
// Get info
ResultSet rs = stm.executeQuery(query);
while (rs.next()) {
String columnName = rs.getString(systemDB.getColumnNameIndex());
oldModel.put(columnName, cpt);
// Check that column names are similar
if (!columnName.equals(modelBuilder.getValueAt(cpt))) {
// Save the diff column name and its position in the old
// model
modelBuilder.getOldModelMapDiff().put(columnName, cpt);
tableHasDifference = true;
}
cpt++;
}
int currentModelLength = modelBuilder.getColumnNumber();
// If size is different return false (missing field)
if (cpt - 1 != currentModelLength)
tableHasDifference = true;
// If a diff was found
if (tableHasDifference) {
// Also check in reverse for potential missing parameter
for (int i = 1; i <= currentModelLength; i++) {
String currentModelColName = modelBuilder.getValueAt(i);
if (!oldModel.containsKey(currentModelColName))
modelBuilder.getOldModelMapDiff().put(
currentModelColName,
DBModelRebuilder.MISSING_PARAMETER_VALUE);
}
}
stm.close();
} catch (SQLException | SoCTraceException | SecurityException
| IllegalArgumentException e) {
throw new SoCTraceException(e);
}
}
/**
* Try to update the database from one model to the current one
*/
public void updateDB() throws SoCTraceException {
String tmpDbName = Configuration.getInstance().get(
SoCTraceProperty.soctrace_db_name)
+ NEW_SYSTEM_DB_SUFFIX;
SystemDBObject newSysDB = null;
SystemDBObject oldsysDB = null;
// Create a new DB with the current model
try {
// If the temp DB already exists
if (DBObject.isDBExisting(tmpDbName))
// Delete it
new SystemDBObject(tmpDbName, DBMode.DB_OPEN)
.dropDatabase();
newSysDB = new SystemDBObject(tmpDbName, DBMode.DB_CREATE);
oldsysDB = new SystemDBObject(Configuration.getInstance().get(
SoCTraceProperty.soctrace_db_name), DBMode.DB_OPEN);
// Fetch the difference between the old and the new model
for (FramesocTable framesocTable : checkedTableModel) {
getDatabaseModelDifferences(oldsysDB,
DBModelRebuilder.DBModelRebuilderFactory(framesocTable));
}
// Copy similar things and import the rest
for (DBModelRebuilder dbModelrebuider : dbModelRebuilders) {
dbModelrebuider.setDBs(oldsysDB, newSysDB);
dbModelrebuider.copyTable();
}
oldsysDB.close();
newSysDB.close();
// Erase the old one and replace with the new updated one
DBManager.getDBManager(
Configuration.getInstance().get(
SoCTraceProperty.soctrace_db_name)).replaceDB(
Configuration.getInstance().get(
SoCTraceProperty.soctrace_db_name), tmpDbName);
} catch (SoCTraceException e) {
// TODO Clean up potential mess
throw new SoCTraceException(e);
} finally {
DBObject.finalClose(oldsysDB);
DBObject.finalClose(newSysDB);
if (newSysDB != null) {
// If the temp DB still exists
if (DBObject.isDBExisting(newSysDB.getDBName())) {
// Delete it
newSysDB.dropDatabase();
}
}
}
}
}