Files
obitools4/pkg/obitax/iterator.go

233 lines
4.5 KiB
Go
Raw Normal View History

2022-01-13 23:27:39 +01:00
package obitax
2025-01-24 18:09:59 +01:00
import (
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obiutils"
)
2024-11-16 05:59:41 +01:00
// ITaxon represents an iterator for traversing Taxon instances.
// It provides methods to retrieve the next Taxon and check if the iteration is finished.
2024-11-14 19:10:23 +01:00
type ITaxon struct {
2024-11-16 05:59:41 +01:00
source chan *Taxon // Channel to receive Taxon instances
current *Taxon // Current Taxon instance
finished bool // Indicates if the iteration is finished
p_finished *bool // Pointer to the finished status
2022-01-13 23:27:39 +01:00
}
2024-11-16 05:59:41 +01:00
// NewITaxon creates a new ITaxon iterator instance and initializes its fields.
2024-11-14 19:10:23 +01:00
func NewITaxon() *ITaxon {
i := ITaxon{
source: make(chan *Taxon),
current: nil,
finished: false,
2024-11-16 05:59:41 +01:00
p_finished: nil,
}
2022-01-13 23:27:39 +01:00
i.p_finished = &i.finished
return &i
}
2024-11-16 05:59:41 +01:00
// Iterator creates a new ITaxon iterator for the TaxonSet.
// It starts a goroutine to send Taxon instances from the set to the iterator's source channel.
2024-11-14 19:10:23 +01:00
func (set *TaxonSet) Iterator() *ITaxon {
i := NewITaxon()
2022-01-13 23:27:39 +01:00
go func() {
2024-11-08 09:48:16 +01:00
for _, t := range set.set {
2024-11-24 19:33:24 +01:00
taxon := &Taxon{
2024-11-14 19:10:23 +01:00
Taxonomy: set.taxonomy,
2024-11-24 19:33:24 +01:00
Metadata: nil,
2024-11-14 19:10:23 +01:00
Node: t,
}
2024-11-24 19:33:24 +01:00
i.Push(taxon)
2022-01-13 23:27:39 +01:00
}
close(i.source)
}()
return i
}
2024-11-16 05:59:41 +01:00
// Iterator creates a new ITaxon iterator for the TaxonSlice.
// It starts a goroutine to send Taxon instances from the slice to the iterator's source channel.
2024-11-14 19:10:23 +01:00
func (set *TaxonSlice) Iterator() *ITaxon {
i := NewITaxon()
2022-01-13 23:27:39 +01:00
go func() {
2024-11-08 09:48:16 +01:00
for _, t := range set.slice {
2024-11-24 19:33:24 +01:00
i.Push(&Taxon{
2024-11-14 19:10:23 +01:00
Taxonomy: set.taxonomy,
Node: t,
2024-11-24 19:33:24 +01:00
})
2022-01-13 23:27:39 +01:00
}
2024-11-24 19:33:24 +01:00
i.Close()
2022-01-13 23:27:39 +01:00
}()
return i
}
2024-11-24 19:33:24 +01:00
func (iterator *ITaxon) Push(taxon *Taxon) {
iterator.source <- taxon
}
func (iterator *ITaxon) Close() {
close(iterator.source)
}
2024-11-16 05:59:41 +01:00
// Iterator creates a new ITaxon iterator for the Taxonomy's nodes.
func (taxonomy *Taxonomy) Iterator() *ITaxon {
return taxonomy.nodes.Iterator()
2022-01-13 23:27:39 +01:00
}
2024-11-16 05:59:41 +01:00
// Next advances the iterator to the next Taxon instance.
// It returns true if there is a next Taxon, and false if the iteration is finished.
2024-11-14 19:10:23 +01:00
func (iterator *ITaxon) Next() bool {
2022-01-13 23:27:39 +01:00
if *(iterator.p_finished) {
return false
}
next, ok := (<-iterator.source)
if ok {
iterator.current = next
return true
}
iterator.current = nil
*iterator.p_finished = true
return false
}
2024-11-16 05:59:41 +01:00
// Get returns the current Taxon instance pointed to by the iterator.
// You must call 'Next' before calling 'Get' to retrieve the next instance.
2024-11-14 19:10:23 +01:00
func (iterator *ITaxon) Get() *Taxon {
2024-11-24 19:33:24 +01:00
if iterator == nil {
return nil
}
2022-01-13 23:27:39 +01:00
return iterator.current
}
2024-11-16 05:59:41 +01:00
// Finished returns true if no more data is available from the iterator.
2024-11-14 19:10:23 +01:00
func (iterator *ITaxon) Finished() bool {
2024-11-24 19:33:24 +01:00
if iterator == nil {
return true
}
2022-01-13 23:27:39 +01:00
return *iterator.p_finished
}
2024-11-16 05:59:41 +01:00
// Split creates a new ITaxon iterator that shares the same source channel
// and finished status as the original iterator.
2024-11-14 19:10:23 +01:00
func (iterator *ITaxon) Split() *ITaxon {
2024-11-24 19:33:24 +01:00
if iterator == nil {
return nil
}
2024-11-14 19:10:23 +01:00
return &ITaxon{
source: iterator.source,
current: nil,
finished: false,
p_finished: iterator.p_finished,
2022-01-13 23:27:39 +01:00
}
}
2024-11-24 19:33:24 +01:00
func (iterator *ITaxon) AddMetadata(name string, value interface{}) *ITaxon {
if iterator == nil {
return nil
}
i := NewITaxon()
go func() {
for iterator.Next() {
taxon := iterator.Get()
taxon.SetMetadata(name, value)
i.Push(taxon)
}
i.Close()
}()
return i
}
func (iterator *ITaxon) Concat(iterators ...*ITaxon) *ITaxon {
newIter := NewITaxon()
go func() {
if iterator != nil {
for iterator.Next() {
taxon := iterator.Get()
newIter.Push(taxon)
}
}
for _, iter := range iterators {
if iter != nil {
for iter.Next() {
taxon := iter.Get()
newIter.Push(taxon)
}
}
}
newIter.Close()
}()
return newIter
}
2025-01-24 18:09:59 +01:00
func (taxon *Taxon) ISubTaxonomy() *ITaxon {
taxo := taxon.Taxonomy
path := taxon.Path()
lpath := path.Len()
iter := NewITaxon()
parents := map[*TaxNode]bool{taxon.Node: true}
obiutils.RegisterAPipe()
go func() {
for i := lpath - 1; i >= 0; i-- {
taxon := path.Taxon(i)
iter.Push(taxon)
}
pushed := true
for pushed {
itaxo := taxo.Iterator()
pushed = false
for itaxo.Next() {
taxon := itaxo.Get()
if !parents[taxon.Node] && parents[taxon.Parent().Node] {
parents[taxon.Node] = true
iter.Push(taxon)
pushed = true
}
}
}
iter.Close()
obiutils.UnregisterPipe()
}()
return iter
}
func (taxonomy *Taxonomy) ISubTaxonomy(taxid string) *ITaxon {
taxon, _, err := taxonomy.Taxon(taxid)
if err != nil {
return nil
}
return taxon.ISubTaxonomy()
}
func (iterator *ITaxon) Consume() {
for iterator.Next() {
iterator.Get()
}
}