/*******************************************************************************
* 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:
* Generoso Pagano - initial API and implementation
******************************************************************************/
package fr.inria.soctrace.lib.storage.visitors;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import fr.inria.soctrace.lib.model.AnalysisResult;
import fr.inria.soctrace.lib.model.AnalysisResultAnnotationData;
import fr.inria.soctrace.lib.model.AnalysisResultData.AnalysisResultType;
import fr.inria.soctrace.lib.model.AnalysisResultGroupData;
import fr.inria.soctrace.lib.model.AnalysisResultGroupData.DepthFirstIterator;
import fr.inria.soctrace.lib.model.AnalysisResultProcessedTraceData;
import fr.inria.soctrace.lib.model.AnalysisResultSearchData;
import fr.inria.soctrace.lib.model.Annotation;
import fr.inria.soctrace.lib.model.AnnotationParam;
import fr.inria.soctrace.lib.model.AnnotationParamType;
import fr.inria.soctrace.lib.model.AnnotationType;
import fr.inria.soctrace.lib.model.Event;
import fr.inria.soctrace.lib.model.EventParam;
import fr.inria.soctrace.lib.model.EventParamType;
import fr.inria.soctrace.lib.model.EventProducer;
import fr.inria.soctrace.lib.model.EventType;
import fr.inria.soctrace.lib.model.File;
import fr.inria.soctrace.lib.model.Group;
import fr.inria.soctrace.lib.model.Group.LeafMapping;
import fr.inria.soctrace.lib.model.ISearchable;
import fr.inria.soctrace.lib.model.OrderedGroup;
import fr.inria.soctrace.lib.model.UnorderedGroup;
import fr.inria.soctrace.lib.model.utils.SoCTraceException;
import fr.inria.soctrace.lib.storage.TraceDBObject;
import fr.inria.soctrace.lib.storage.utils.SQLConstants;
import fr.inria.soctrace.lib.storage.utils.SQLConstants.FramesocTable;
import fr.inria.soctrace.lib.utils.IdManager;
import fr.inria.soctrace.lib.utils.SoctraceUtils;
/**
* Visitor able to save the entities of the Trace DB
*
* @author "Generoso Pagano <generoso.pagano@inria.fr>"
*
*/
public class TraceDBSaveVisitor extends ModelVisitor {
/**
* DB object related to this visitor
*/
private TraceDBObject traceDB;
/**
* This variable is used to automatically assign ID to analysis results without replicating it
* (e.g. if 2 analysis result are saved without flushing the visitor batches). - At visitor
* initialization the variable gets the MAX ID in ANALYSIS_RESULT table. - At each
* visit(AnalysisResult) it gets incremented. - At each postClearBatches it gets the (updated)
* MAX ID again.
*/
private int analysisResultLastId;
/**
* The constructor.
*
* @param traceDB
* trace DB object
* @throws SoCTraceException
*/
public TraceDBSaveVisitor(TraceDBObject traceDB) throws SoCTraceException {
super();
this.traceDB = traceDB;
try {
Connection conn = traceDB.getConnection();
PreparedStatementDescriptor psd = null;
// Raw trace
// Events
psd = new PreparedStatementDescriptor(
conn.prepareStatement(SQLConstants.PREPARED_STATEMENT_EVENT_INSERT),
FramesocTable.EVENT);
addDescriptor(psd);
psd = new PreparedStatementDescriptor(
conn.prepareStatement(SQLConstants.PREPARED_STATEMENT_EVENT_TYPE_INSERT),
FramesocTable.EVENT_TYPE);
addDescriptor(psd);
psd = new PreparedStatementDescriptor(
conn.prepareStatement(SQLConstants.PREPARED_STATEMENT_EVENT_PARAM_INSERT),
FramesocTable.EVENT_PARAM);
addDescriptor(psd);
psd = new PreparedStatementDescriptor(
conn.prepareStatement(SQLConstants.PREPARED_STATEMENT_EVENT_PARAM_TYPE_INSERT),
FramesocTable.EVENT_PARAM_TYPE);
addDescriptor(psd);
// Event Producers
psd = new PreparedStatementDescriptor(
conn.prepareStatement(SQLConstants.PREPARED_STATEMENT_EVENT_PRODUCER_INSERT),
FramesocTable.EVENT_PRODUCER);
addDescriptor(psd);
// File
psd = new PreparedStatementDescriptor(
conn.prepareStatement(SQLConstants.PREPARED_STATEMENT_FILE_INSERT),
FramesocTable.FILE);
addDescriptor(psd);
// Analysis results
// Analysis Result
postClearBatches();
psd = new PreparedStatementDescriptor(
conn.prepareStatement(SQLConstants.PREPARED_STATEMENT_ANALYSIS_RESULT_INSERT),
FramesocTable.ANALYSIS_RESULT);
addDescriptor(psd);
// Search
psd = new PreparedStatementDescriptor(
conn.prepareStatement(SQLConstants.PREPARED_STATEMENT_SEARCH_INSERT),
FramesocTable.SEARCH);
addDescriptor(psd);
psd = new PreparedStatementDescriptor(
conn.prepareStatement(SQLConstants.PREPARED_STATEMENT_SEARCH_MAPPING_INSERT),
FramesocTable.SEARCH_MAPPING);
addDescriptor(psd);
// Annotation
psd = new PreparedStatementDescriptor(
conn.prepareStatement(SQLConstants.PREPARED_STATEMENT_ANNOTATION_INSERT),
FramesocTable.ANNOTATION);
addDescriptor(psd);
psd = new PreparedStatementDescriptor(
conn.prepareStatement(SQLConstants.PREPARED_STATEMENT_ANNOTATION_TYPE_INSERT),
FramesocTable.ANNOTATION_TYPE);
addDescriptor(psd);
psd = new PreparedStatementDescriptor(
conn.prepareStatement(SQLConstants.PREPARED_STATEMENT_ANNOTATION_PARAM_INSERT),
FramesocTable.ANNOTATION_PARAM);
addDescriptor(psd);
psd = new PreparedStatementDescriptor(
conn.prepareStatement(SQLConstants.PREPARED_STATEMENT_ANNOTATION_PARAM_TYPE_INSERT),
FramesocTable.ANNOTATION_PARAM_TYPE);
addDescriptor(psd);
// Group
psd = new PreparedStatementDescriptor(
conn.prepareStatement(SQLConstants.PREPARED_STATEMENT_GROUP_INSERT),
FramesocTable.ENTITY_GROUP);
addDescriptor(psd);
psd = new PreparedStatementDescriptor(
conn.prepareStatement(SQLConstants.PREPARED_STATEMENT_GROUP_MAPPING_INSERT),
FramesocTable.GROUP_MAPPING);
addDescriptor(psd);
// Processed Trace
psd = new PreparedStatementDescriptor(
conn.prepareStatement(SQLConstants.PREPARED_STATEMENT_PROCESSED_TRACE_INSERT),
FramesocTable.PROCESSED_TRACE);
addDescriptor(psd);
} catch (SQLException e) {
throw new SoCTraceException(e);
}
}
@Override
protected void postClearBatches() throws SoCTraceException {
// reset analysis result last id to the max in the DB
analysisResultLastId = traceDB.getMaxId(FramesocTable.ANALYSIS_RESULT.toString(), "ID");
}
/*
* Events
*/
@Override
public void visit(Event event) throws SoCTraceException {
try {
PreparedStatementDescriptor psd = getDescriptor(FramesocTable.EVENT);
psd.visited = true;
psd.statement.setInt(1, event.getId());
psd.statement.setInt(2, event.getType().getId());
psd.statement.setInt(3, event.getEventProducer().getId());
psd.statement.setLong(4, event.getTimestamp());
psd.statement.setInt(5, event.getCpu());
psd.statement.setInt(6, event.getPage());
psd.statement.setInt(7, event.getCategory());
psd.statement.setLong(8, event.getLongPar());
psd.statement.setDouble(9, event.getDoublePar());
psd.statement.addBatch();
} catch (SQLException e) {
throw new SoCTraceException(e);
}
}
@Override
public void visit(EventType eventType) throws SoCTraceException {
try {
PreparedStatementDescriptor psd = getDescriptor(FramesocTable.EVENT_TYPE);
psd.visited = true;
psd.statement.setInt(1, eventType.getId());
psd.statement.setInt(2, eventType.getCategory());
psd.statement.setString(3, eventType.getName());
psd.statement.addBatch();
} catch (SQLException e) {
throw new SoCTraceException(e);
}
}
@Override
public void visit(EventParam eventParam) throws SoCTraceException {
try {
PreparedStatementDescriptor psd = getDescriptor(FramesocTable.EVENT_PARAM);
psd.visited = true;
psd.statement.setInt(1, eventParam.getId());
psd.statement.setInt(2, eventParam.getEvent().getId());
psd.statement.setInt(3, eventParam.getEventParamType().getId());
psd.statement.setString(4, eventParam.getValue());
psd.statement.addBatch();
} catch (SQLException e) {
throw new SoCTraceException(e);
}
}
@Override
public void visit(EventParamType eventParamType) throws SoCTraceException {
try {
PreparedStatementDescriptor psd = getDescriptor(FramesocTable.EVENT_PARAM_TYPE);
psd.visited = true;
psd.statement.setInt(1, eventParamType.getId());
psd.statement.setInt(2, eventParamType.getEventType().getId());
psd.statement.setString(3, eventParamType.getName());
psd.statement.setString(4, eventParamType.getType());
psd.statement.addBatch();
} catch (SQLException e) {
throw new SoCTraceException(e);
}
}
/*
* Event Producers
*/
@Override
public void visit(EventProducer eventProducer) throws SoCTraceException {
try {
PreparedStatementDescriptor psd = getDescriptor(FramesocTable.EVENT_PRODUCER);
psd.visited = true;
psd.statement.setInt(1, eventProducer.getId());
psd.statement.setString(2, eventProducer.getType());
psd.statement.setString(3, eventProducer.getLocalId());
psd.statement.setString(4, eventProducer.getName());
psd.statement.setInt(5, eventProducer.getParentId());
psd.statement.addBatch();
} catch (SQLException e) {
throw new SoCTraceException(e);
}
}
/*
* File
*/
@Override
public void visit(File file) throws SoCTraceException {
try {
PreparedStatementDescriptor psd = getDescriptor(FramesocTable.FILE);
psd.visited = true;
psd.statement.setInt(1, file.getId());
psd.statement.setString(2, file.getPath());
psd.statement.setString(3, file.getDescription());
psd.statement.addBatch();
} catch (SQLException e) {
throw new SoCTraceException(e);
}
}
/*
* Results
*/
@Override
public void visit(AnalysisResult analysisResult) throws SoCTraceException {
try {
analysisResult.setId(++analysisResultLastId);
analysisResult.setDate(new Timestamp(new Date().getTime()));
PreparedStatementDescriptor psd = getDescriptor(FramesocTable.ANALYSIS_RESULT);
psd.visited = true;
psd.statement.setInt(1, analysisResult.getId());
psd.statement.setInt(2, analysisResult.getTool().getId());
psd.statement.setString(3, analysisResult.getType());
// XXX see note at the bottom of ModelVisitor.java
psd.statement.setString(4, SoctraceUtils.timestampToString(analysisResult.getDate()));
psd.statement.setString(5, analysisResult.getDescription());
psd.statement.addBatch();
if (analysisResult.getData() == null)
throw new SoCTraceException("Trying to save an analysis result with no data");
String type = analysisResult.getType();
if (type.equals(AnalysisResultType.TYPE_SEARCH.toString())) {
saveSearchResult(analysisResult);
} else if (type.equals(AnalysisResultType.TYPE_GROUP.toString())) {
saveGroupResult(analysisResult);
} else if (type.equals(AnalysisResultType.TYPE_ANNOTATION.toString())) {
saveAnnotationResult(analysisResult);
} else if (type.equals(AnalysisResultType.TYPE_PROCESSED_TRACE.toString())) {
saveProcessedTraceResult(analysisResult);
}
} catch (SQLException e) {
throw new SoCTraceException(e);
}
}
/*
* U t i l i t i e s
*/
private void saveSearchResult(AnalysisResult analysisResult) throws SQLException,
SoCTraceException {
AnalysisResultSearchData data = (AnalysisResultSearchData) analysisResult.getData();
// search
PreparedStatementDescriptor psd = getDescriptor(FramesocTable.SEARCH);
psd.visited = true;
psd.statement.setInt(1, analysisResult.getId());
psd.statement.setString(2, data.getSearchCommand());
psd.statement.setString(3, data.getTargetEntity());
psd.statement.addBatch();
// mapping
psd = getDescriptor(FramesocTable.SEARCH_MAPPING);
psd.visited = true;
for (ISearchable e : data.getElements()) {
psd.statement.setInt(1, analysisResult.getId());
psd.statement.setInt(2, e.getId());
psd.statement.addBatch();
}
}
private void saveGroupResult(AnalysisResult analysisResult) throws SQLException,
SoCTraceException {
AnalysisResultGroupData data = (AnalysisResultGroupData) analysisResult.getData();
PreparedStatementDescriptor psdGroup = getDescriptor(FramesocTable.ENTITY_GROUP);
PreparedStatementDescriptor psdMapping = getDescriptor(FramesocTable.GROUP_MAPPING);
psdGroup.visited = true;
psdMapping.visited = true;
DepthFirstIterator treeIt = data.getDepthFirstIterator();
IdManager mappingIdManager = new IdManager();
while (treeIt.hasNext()) {
Group g = treeIt.next();
psdGroup.statement.setInt(1, analysisResult.getId());
psdGroup.statement.setInt(2, g.getId());
psdGroup.statement.setInt(3, g.getParentId());
psdGroup.statement.setString(4, g.getName());
psdGroup.statement.setString(5, g.getTargetEntity());
psdGroup.statement.setString(6, g.getGroupingOperator());
psdGroup.statement.setBoolean(7, g.isOrdered());
psdGroup.statement.setInt(8, g.getSequenceNumber());
psdGroup.statement.addBatch();
if (g instanceof OrderedGroup) {
Map<Integer, LeafMapping> sons = ((OrderedGroup) g).getSonLeaves();
Iterator<Entry<Integer, LeafMapping>> it = (Iterator<Entry<Integer, LeafMapping>>) sons
.entrySet().iterator();
while (it.hasNext()) {
Entry<Integer, LeafMapping> pairs = (Entry<Integer, LeafMapping>) it.next();
LeafMapping mapping = pairs.getValue();
mapping.setMappingId(mappingIdManager.getNextId());
psdMapping.statement.setInt(1, analysisResult.getId());
psdMapping.statement.setInt(2, mapping.getMappingId());
psdMapping.statement.setInt(3, g.getId());
psdMapping.statement.setInt(4, mapping.getSon().getId());
psdMapping.statement.setInt(5, pairs.getKey());
psdMapping.statement.addBatch();
}
} else {
List<LeafMapping> leaves = ((UnorderedGroup) g).getSonLeaves();
for (LeafMapping mapping : leaves) {
mapping.setMappingId(mappingIdManager.getNextId());
psdMapping.statement.setInt(1, analysisResult.getId());
psdMapping.statement.setInt(2, mapping.getMappingId());
psdMapping.statement.setInt(3, g.getId());
psdMapping.statement.setInt(4, mapping.getSon().getId());
psdMapping.statement.setInt(5, -1);
psdMapping.statement.addBatch();
}
}
}
}
private void saveAnnotationResult(AnalysisResult analysisResult) throws SQLException,
SoCTraceException {
AnalysisResultAnnotationData annotationData = (AnalysisResultAnnotationData) analysisResult
.getData();
PreparedStatementDescriptor psdAnnotation = getDescriptor(FramesocTable.ANNOTATION);
PreparedStatementDescriptor psdAnnotationType = getDescriptor(FramesocTable.ANNOTATION_TYPE);
PreparedStatementDescriptor psdAnnotationParam = getDescriptor(FramesocTable.ANNOTATION_PARAM);
PreparedStatementDescriptor psdAnnotationParamType = getDescriptor(FramesocTable.ANNOTATION_PARAM_TYPE);
psdAnnotation.visited = true;
psdAnnotationType.visited = true;
psdAnnotationParam.visited = true;
psdAnnotationParamType.visited = true;
for (AnnotationType at : annotationData.getAnnotationTypes()) {
psdAnnotationType.statement.setInt(1, analysisResult.getId());
psdAnnotationType.statement.setInt(2, at.getId());
psdAnnotationType.statement.setString(3, at.getName());
psdAnnotationType.statement.addBatch();
for (AnnotationParamType pt : at.getParamTypes()) {
psdAnnotationParamType.statement.setInt(1, analysisResult.getId());
psdAnnotationParamType.statement.setInt(2, pt.getId());
psdAnnotationParamType.statement.setInt(3, pt.getAnnotationType().getId());
psdAnnotationParamType.statement.setString(4, pt.getName());
psdAnnotationParamType.statement.setString(5, pt.getType());
psdAnnotationParamType.statement.addBatch();
}
}
for (Annotation a : annotationData.getAnnotations()) {
psdAnnotation.statement.setInt(1, analysisResult.getId());
psdAnnotation.statement.setInt(2, a.getId());
psdAnnotation.statement.setInt(3, a.getAnnotationType().getId());
psdAnnotation.statement.setString(4, a.getName());
psdAnnotation.statement.addBatch();
for (AnnotationParam p : a.getParams()) {
psdAnnotationParam.statement.setInt(1, analysisResult.getId());
psdAnnotationParam.statement.setInt(2, p.getId());
psdAnnotationParam.statement.setInt(3, a.getId());
psdAnnotationParam.statement.setInt(4, p.getAnnotationParamType().getId());
psdAnnotationParam.statement.setString(5, p.getValue());
psdAnnotationParam.statement.addBatch();
}
}
}
private void saveProcessedTraceResult(AnalysisResult analysisResult) throws SQLException,
SoCTraceException {
AnalysisResultProcessedTraceData data = (AnalysisResultProcessedTraceData) analysisResult
.getData();
PreparedStatementDescriptor psd = getDescriptor(FramesocTable.PROCESSED_TRACE);
psd.visited = true;
psd.statement.setInt(1, analysisResult.getId());
psd.statement.setInt(2, data.getProcessedTrace().getId());
psd.statement.addBatch();
}
}