package org.openbel.framework.compiler;
import static java.lang.String.format;
import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.openbel.framework.api.internal.KamDbObject;
import org.openbel.framework.common.DBConnectionFailure;
import org.openbel.framework.common.InvalidArgument;
import org.openbel.framework.common.protonetwork.model.DocumentTable.DocumentHeader;
import org.openbel.framework.common.protonetwork.model.NamespaceTable;
import org.openbel.framework.common.protonetwork.model.NamespaceTable.TableNamespace;
import org.openbel.framework.common.protonetwork.model.ProtoNetwork;
import org.openbel.framework.compiler.kam.KAMStoreSchemaService;
import org.openbel.framework.core.compiler.CreateKAMFailure;
import org.openbel.framework.core.df.DBConnection;
import org.openbel.framework.core.df.DatabaseError;
import org.openbel.framework.core.df.DatabaseService;
import org.openbel.framework.core.kam.JdbcKAMLoaderImpl;
import org.openbel.framework.core.kam.KAMCatalogFailure;
/**
* BEL compiler phase four implementation.
*/
public class PhaseFourImpl implements DefaultPhaseFour {
/**
* Defines the DatabaseService used to connect/execute against a database.
*/
private final DatabaseService ds;
/**
* Defines the KAMStoreSchemaService used to create a KAMstore.
*/
private final KAMStoreSchemaService ksss;
/**
* Creates a phase four implementation.
*
* @param ds {@link DatabaseService}, the database service
* @param ksss {@link KAMStoreSchemaService}, the kam store schema service
*/
public PhaseFourImpl(final DatabaseService ds,
final KAMStoreSchemaService ksss) {
this.ds = ds;
this.ksss = ksss;
}
/**
* {@inheritDoc}
*/
@Override
public DBConnection stage1ConnectKAMStore(String jdbcUrl, String user,
String pass) throws DBConnectionFailure {
try {
return ds.dbConnection(jdbcUrl, user, pass);
} catch (SQLException e) {
// rethrow as fatal exception since we couldn't connect to KAMStore
throw new DBConnectionFailure(jdbcUrl, e.getMessage(), e);
}
}
/**
* {@inheritDoc}
*/
@Override
public String stage2SaveToKAMCatalog(KamDbObject kamDb)
throws KAMCatalogFailure {
if (kamDb == null) {
throw new InvalidArgument("kamDb", kamDb);
}
try {
// Load the KAM catalog schema, if it doesn't exist.
ksss.setupKAMCatalogSchema();
// Saves to KAM catalog and retrieves schema name.
String schemaName = ksss.saveToKAMCatalog(kamDb);
return schemaName;
} catch (SQLException e) {
throw new KAMCatalogFailure(kamDb.getName(), e.getMessage());
} catch (IOException e) {
throw new KAMCatalogFailure(kamDb.getName(), e.getMessage());
}
}
/**
* {@inheritDoc}
*/
@Override
public void stage3CreateKAMstore(final DBConnection db, String schemaName)
throws CreateKAMFailure {
if (db == null) {
throw new InvalidArgument("db", db);
}
try {
ksss.setupKAMStoreSchema(db, schemaName);
} catch (IOException e) {
throw new CreateKAMFailure(db, e.getMessage());
} catch (SQLException e) {
throw new CreateKAMFailure(db, e.getMessage());
}
}
/**
* {@inheritDoc}
*
* @throws SQLException
*/
@Override
public void stage4LoadKAM(DBConnection dbConnection, ProtoNetwork p2pn,
String schema) throws DatabaseError, CreateKAMFailure {
JdbcKAMLoaderImpl jkl;
try {
jkl = new JdbcKAMLoaderImpl(dbConnection, schema);
} catch (SQLException e) {
final String msg = "Error creating KAM loader";
throw new DatabaseError(schema, msg, e);
}
if (!jkl.schemaExists()) {
final String fmt = "schema \"%s\" does not exist";
final String msg = format(fmt, jkl.getSchemaName());
throw new CreateKAMFailure(dbConnection, msg);
}
try {
// load type tables
jkl.loadObjectTypes();
} catch (SQLException e) {
final String msg = "Error loading object types";
throw new DatabaseError(schema, msg, e);
}
try {
jkl.loadFunctionTypes();
} catch (SQLException e) {
final String msg = "Error loading function types";
throw new DatabaseError(schema, msg, e);
}
try {
jkl.loadRelationshipTypes();
} catch (SQLException e) {
final String msg = "Error loading relationship types";
throw new DatabaseError(schema, msg, e);
}
try {
jkl.loadAnnotationDefinitionTypes();
} catch (SQLException e) {
final String msg = "Error loading annotation definitions types";
throw new DatabaseError(schema, msg, e);
}
// load documents
List<DocumentHeader> dhs = p2pn.getDocumentTable().getDocumentHeaders();
try {
jkl.loadDocuments(dhs);
} catch (SQLException e) {
final String msg = "Error loading documents";
throw new DatabaseError(schema, msg, e);
}
// load namespaces
NamespaceTable nt = p2pn.getNamespaceTable();
Set<TableNamespace> nsl = nt.getNamespaces();
Map<TableNamespace, Integer> nsi = nt.getNamespaceIndex();
for (TableNamespace ns : nsl) {
try {
jkl.loadNamespace(nsi.get(ns), ns);
} catch (SQLException e) {
final String fmt = "Error loading namespace %s/%s";
final String msg =
format(fmt, ns.getPrefix(), ns.getResourceLocation());
throw new DatabaseError(schema, msg, e);
}
}
// load annotation definitions
try {
jkl.loadAnnotationDefinitions(p2pn.getAnnotationDefinitionTable());
} catch (SQLException e) {
final String msg = "Error loading annotation definitions";
throw new DatabaseError(schema, msg, e);
}
try {
// load annotations
jkl.loadAnnotationValues(p2pn.getAnnotationValueTable());
} catch (SQLException e) {
final String msg = "Error loading annotation values";
throw new DatabaseError(schema, msg, e);
}
try {
// load document to namespace map
jkl.loadDocumentNamespaceMap(nt.getDocumentNamespaces());
} catch (SQLException e) {
final String msg = "Error loading document namespaces";
throw new DatabaseError(schema, msg, e);
}
try {
// load nodes
jkl.loadNodes(p2pn.getNamespaceTable(), p2pn.getParameterTable(),
p2pn.getTermTable(),
p2pn.getTermParameterMapTable(),
p2pn.getProtoNodeTable());
} catch (SQLException e) {
final String msg = "Error loading nodes";
throw new DatabaseError(schema, msg, e);
}
try {
// load edges
jkl.loadEdges(p2pn.getStatementTable(), p2pn.getTermTable(),
p2pn.getProtoNodeTable(), p2pn.getProtoEdgeTable());
} catch (SQLException e) {
final String msg = "Error loading edges";
throw new DatabaseError(schema, msg, e);
}
try {
// associate annotations to statements
jkl.loadStatementAnnotationMap(p2pn
.getStatementAnnotationMapTable());
} catch (SQLException e) {
final String msg = "Error loading statement annotations";
throw new DatabaseError(schema, msg, e);
}
// close loader dao
jkl.terminate();
}
}