use crate::data;
use crate::data::uta;
use crate::data::{
error::Error, interface, interface::GeneInfoRecord, interface::TxExonsRecord,
interface::TxForRegionRecord, interface::TxIdentityInfo, interface::TxInfoRecord,
interface::TxMappingOptionsRecord, interface::TxSimilarityRecord,
};
use indexmap::IndexMap;
use seqrepo::{self, AliasOrSeqId, SeqRepo};
use std::path::PathBuf;
use std::sync::Arc;
#[derive(Debug, PartialEq, Clone)]
pub struct Config {
pub db_url: String,
pub db_schema: String,
pub seqrepo_path: String,
}
pub struct Provider {
inner: uta::Provider,
seqrepo: Arc<dyn seqrepo::Interface + Send + Sync>,
}
impl Provider {
pub fn new(config: Config) -> Result<Provider, Error> {
let seqrepo = PathBuf::from(&config.seqrepo_path);
let path = seqrepo
.parent()
.ok_or(Error::PathParent(config.seqrepo_path.clone()))?
.to_str()
.expect("problem with path to string conversion")
.to_string();
let instance = seqrepo
.file_name()
.ok_or(Error::PathBasename(config.seqrepo_path.clone()))?
.to_str()
.expect("problem with path to string conversion")
.to_string();
Ok(Self {
inner: uta::Provider::with_config(&uta::Config {
db_url: config.db_url.clone(),
db_schema: config.db_schema,
})?,
seqrepo: Arc::new(SeqRepo::new(path, &instance)?),
})
}
pub fn with_seqrepo(
config: Config,
seqrepo: Arc<dyn seqrepo::Interface + Send + Sync>,
) -> Result<Provider, Error> {
Ok(Self {
inner: uta::Provider::with_config(&uta::Config {
db_url: config.db_url.clone(),
db_schema: config.db_schema,
})?,
seqrepo,
})
}
}
impl interface::Provider for Provider {
fn data_version(&self) -> &str {
self.inner.data_version()
}
fn schema_version(&self) -> &str {
self.inner.schema_version()
}
fn get_assembly_map(
&self,
assembly: &str,
) -> Result<IndexMap<String, String>, data::error::Error> {
self.inner.get_assembly_map(assembly)
}
fn get_gene_info(&self, hgnc: &str) -> Result<GeneInfoRecord, Error> {
self.inner.get_gene_info(hgnc)
}
fn get_pro_ac_for_tx_ac(&self, tx_ac: &str) -> Result<Option<String>, Error> {
self.inner.get_pro_ac_for_tx_ac(tx_ac)
}
fn get_seq_part(
&self,
ac: &str,
begin: Option<usize>,
end: Option<usize>,
) -> Result<String, Error> {
let aos = AliasOrSeqId::Alias {
value: ac.to_owned(),
namespace: None,
};
self.seqrepo
.fetch_sequence_part(&aos, begin, end)
.map_err(Error::SeqRepoError)
}
fn get_acs_for_protein_seq(&self, seq: &str) -> Result<Vec<String>, Error> {
self.inner.get_acs_for_protein_seq(seq)
}
fn get_similar_transcripts(&self, tx_ac: &str) -> Result<Vec<TxSimilarityRecord>, Error> {
self.inner.get_similar_transcripts(tx_ac)
}
fn get_tx_exons(
&self,
tx_ac: &str,
alt_ac: &str,
alt_aln_method: &str,
) -> Result<Vec<TxExonsRecord>, Error> {
self.inner.get_tx_exons(tx_ac, alt_ac, alt_aln_method)
}
fn get_tx_for_gene(&self, gene: &str) -> Result<Vec<TxInfoRecord>, Error> {
self.inner.get_tx_for_gene(gene)
}
fn get_tx_for_region(
&self,
alt_ac: &str,
alt_aln_method: &str,
start_i: i32,
end_i: i32,
) -> Result<Vec<TxForRegionRecord>, Error> {
self.inner
.get_tx_for_region(alt_ac, alt_aln_method, start_i, end_i)
}
fn get_tx_identity_info(&self, tx_ac: &str) -> Result<TxIdentityInfo, Error> {
self.inner.get_tx_identity_info(tx_ac)
}
fn get_tx_info(
&self,
tx_ac: &str,
alt_ac: &str,
alt_aln_method: &str,
) -> Result<TxInfoRecord, Error> {
self.inner.get_tx_info(tx_ac, alt_ac, alt_aln_method)
}
fn get_tx_mapping_options(&self, tx_ac: &str) -> Result<Vec<TxMappingOptionsRecord>, Error> {
self.inner.get_tx_mapping_options(tx_ac)
}
}
#[cfg(test)]
pub mod test_helpers {
use anyhow::Error;
use seqrepo::{CacheReadingSeqRepo, CacheWritingSeqRepo, SeqRepo};
use std::{path::PathBuf, sync::Arc};
use crate::data::interface;
use super::{Config, Provider};
#[test]
fn test_sync() {
fn is_sync<T: Sync>() {}
is_sync::<super::Provider>();
}
pub fn build_provider() -> Result<Arc<dyn interface::Provider + Send + Sync>, Error> {
tracing::debug!("building provider...");
let db_url = std::env::var("TEST_UTA_DATABASE_URL")
.expect("Environment variable TEST_UTA_DATABASE_URL undefined!");
let db_schema = std::env::var("TEST_UTA_DATABASE_SCHEMA")
.expect("Environment variable TEST_UTA_DATABASE_SCHEMA undefined!");
let sr_cache_mode = std::env::var("TEST_SEQREPO_CACHE_MODE")
.expect("Environment variable TEST_SEQREPO_CACHE_MODE undefined!");
let sr_cache_path = std::env::var("TEST_SEQREPO_CACHE_PATH")
.expect("Environment variable TEST_SEQREPO_CACHE_PATH undefined!");
let (seqrepo, seqrepo_path) = if sr_cache_mode == "read" {
tracing::debug!("reading provider...");
let seqrepo: Arc<dyn seqrepo::Interface + Send + Sync> =
Arc::new(CacheReadingSeqRepo::new(sr_cache_path)?);
tracing::debug!("construction done...");
(seqrepo, "".to_string())
} else if sr_cache_mode == "write" {
tracing::debug!("writing provider...");
build_writing_sr(sr_cache_path)?
} else {
panic!("Invalid cache mode {}", &sr_cache_mode);
};
tracing::debug!("now returning provider...");
Ok(Arc::new(Provider::with_seqrepo(
Config {
db_url,
db_schema,
seqrepo_path,
},
seqrepo,
)?))
}
pub fn build_writing_sr(
sr_cache_path: String,
) -> Result<(Arc<dyn seqrepo::Interface + Send + Sync>, String), Error> {
let seqrepo_path = std::env::var("TEST_SEQREPO_PATH")
.expect("Environment variable TEST_SEQREPO_PATH undefined!");
let path_buf = PathBuf::from(seqrepo_path.clone());
let path = path_buf
.parent()
.ok_or(anyhow::anyhow!(
"Could not get parent from {}",
&seqrepo_path
))?
.to_str()
.expect("problem with path to string conversion")
.to_string();
let instance = path_buf
.file_name()
.ok_or(anyhow::anyhow!(
"Could not get basename from {}",
&seqrepo_path
))?
.to_str()
.expect("problem with path to string conversion")
.to_string();
let seqrepo: Arc<dyn seqrepo::Interface + Send + Sync> = Arc::new(
CacheWritingSeqRepo::new(SeqRepo::new(path, &instance)?, sr_cache_path)?,
);
Ok((seqrepo, seqrepo_path))
}
}