@@ -49,8 +49,10 @@ pub struct AnnotationSubStore {
49
49
pub ( crate ) filename : Option < PathBuf > ,
50
50
51
51
#[ n( 3 ) ]
52
- /// Refers to an index in substores which is the parent of the curent substore. This allows for deeper nesting, it is set to None if this is a first level substore
53
- pub ( crate ) parent : Option < AnnotationSubStoreHandle > ,
52
+ /// Refers to indices in substores, indicating which are the parents of the curent substore.
53
+ /// A value of `None` means the root store is the parent.
54
+ /// This allows for deeper nesting, it is set to None if this is a first level substore
55
+ pub ( crate ) parents : Vec < Option < AnnotationSubStoreHandle > > ,
54
56
55
57
#[ n( 4 ) ]
56
58
pub ( crate ) annotations : Vec < AnnotationHandle > ,
@@ -91,13 +93,26 @@ impl AnnotationSubStore {
91
93
self . annotationsets . len ( )
92
94
}
93
95
94
- pub fn parent ( & self ) -> Option < AnnotationSubStoreHandle > {
95
- self . parent
96
+ pub fn parents ( & self ) -> & Vec < Option < AnnotationSubStoreHandle > > {
97
+ & self . parents
96
98
}
97
99
98
- /// Sets the parent of this substore
100
+ /// Sets the parent of this substore, may be called multiple times to add multiple parents!
101
+ /// The value is wrapped in an option, None means the root store is the parent
99
102
fn with_parent ( mut self , index : Option < AnnotationSubStoreHandle > ) -> Self {
100
- self . parent = index;
103
+ self . add_parent ( index) ;
104
+ self
105
+ }
106
+
107
+ /// Sets the parent of this substore, may be called multiple times to add multiple parents!
108
+ /// The value is wrapped in an option, None means the root store is the parent
109
+ fn add_parent ( & mut self , index : Option < AnnotationSubStoreHandle > ) {
110
+ self . parents . push ( index) ;
111
+ }
112
+
113
+ /// Sets the parents of this substore
114
+ fn with_parents ( mut self , parents : Vec < Option < AnnotationSubStoreHandle > > ) -> Self {
115
+ self . parents = parents;
101
116
self
102
117
}
103
118
@@ -180,22 +195,29 @@ impl AnnotationStore {
180
195
// check if the substore is already loaded (it may be referenced from multiple places)
181
196
// in that case we don't need to process it again
182
197
let foundpath = Some ( get_filepath ( filename, self . config . workdir ( ) ) ?) ;
198
+ let mut foundsubstore = None ;
183
199
for substore in <Self as StoreFor < AnnotationSubStore > >:: iter ( self ) {
184
200
if substore. filename == foundpath || substore. filename == Some ( filename. into ( ) ) {
185
- return Ok ( substore. handle ( ) . expect ( "substore must have handle" ) ) ;
201
+ foundsubstore = Some ( substore. handle ( ) . expect ( "substore must have handle" ) ) ;
202
+ break ;
186
203
}
187
204
}
205
+ if let Some ( foundsubstore) = foundsubstore {
206
+ let parent_handle = self . config . current_substore_path . last ( ) . copied ( ) ;
207
+ let substore: & mut AnnotationSubStore = self . get_mut ( foundsubstore) ?;
208
+ substore. add_parent ( parent_handle) ;
209
+ return Ok ( foundsubstore) ;
210
+ }
188
211
}
189
- let new_index = self . substores . len ( ) ;
190
- let parent_index = if new_index == 0 {
191
- None
192
- } else {
193
- Some ( new_index - 1 )
194
- } ;
195
- let handle = self . insert (
196
- AnnotationSubStore :: default ( )
197
- . with_parent ( parent_index. map ( |x| AnnotationSubStoreHandle :: new ( x) ) ) ,
198
- ) ?; //this data will be modified whilst parsing
212
+
213
+ let parent_handle = self . config . current_substore_path . last ( ) . copied ( ) ;
214
+ let handle = self . insert ( AnnotationSubStore :: default ( ) . with_parent ( parent_handle) ) ?; //this data will be modified whilst parsing
215
+ debug ( self . config ( ) , || {
216
+ format ! (
217
+ "AnnotationStore.add_substore: adding substore filename={:?}, parent={:?}" ,
218
+ filename, parent_handle
219
+ )
220
+ } ) ;
199
221
self . push_current_substore ( handle) ;
200
222
self . merge_json_file ( filename) ?;
201
223
self . pop_current_substore ( ) ;
@@ -214,33 +236,45 @@ impl AnnotationStore {
214
236
// check if the substore is already loaded (it may be referenced from multiple places)
215
237
// in that case we don't need to process it again
216
238
let foundpath = Some ( get_filepath ( filename, self . config . workdir ( ) ) ?) ;
239
+ let mut foundsubstore = None ;
217
240
for substore in <Self as StoreFor < AnnotationSubStore > >:: iter ( self ) {
218
241
if substore. filename == foundpath || substore. filename == Some ( filename. into ( ) ) {
219
- return Ok ( substore. handle ( ) . expect ( "substore must have handle" ) ) ;
242
+ foundsubstore = Some ( substore. handle ( ) . expect ( "substore must have handle" ) ) ;
243
+ break ;
220
244
}
221
245
}
246
+ if let Some ( foundsubstore) = foundsubstore {
247
+ let parent_handle = self . config . current_substore_path . last ( ) . copied ( ) ;
248
+ let substore: & mut AnnotationSubStore = self . get_mut ( foundsubstore) ?;
249
+ substore. add_parent ( parent_handle) ;
250
+ return Ok ( foundsubstore) ;
251
+ }
222
252
}
223
- let new_index = self . substores . len ( ) ;
224
- let parent_index = if new_index == 0 {
225
- None
226
- } else {
227
- Some ( new_index - 1 )
228
- } ;
253
+
254
+ let parent_handle = self . config . current_substore_path . last ( ) . copied ( ) ;
229
255
let handle = self . insert (
230
256
AnnotationSubStore :: default ( )
231
- . with_filename ( filename)
232
257
. with_id ( id)
233
- . with_parent ( parent_index. map ( |x| AnnotationSubStoreHandle :: new ( x) ) ) ,
258
+ . with_filename ( filename)
259
+ . with_parent ( parent_handle) ,
234
260
) ?; //this data will be modified whilst parsing
261
+ debug ( self . config ( ) , || {
262
+ format ! (
263
+ "AnnotationStore.add_substore: adding substore filename={:?}, parent={:?}" ,
264
+ filename, parent_handle
265
+ )
266
+ } ) ;
235
267
Ok ( handle)
236
268
}
237
269
238
270
/// used to add a substore to the path, indicating which substore is currently being parsed
271
+ /// influences the behaviour of add_substore()
239
272
fn push_current_substore ( & mut self , index : AnnotationSubStoreHandle ) {
240
273
self . config . current_substore_path . push ( index) ;
241
274
}
242
275
243
276
/// used to add a substore to the path, indicating which substore is currently being parsed
277
+ /// influences the behaviour of add_substore()
244
278
fn pop_current_substore ( & mut self ) -> bool {
245
279
self . config . current_substore_path . pop ( ) . is_some ( )
246
280
}
@@ -380,12 +414,12 @@ impl<'store> Serialize for ResultItem<'store, AnnotationSubStore> {
380
414
state. serialize_field ( "@id" , id) ?;
381
415
}
382
416
let substores: Vec < _ > = self . substores ( ) . collect ( ) ;
383
- let substore_handle = Some ( self . handle ( ) ) ;
417
+ let substore_handle = self . handle ( ) ;
384
418
if !substores. is_empty ( ) {
385
419
if substores. len ( ) == 1 {
386
420
if let Some ( substore) =
387
421
<AnnotationStore as StoreFor < AnnotationSubStore > >:: iter ( self . store ( ) )
388
- . filter ( |substore| substore. parent == substore_handle)
422
+ . filter ( |substore| substore. parents . contains ( & Some ( substore_handle) ) )
389
423
. next ( )
390
424
{
391
425
state. serialize_field (
@@ -398,20 +432,20 @@ impl<'store> Serialize for ResultItem<'store, AnnotationSubStore> {
398
432
} else {
399
433
let substores_filenames: Vec < _ > =
400
434
<AnnotationStore as StoreFor < AnnotationSubStore > >:: iter ( self . store ( ) )
401
- . filter ( |substore| substore. parent == substore_handle)
435
+ . filter ( |substore| substore. parents . contains ( & Some ( substore_handle) ) )
402
436
. filter_map ( |substore| substore. filename ( ) )
403
437
. collect ( ) ;
404
438
state. serialize_field ( "@include" , & substores_filenames) ?;
405
439
}
406
440
}
407
441
let wrappedstore: WrappedStore < TextResource , AnnotationStore > =
408
- self . store ( ) . wrap_store ( substore_handle) ;
442
+ self . store ( ) . wrap_store ( Some ( substore_handle) ) ;
409
443
state. serialize_field ( "resources" , & wrappedstore) ?;
410
444
let wrappedstore: WrappedStore < AnnotationDataSet , AnnotationStore > =
411
- self . store ( ) . wrap_store ( substore_handle) ;
445
+ self . store ( ) . wrap_store ( Some ( substore_handle) ) ;
412
446
state. serialize_field ( "annotationsets" , & wrappedstore) ?;
413
447
let wrappedstore: WrappedStore < Annotation , AnnotationStore > =
414
- self . store ( ) . wrap_store ( substore_handle) ;
448
+ self . store ( ) . wrap_store ( Some ( substore_handle) ) ;
415
449
state. serialize_field ( "annotations" , & wrappedstore) ?;
416
450
state. end ( )
417
451
}
0 commit comments