diff --git a/src/annotation.rs b/src/annotation.rs index 0f9e8a3..0da4880 100644 --- a/src/annotation.rs +++ b/src/annotation.rs @@ -419,7 +419,10 @@ impl AnnotationStore { } /// Builds and adds multiple annotations - pub fn with_annotations(mut self, builders: Vec) -> Result { + pub fn with_annotations<'a, I>(mut self, builders: I) -> Result + where + I: IntoIterator>, + { self.annotate_from_iter(builders)?; Ok(self) } @@ -469,11 +472,10 @@ impl AnnotationStore { /// //instantiate a store /// let mut store = AnnotationStore::new(Config::default()) /// .with_id("example") - /// .add( + /// .with_resource( /// TextResourceBuilder::new() /// .with_id("myresource") /// .with_text("Hello world") - /// .build()?, /// )? /// .add( /// AnnotationDataSet::new(Config::default()) diff --git a/src/annotationstore.rs b/src/annotationstore.rs index 0dd9d5f..236c975 100644 --- a/src/annotationstore.rs +++ b/src/annotationstore.rs @@ -38,7 +38,9 @@ use crate::datakey::DataKeyHandle; use crate::error::*; use crate::file::*; use crate::json::{FromJson, ToJson}; -use crate::resources::{DeserializeTextResource, TextResource, TextResourceHandle}; +use crate::resources::{ + DeserializeTextResource, TextResource, TextResourceBuilder, TextResourceHandle, +}; use crate::selector::{Offset, OffsetMode, Selector, SelectorBuilder}; use crate::store::*; use crate::substore::{AnnotationSubStore, AnnotationSubStoreHandle}; @@ -59,11 +61,10 @@ use crate::types::*; /// # fn main() -> Result<(),StamError> { /// let store = AnnotationStore::default() /// .with_id("example") -/// .add(TextResource::from_string( -/// "myresource", -/// "Hello world", -/// Config::default(), -/// ))? +/// .with_resource(TextResourceBuilder::new() +/// .with_id("myresource") +/// .with_text("Hello world") +/// )? /// .add(AnnotationDataSet::new(Config::default()).with_id("mydataset"))? /// .with_annotation( /// AnnotationBuilder::new() @@ -86,11 +87,10 @@ use crate::types::*; /// # fn main() -> Result<(),StamError> { /// let store = AnnotationStore::new(Config::default()) /// .with_id("example") -/// .add( +/// .with_resource( /// TextResourceBuilder::new() /// .with_id("myresource") /// .with_text("Hello world") -/// .build()?, /// )? /// .add( /// AnnotationDataSet::new(Config::default()) @@ -268,7 +268,7 @@ impl private::StoreCallbacks for AnnotationStore { /// parameters from parent to the item #[allow(unused_variables)] fn preinsert(&self, item: &mut TextResource) -> Result<(), StamError> { - item.set_config(self.new_config()); + item.initialize(self); Ok(()) } @@ -1004,7 +1004,7 @@ impl AnnotationStore { /// Returns a [`Config`] instance suitable for instantiation of dependent instances like TextResource,AnnotationDataSet and /// This will have the working directory set to the annotation store's directory - pub fn new_config(&self) -> Config { + pub(crate) fn new_config(&self) -> Config { debug(&self.config(), || format!("AnnotationStore::new_config")); let mut config = self.config().clone(); config.workdir = self.dirname(); @@ -1348,18 +1348,9 @@ impl AnnotationStore { self } - /// Shortcut method to load a resource from file and add it to the store. Returns a handle, - /// wrap it in a call to `self.resource()` to get the resource itself. - pub fn add_resource_from_file( - &mut self, - filename: &str, - ) -> Result { - let resource = TextResource::from_file(filename, self.new_config())?; - self.insert(resource) - } - /// Shortcut method to load a dataset from file and add it to the store. Returns a handle, /// wrap it in a call to `self.dataset()` to get the resource itself. + //TODO: REMOTE THIS, obsolete once we have add_dataset() pub fn add_dataset_from_file( &mut self, filename: &str, diff --git a/src/csv.rs b/src/csv.rs index 53a7527..0854283 100644 --- a/src/csv.rs +++ b/src/csv.rs @@ -1187,15 +1187,12 @@ impl FromCsv for AnnotationStore { record.filename ) }); - let mut resourcebuilder = TextResourceBuilder::from_txt_file( - &record.filename, - store.new_config(), - )?; + let mut resourcebuilder = TextResourceBuilder::new().with_filename(record.filename); if record.id.is_some() { resourcebuilder = resourcebuilder.with_id(record.id.map(|x| x.to_string()).unwrap()); } - store.insert(resourcebuilder.build()?)?; + store.add_resource(resourcebuilder)?; } Type::AnnotationStore => { return Err(StamError::CsvError( diff --git a/src/resources.rs b/src/resources.rs index b809f08..477e6a4 100644 --- a/src/resources.rs +++ b/src/resources.rs @@ -94,10 +94,10 @@ pub struct TextResource { /// ``` /// use stam::*; /// let mut store = AnnotationStore::default(); -/// store.insert( -/// TextResourceBuilder::new().with_id("testres").with_text( -/// "Hello world!", -/// ).with_config(store.new_config()).build().unwrap() +/// store.add_resource( +/// TextResourceBuilder::new() +/// .with_id("testres") +/// .with_text("Hello world!") /// ); /// ``` #[derive(Deserialize, Debug, Default)] @@ -111,75 +111,6 @@ pub struct TextResourceBuilder { /// if we have a filename but no text, the include is still to be parsed. #[serde(rename = "@include")] filename: Option, - - #[serde(skip)] - config: Config, -} - -impl TryFrom for TextResource { - type Error = StamError; - - fn try_from(builder: TextResourceBuilder) -> Result { - debug(&builder.config, || { - format!("TryFrom: Creation of TextResource from builder (done)") - }); - - //do we need to resolve an @include? - let mut includebuilder: Option = None; - if builder.text.is_none() { - if let Some(filename) = &builder.filename { - // we have a filename but no text, that means the include has to be resolved still - // we load the resource from the external file into a new builder and - // merge it with this one at the end of this function - includebuilder = Some(TextResourceBuilder::from_file( - filename.as_str(), - builder.config.clone(), - )?); - } - } - - let textlen = if let Some(text) = &builder.text { - text.chars().count() - } else if let Some(includebuilder) = includebuilder.as_ref() { - includebuilder - .text - .as_ref() - .map(|s| s.chars().count()) - .unwrap_or(0) - } else { - 0 - }; - let changed = builder.text.is_some() && builder.filename.is_some(); //we supplied text but also have a filename, that means the file will be new - Ok(Self { - intid: None, - id: if let Some(id) = builder.id { - id - } else if includebuilder.is_some() && includebuilder.as_ref().unwrap().id.is_some() { - includebuilder.as_ref().unwrap().id.clone().unwrap() - } else if let Some(filename) = builder.filename.as_ref() { - filename.clone() - } else { - return Err(StamError::NoIdError("Expected an ID for resource")); - }, - text: if let Some(text) = builder.text { - text - } else if let Some(includebuilder) = includebuilder { - //this consumes the includebuilder - includebuilder - .text - .ok_or_else(|| StamError::NoText("Included resource has no text"))? - } else { - String::new() - }, - textlen, - positionindex: PositionIndex::default(), - byte2charmap: BTreeMap::default(), - textselections: Store::default(), - config: builder.config, - filename: builder.filename, - changed: Arc::new(RwLock::new(changed)), - }) - } } /// [Handle] to an instance of [`TextResource`] in the store ([`AnnotationStore`]). @@ -371,101 +302,37 @@ impl PartialEq for TextResource { } } -impl FromJson for TextResourceBuilder { - /// Loads a Text Resource from a STAM JSON or plain text file file. - /// If the file is JSON, it file must contain a single object which has "@type": "TextResource" - /// If `include` is true, the file will be included via the `@include` mechanism, and is kept external upon serialization - fn from_json_file(filename: &str, config: Config) -> Result { - let reader = open_file_reader(filename, &config)?; - let deserializer = &mut serde_json::Deserializer::from_reader(reader); - let mut result: Result = - serde_path_to_error::deserialize(deserializer); - if result.is_ok() && config.use_include { - let result = result.as_mut().unwrap(); - result.filename = Some(filename.to_string()); //always uses the original filename (not the found one) - result.config = config; - } - result.map_err(|e| { - StamError::JsonError(e, filename.to_string(), "Reading text resource from file") - }) +impl AnnotationStore { + /// Builds and adds resource + pub fn with_resource(mut self, builder: TextResourceBuilder) -> Result { + self.add_resource(builder)?; + Ok(self) } - /// Loads a text resource from a STAM JSON string - /// The string must contain a single object which has "@type": "TextResource" - fn from_json_str(string: &str, config: Config) -> Result { - let deserializer = &mut serde_json::Deserializer::from_str(string); - let mut result: Result = - serde_path_to_error::deserialize(deserializer); - if result.is_ok() { - let result = result.as_mut().unwrap(); - result.config = config; - } - result.map_err(|e| { - StamError::JsonError(e, string.to_string(), "Reading text resource from string") - }) + pub fn add_resource( + &mut self, + builder: TextResourceBuilder, + ) -> Result { + debug(self.config(), || { + format!("AnnotationStore.add_resource: builder={:?}", builder) + }); + self.insert(builder.build(self.new_config())?) } } impl TextResourceBuilder { + /// Instantiate a new TextResourceBuilder. + /// You likely want to pass the result to [`AnnotationStore::add_resource()`]. pub fn new() -> Self { TextResourceBuilder::default() } - fn text_from_file(filename: &str, config: &Config) -> Result { - let mut f = open_file(filename, config)?; - let mut text: String = String::new(); - if let Err(err) = f.read_to_string(&mut text) { - return Err(StamError::IOError( - err, - filename.to_owned(), - "TextResourceBuilder::from_txt_file", - )); - } - Ok(text) - } - - /// Loads a resource from text file - pub fn from_txt_file(filename: &str, config: Config) -> Result { - //plain text - debug(&config, || { - format!( - "TextResourceBuilder::from_txt_file: filename={}, workdir={:?}", - filename, - config.workdir() - ) - }); - let text = Self::text_from_file(filename, &config)?; - Ok(Self { - id: Some(filename.to_string()), - text: Some(text), - filename: Some(filename.to_string()), - config, - }) - } - - /// Load a resource from file. The extension determines the type (`json` for STAM JSON or plain text otherwise). - /// You also need to pass a configuration, for which you should normally use [`AnnotationStore::new_config()`]. - pub fn from_file(filename: &str, config: Config) -> Result { - if filename.ends_with(".json") { - Self::from_json_file(filename, config) - } else { - Self::from_txt_file(filename, config) - } - } - /// Associate a public identifier with the resource pub fn with_id(mut self, id: impl Into) -> Self { self.id = Some(id.into()); self } - /// Set a configuration to use for this resource - /// You'll most likely want to pass the result of [`AnnotationStore::new_config()`] to this method. - pub fn with_config(mut self, config: Config) -> Self { - self.config = config; - self - } - /// Set the filename associated with the resource. This does **NOT** load /// the resource from file, but merely sets up the association and where to write to. /// Use [`Self::from_file()`] instead if you want to load from file. @@ -481,28 +348,102 @@ impl TextResourceBuilder { } ///Builds a new [`TextResource`] from [`TextResourceBuilder`], consuming the latter - pub fn build(self) -> Result { - debug(&self.config, || { + pub(crate) fn build(self, config: Config) -> Result { + debug(&config, || { format!( "TextResourceBuilder::build: id={:?}, filename={:?}, workdir={:?}, use_include={}", self.id, self.filename, - self.config.workdir(), - self.config.use_include() + config.workdir(), + config.use_include() ) }); - let mut res: TextResource = self.try_into()?; - res.textlen = res.text.chars().count(); - if res.config().milestone_interval > 0 { - res.create_milestones(res.config().milestone_interval) + + if let Some(text) = self.text { + let changed = self.filename.is_some(); //we supplied text but also have a filename, that means the file will be new + Ok(TextResource { + intid: None, + id: if let Some(id) = self.id { + id + } else if let Some(filename) = self.filename.as_ref() { + filename.clone() + } else { + return Err(StamError::NoIdError("Expected an ID for resource")); + }, + textlen: text.chars().count(), + text, + filename: self.filename, + config, + positionindex: PositionIndex::default(), + byte2charmap: BTreeMap::default(), + textselections: Store::default(), + changed: Arc::new(RwLock::new(changed)), + }) + } else if let Some(filename) = self.filename { + // we have a filename but no text, that means the include has to be resolved still + // we load the resource from the external file + if filename.ends_with(".json") { + // load STAM JSON file + let reader = open_file_reader(filename.as_str(), &config)?; + let deserializer = &mut serde_json::Deserializer::from_reader(reader); + //this generates a new builder + let result: Result = + serde_path_to_error::deserialize(deserializer); + match result { + Ok(mut builder) => { + //recursion step into the new builder: + if self.id.is_some() && builder.id.is_none() { + builder.id = self.id; + } + builder.filename = Some(filename); //always uses the original filename (not the found one) + builder.build(config) //<-- actual recursion step + } + Err(e) => Err(StamError::JsonError( + e, + filename.to_string(), + "Reading text resource from STAM JSON file", + )), + } + } else { + // load plain text file + let mut f = open_file(filename.as_str(), &config)?; + let mut text: String = String::new(); + if let Err(err) = f.read_to_string(&mut text) { + return Err(StamError::IOError( + err, + filename, + "TextResourceBuilder::build(): from text file: ", + )); + } + Ok(TextResource { + intid: None, + id: if let Some(id) = self.id { + id + } else { + filename.clone() + }, + textlen: text.chars().count(), + text, + filename: Some(filename), + config, + positionindex: PositionIndex::default(), + byte2charmap: BTreeMap::default(), + textselections: Store::default(), + changed: Arc::new(RwLock::new(false)), + }) + } + } else { + Err(StamError::OtherError( + "TextResourceBuilder No filename or text received", + )) } - Ok(res) } } impl TextResource { /// Instantiates a new completely empty TextResource /// Use [`AnnotationStore::new_config()`] to obtain a configuration to pass to this method. + /// This is a low-level method. Use [`AnnotationStore::add_resource()`] with a [`TextResourceBuilder`] instead. pub fn new(id: impl Into, config: Config) -> Self { Self { id: id.into(), @@ -519,6 +460,7 @@ impl TextResource { } /// Create a new TextResource from file, the text will be loaded into memory entirely + /// This is a low-level method. Use [`AnnotationStore::add_resource()`] with a [`TextResourceBuilder`] instead. pub fn from_file(filename: &str, config: Config) -> Result { debug(&config, || { format!( @@ -526,7 +468,9 @@ impl TextResource { filename, config ) }); - TextResourceBuilder::from_file(filename, config)?.build() + TextResourceBuilder::new() + .with_filename(filename) + .build(config) } /// Sets the text of the TextResource from string, kept in memory entirely @@ -577,6 +521,7 @@ impl TextResource { } /// Create a new TextResource from string, kept in memory entirely + /// This is a low-level method. Use [`AnnotationStore::add_resource()`] with a [`TextResourceBuilder`] instead. pub fn from_string(id: impl Into, text: impl Into, config: Config) -> Self { let text = text.into(); let textlen = text.chars().count(); @@ -598,6 +543,15 @@ impl TextResource { resource } + /// This function will be called after insertion (and after a configuration is associated with the TextResource) + pub(crate) fn initialize(&mut self, store: &AnnotationStore) { + self.config.workdir = store.dirname(); + self.textlen = self.text.chars().count(); + if self.config().milestone_interval > 0 { + self.create_milestones(self.config().milestone_interval) + } + } + /// Creates milestones (reverse index to facilitate character positions to utf8 byte position lookup and vice versa) /// Does initial population of the positionindex. fn create_milestones(&mut self, interval: usize) { @@ -1163,8 +1117,7 @@ impl<'de> DeserializeSeed<'de> for DeserializeTextResource { let builder: TextResourceBuilder = Deserialize::deserialize(deserializer)?; //inject the config builder - .with_config(self.config) - .build() + .build(self.config) .map_err(|e| -> D::Error { serde::de::Error::custom(e) }) } } diff --git a/src/tests.rs b/src/tests.rs index c0aa6e3..73fbbf8 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -813,11 +813,10 @@ fn utf82unicode() { #[test] fn find_text_single() -> Result<(), StamError> { let mut store = AnnotationStore::default(); - store.insert( + store.add_resource( TextResourceBuilder::new() .with_id("testres") - .with_text("Hallå världen") - .build()?, + .with_text("Hallå världen"), )?; let resource = store.resource("testres").unwrap(); let textselection = resource.find_text("världen").next().unwrap(); @@ -829,11 +828,10 @@ fn find_text_single() -> Result<(), StamError> { #[test] fn find_text_single2() -> Result<(), StamError> { let mut store = AnnotationStore::default(); - store.insert( + store.add_resource( TextResourceBuilder::new() .with_id("testres") - .with_text("Hallå världen") - .build()?, + .with_text("Hallå världen"), )?; let resource = store.resource("testres").unwrap(); let textselection = resource.find_text("Hallå").next().unwrap(); @@ -845,11 +843,10 @@ fn find_text_single2() -> Result<(), StamError> { #[test] fn find_text_multi() -> Result<(), StamError> { let mut store = AnnotationStore::default(); - store.insert( + store.add_resource( TextResourceBuilder::new() .with_id("testres") - .with_text("To be or not to be, that's the question") - .build()?, + .with_text("To be or not to be, that's the question"), )?; let resource = store.resource("testres").unwrap(); let textselections: Vec<_> = resource.find_text("be").collect(); @@ -864,11 +861,10 @@ fn find_text_multi() -> Result<(), StamError> { #[test] fn find_text_none() -> Result<(), StamError> { let mut store = AnnotationStore::default(); - store.insert( + store.add_resource( TextResourceBuilder::new() .with_id("testres") - .with_text("Hallå världen") - .build()?, + .with_text("Hallå världen"), )?; let resource = store.resource("testres").unwrap(); let v: Vec<_> = resource.find_text("blah").collect(); @@ -879,11 +875,10 @@ fn find_text_none() -> Result<(), StamError> { #[test] fn split_text() -> Result<(), StamError> { let mut store = AnnotationStore::default(); - store.insert( + store.add_resource( TextResourceBuilder::new() .with_id("testres") - .with_text("To be or not to be") - .build()?, + .with_text("To be or not to be"), )?; let resource = store.resource("testres").unwrap(); let textselections: Vec<_> = resource.split_text(" ").collect(); @@ -900,11 +895,10 @@ fn split_text() -> Result<(), StamError> { fn split_text_whitespace() -> Result<(), StamError> { //with leading and trailing 'empty' texts let mut store = AnnotationStore::default(); - store.insert( + store.add_resource( TextResourceBuilder::new() .with_id("testres") - .with_text("\nTo be or not to be\nthat is the question\n") - .build()?, + .with_text("\nTo be or not to be\nthat is the question\n"), )?; let resource = store.resource("testres").unwrap(); let textselections: Vec<_> = resource.split_text("\n").collect(); @@ -917,11 +911,10 @@ fn split_text_whitespace() -> Result<(), StamError> { fn split_text_none() -> Result<(), StamError> { //with no occurrences at all let mut store = AnnotationStore::default(); - store.insert( + store.add_resource( TextResourceBuilder::new() .with_id("testres") - .with_text("To be or not to be") - .build()?, + .with_text("To be or not to be"), )?; let resource = store.resource("testres").unwrap(); let textselections: Vec<_> = resource.split_text("?").collect(); @@ -933,11 +926,10 @@ fn split_text_none() -> Result<(), StamError> { #[test] fn trim_text() -> Result<(), StamError> { let mut store = AnnotationStore::default(); - store.insert( + store.add_resource( TextResourceBuilder::new() .with_id("testres") - .with_text(" To be or not to be ") - .build()?, + .with_text(" To be or not to be "), )?; let resource = store.resource("testres").unwrap(); let textselection = resource.trim_text(&[' ']).unwrap(); @@ -950,11 +942,10 @@ fn trim_text() -> Result<(), StamError> { #[test] fn textselection_out_of_bounds() -> Result<(), StamError> { let mut store = AnnotationStore::default(); - let handle = store.insert( + let handle = store.add_resource( TextResourceBuilder::new() .with_id("testres") - .with_text("Hello world") - .build()?, + .with_text("Hello world"), )?; let resource = store.resource(handle).unwrap(); let result = resource.textselection(&Offset::simple(0, 999)); diff --git a/tests/api.rs b/tests/api.rs index da07eaf..c91c26c 100644 --- a/tests/api.rs +++ b/tests/api.rs @@ -859,12 +859,10 @@ fn test_write_include_annotationstore() -> Result<(), StamError> { #[test] fn find_text() -> Result<(), StamError> { let mut store = AnnotationStore::default(); - store.insert( + store.add_resource( TextResourceBuilder::new() .with_id("testres") - .with_text("Hello world") - .with_config(store.new_config()) - .build()?, + .with_text("Hello world"), )?; let resource = store.resource("testres").unwrap(); let mut count = 0; @@ -881,12 +879,10 @@ fn find_text() -> Result<(), StamError> { #[test] fn find_text_nocase() -> Result<(), StamError> { let mut store = AnnotationStore::default(); - store.insert( + store.add_resource( TextResourceBuilder::new() .with_id("testres") - .with_text("Hello world") - .with_config(store.new_config()) - .build()?, + .with_text("Hello world"), )?; let resource = store.resource("testres").or_fail()?; let mut count = 0; @@ -903,12 +899,10 @@ fn find_text_nocase() -> Result<(), StamError> { #[test] fn find_text_sequence() -> Result<(), StamError> { let mut store = AnnotationStore::default(); - store.insert( + store.add_resource( TextResourceBuilder::new() .with_id("testres") - .with_text("Hello world") - .with_config(store.new_config()) - .build()?, + .with_text("Hello world"), )?; let resource = store.resource("testres").or_fail()?; let results = resource @@ -927,12 +921,10 @@ fn find_text_sequence() -> Result<(), StamError> { #[test] fn find_text_sequence2() -> Result<(), StamError> { let mut store = AnnotationStore::default(); - store.insert( + store.add_resource( TextResourceBuilder::new() .with_id("testres") - .with_text("Hello, world") - .with_config(store.new_config()) - .build()?, + .with_text("Hello, world"), )?; let resource = store.resource("testres").or_fail()?; let results = resource @@ -951,12 +943,10 @@ fn find_text_sequence2() -> Result<(), StamError> { #[test] fn find_text_sequence_nocase() -> Result<(), StamError> { let mut store = AnnotationStore::default(); - store.insert( + store.add_resource( TextResourceBuilder::new() .with_id("testres") - .with_text("Hello world") - .with_config(store.new_config()) - .build()?, + .with_text("Hello world"), )?; let resource = store.resource("testres").or_fail()?; let results = resource @@ -975,12 +965,10 @@ fn find_text_sequence_nocase() -> Result<(), StamError> { #[test] fn test_find_text_sequence_nomatch() -> Result<(), StamError> { let mut store = AnnotationStore::default(); - store.insert( + store.add_resource( TextResourceBuilder::new() .with_id("testres") - .with_text("Hello world") - .with_config(store.new_config()) - .build()?, + .with_text("Hello world"), )?; let resource = store.resource("testres").or_fail()?; let results = @@ -992,12 +980,10 @@ fn test_find_text_sequence_nomatch() -> Result<(), StamError> { #[test] fn test_split_text() -> Result<(), StamError> { let mut store = AnnotationStore::default(); - store.insert( + store.add_resource( TextResourceBuilder::new() .with_id("testres") - .with_text("Hello world") - .with_config(store.new_config()) - .build()?, + .with_text("Hello world"), )?; let resource = store.resource("testres").or_fail()?; let mut count = 0; @@ -1020,11 +1006,9 @@ fn test_split_text() -> Result<(), StamError> { #[test] fn test_search_text_regex_single() -> Result<(), StamError> { let mut store = AnnotationStore::default(); - store.insert( - TextResourceBuilder::new().with_id("testres").with_text( + store.add_resource(TextResourceBuilder::new().with_id("testres").with_text( "I categorically deny any eavesdropping on you and hearing about your triskaidekaphobia.", - ).with_config(store.new_config()).build()? - )?; + ))?; let resource = store.resource("testres").or_fail()?; let mut count = 0; for result in resource.find_text_regex(&[Regex::new(r"eavesdropping").unwrap()], None, true)? { @@ -1041,11 +1025,9 @@ fn test_search_text_regex_single() -> Result<(), StamError> { #[test] fn test_search_text_regex_single2() -> Result<(), StamError> { let mut store = AnnotationStore::default(); - store.insert( - TextResourceBuilder::new().with_id("testres").with_text( + store.add_resource(TextResourceBuilder::new().with_id("testres").with_text( "I categorically deny any eavesdropping on you and hearing about your triskaidekaphobia.", - ).with_config(store.new_config()).build()? - )?; + ))?; let resource = store.resource("testres").or_fail()?; let mut count = 0; for result in resource.find_text_regex(&[Regex::new(r"\b\w{13}\b").unwrap()], None, true)? { @@ -1069,11 +1051,9 @@ fn test_search_text_regex_single2() -> Result<(), StamError> { #[test] fn test_search_text_regex_single_multiexpr() -> Result<(), StamError> { let mut store = AnnotationStore::default(); - store.insert( - TextResourceBuilder::new().with_id("testres").with_text( + store.add_resource(TextResourceBuilder::new().with_id("testres").with_text( "I categorically deny any eavesdropping on you and hearing about your triskaidekaphobia.", - ).with_config(store.new_config()).build()? - )?; + ))?; let resource = store.resource("testres").or_fail()?; let mut count = 0; for result in resource.find_text_regex( @@ -1104,11 +1084,9 @@ fn test_search_text_regex_single_multiexpr() -> Result<(), StamError> { #[test] fn test_search_text_regex_single_multiexpr2() -> Result<(), StamError> { let mut store = AnnotationStore::default(); - store.insert( - TextResourceBuilder::new().with_id("testres").with_text( + store.add_resource(TextResourceBuilder::new().with_id("testres").with_text( "I categorically deny any eavesdropping on you and hearing about your triskaidekaphobia.", - ).with_config(store.new_config()).build()? - )?; + ))?; let resource = store.resource("testres").or_fail()?; let mut count = 0; for result in resource.find_text_regex( @@ -1139,11 +1117,9 @@ fn test_search_text_regex_single_multiexpr2() -> Result<(), StamError> { #[test] fn test_search_text_regex_single_capture() -> Result<(), StamError> { let mut store = AnnotationStore::default(); - store.insert( - TextResourceBuilder::new().with_id("testres").with_text( + store.add_resource(TextResourceBuilder::new().with_id("testres").with_text( "I categorically deny any eavesdropping on you and hearing about your triskaidekaphobia.", - ).with_config(store.new_config()).build()? - )?; + )); let resource = store.resource("testres").or_fail()?; let mut count = 0; for result in resource.find_text_regex( @@ -1164,11 +1140,9 @@ fn test_search_text_regex_single_capture() -> Result<(), StamError> { #[test] fn test_search_text_regex_double_capture() -> Result<(), StamError> { let mut store = AnnotationStore::default(); - store.insert( - TextResourceBuilder::new().with_id("testres").with_text( + store.add_resource(TextResourceBuilder::new().with_id("testres").with_text( "I categorically deny any eavesdropping on you and hearing about your triskaidekaphobia.", - ).with_config(store.new_config()).build()? - )?; + ))?; let resource = store.resource("testres").or_fail()?; let mut count = 0; for result in resource.find_text_regex( diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 5ffd41f..17d62ae 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -5,11 +5,10 @@ pub fn setup_example_1() -> Result { //instantiate with builder pattern let store = AnnotationStore::new(Config::default().with_debug(true)) .with_id("test") - .add( + .with_resource( TextResourceBuilder::new() .with_id("testres") - .with_text("Hello world") - .build()?, + .with_text("Hello world"), )? .add( AnnotationDataSet::new(Config::default()) @@ -33,11 +32,11 @@ pub fn setup_example_2() -> Result { //instantiate with builder pattern let store = AnnotationStore::default() .with_id("test") - .add(TextResource::from_string( - "testres", - "Hello world", - Config::default(), - ))? + .with_resource( + TextResourceBuilder::new() + .with_id("testres") + .with_text("Hello world"), + )? .add(AnnotationDataSet::new(Config::default()).with_id("testdataset"))? .with_annotation( AnnotationBuilder::new() @@ -55,10 +54,8 @@ pub fn setup_example_3() -> Result { //this example includes a higher-order annotation with relative offset let store = AnnotationStore::default() .with_id("test") - .add(TextResource::from_string( - "testres", + .with_resource(TextResourceBuilder::new().with_id("testres").with_text( "I have no special talent. I am only passionately curious. -- Albert Einstein", - Config::default(), ))? .add(AnnotationDataSet::new(Config::default()).with_id("testdataset"))? .with_annotation( @@ -86,11 +83,11 @@ pub fn setup_example_4() -> Result { //instantiate with builder pattern let store = AnnotationStore::default() .with_id("test") - .add(TextResource::from_string( - "testres", - "Hello world", - Config::default(), - ))? + .with_resource( + TextResourceBuilder::new() + .with_id("testres") + .with_text("Hello world"), + )? .add(AnnotationDataSet::new(Config::default()).with_id("testdataset"))? .with_annotation( AnnotationBuilder::new() @@ -115,11 +112,11 @@ pub fn setup_example_4() -> Result { pub fn setup_example_multiselector_notranged() -> Result { let store = AnnotationStore::default() .with_id("test") - .add(TextResource::from_string( - "testres", - "Hello world", - Config::default(), - ))? + .with_resource( + TextResourceBuilder::new() + .with_id("testres") + .with_text("Hello world"), + )? .add(AnnotationDataSet::new(Config::default()).with_id("testdataset"))? .with_annotation(AnnotationBuilder::new().with_id("A1").with_target( SelectorBuilder::textselector("testres", Offset::simple(6, 11)), @@ -143,11 +140,11 @@ pub fn setup_example_multiselector_notranged() -> Result Result { let store = AnnotationStore::default() .with_id("test") - .add(TextResource::from_string( - "testres", - "Hello world", - Config::default(), - ))? + .with_resource( + TextResourceBuilder::new() + .with_id("testres") + .with_text("Hello world"), + )? .add(AnnotationDataSet::new(Config::default()).with_id("testdataset"))? .with_annotation( AnnotationBuilder::new() @@ -165,11 +162,11 @@ pub fn setup_example_multiselector_ranged() -> Result Result { let store = AnnotationStore::default() .with_id("test") - .add(TextResource::from_string( - "testres", - "Hello world", - Config::default(), - ))? + .with_resource( + TextResourceBuilder::new() + .with_id("testres") + .with_text("Hello world"), + )? .add(AnnotationDataSet::new(Config::default()).with_id("testdataset"))? .with_annotation( AnnotationBuilder::new()