/* $Id: seq_entry_info.cpp 603374 2020-03-10 19:52:03Z vasilche $ * =========================================================================== * * PUBLIC DOMAIN NOTICE * National Center for Biotechnology Information * * This software/database is a "United States Government Work" under the * terms of the United States Copyright Act. It was written as part of * the author's official duties as a United States Government employee and * thus cannot be copyrighted. This software/database is freely available * to the public for use. The National Library of Medicine and the U.S. * Government have not placed any restriction on its use or reproduction. * * Although all reasonable efforts have been taken to ensure the accuracy * and reliability of the software and data, the NLM and the U.S. * Government do not and cannot warrant the performance or results that * may be obtained by using this software or data. The NLM and the U.S. * Government disclaim all warranties, express or implied, including * warranties of performance, merchantability or fitness for any particular * purpose. * * Please cite the author in any work or product based on this material. * * =========================================================================== * * Author: Eugene Vasilchenko * * File Description: * CSeq_entry_Info info -- entry for data source information about Seq-entry * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include BEGIN_NCBI_SCOPE BEGIN_SCOPE(objects) static const int kBioseqChunkId = kMax_Int; CSeq_entry_Info::CSeq_entry_Info(void) : m_Which(CSeq_entry::e_not_set) { } CSeq_entry_Info::CSeq_entry_Info(CSeq_entry& entry) : m_Which(CSeq_entry::e_not_set) { x_SetObject(entry); } CSeq_entry_Info::CSeq_entry_Info(const CSeq_entry_Info& info, TObjectCopyMap* copy_map) : TParent(info, copy_map), m_Which(CSeq_entry::e_not_set) { if ( !copy_map ) { info.x_UpdateComplete(); } x_SetObject(info, copy_map); } CSeq_entry_Info::~CSeq_entry_Info(void) { } const CBioseq_set_Info& CSeq_entry_Info::GetParentBioseq_set_Info(void) const { return static_cast(GetBaseParent_Info()); } CBioseq_set_Info& CSeq_entry_Info::GetParentBioseq_set_Info(void) { return static_cast(GetBaseParent_Info()); } const CSeq_entry_Info& CSeq_entry_Info::GetParentSeq_entry_Info(void) const { return GetParentBioseq_set_Info().GetParentSeq_entry_Info(); } CSeq_entry_Info& CSeq_entry_Info::GetParentSeq_entry_Info(void) { return GetParentBioseq_set_Info().GetParentSeq_entry_Info(); } void CSeq_entry_Info::x_CheckWhich(E_Choice which) const { if ( Which() != which ) { switch ( which ) { case CSeq_entry::e_Seq: NCBI_THROW(CUnassignedMember,eGet,"Seq_entry.seq"); case CSeq_entry::e_Set: NCBI_THROW(CUnassignedMember,eGet,"Seq_entry.set"); default: NCBI_THROW(CUnassignedMember,eGet,"Seq_entry.not_set"); } } } const CSeq_entry_Info& CSeq_entry_Info::GetXrefTSE() const { if ( !HasParent_Info() ) { return *this; } const CBioseq_set_Info* bss = 0; if ( IsSet() ) { bss = &GetSet(); } else if ( HasParent_Info() ) { bss = &GetParentBioseq_set_Info(); } else { return *this; } if ( bss->GetClass() == CBioseq_set::eClass_parts ) { const CSeq_entry_Info& parent = bss->GetParentSeq_entry_Info(); if ( parent.HasParent_Info() ) { bss = &parent.GetParentBioseq_set_Info(); } else { return parent; } } if ( bss->GetClass() == CBioseq_set::eClass_segset ) { const CSeq_entry_Info& parent = bss->GetParentSeq_entry_Info(); if ( parent.HasParent_Info() ) { bss = &parent.GetParentBioseq_set_Info(); } else { return parent; } } return bss->GetParentSeq_entry_Info(); } const CBioseq_Info& CSeq_entry_Info::GetSeq(void) const { x_CheckWhich(CSeq_entry::e_Seq); x_Update(fNeedUpdate_bioseq); const CBioseq_Base_Info& base = *m_Contents; return dynamic_cast(base); } CBioseq_Info& CSeq_entry_Info::SetSeq(void) { x_CheckWhich(CSeq_entry::e_Seq); x_Update(fNeedUpdate_bioseq); CBioseq_Base_Info& base = *m_Contents; return dynamic_cast(base); } const CBioseq_set_Info& CSeq_entry_Info::GetSet(void) const { x_CheckWhich(CSeq_entry::e_Set); const CBioseq_Base_Info& base = *m_Contents; return dynamic_cast(base); } CBioseq_set_Info& CSeq_entry_Info::SetSet(void) { x_CheckWhich(CSeq_entry::e_Set); CBioseq_Base_Info& base = *m_Contents; return dynamic_cast(base); } void CSeq_entry_Info::x_Select(CSeq_entry::E_Choice which, CRef contents) { if ( Which() != which || m_Contents != contents ) { if ( m_Contents ) { x_DetachContents(); m_Contents.Reset(); } m_Which = which; m_Contents = contents; switch ( m_Which ) { case CSeq_entry::e_Seq: m_Object->SetSeq(SetSeq().x_GetObject()); break; case CSeq_entry::e_Set: m_Object->SetSet(SetSet().x_GetObject()); break; default: m_Object->Reset(); break; } x_AttachContents(); } } inline void CSeq_entry_Info::x_Select(CSeq_entry::E_Choice which, CBioseq_Base_Info* contents) { x_Select(which, Ref(contents)); } void CSeq_entry_Info::Reset(void) { x_Select(CSeq_entry::e_not_set, 0); SetBioObjectId(GetTSE_Info().x_RegisterBioObject(*this)); } CBioseq_set_Info& CSeq_entry_Info::SelectSet(CBioseq_set_Info& seqset) { if ( Which() != CSeq_entry::e_not_set ) { NCBI_THROW(CObjMgrException, eModifyDataError, "Reset CSeq_entry_Handle before selecting set"); } x_Select(CSeq_entry::e_Set, &seqset); return SetSet(); } CBioseq_set_Info& CSeq_entry_Info::SelectSet(CBioseq_set& seqset) { return SelectSet(*new CBioseq_set_Info(seqset)); } CBioseq_set_Info& CSeq_entry_Info::SelectSet(void) { if ( !IsSet() ) { SelectSet(*new CBioseq_set); } return SetSet(); } CBioseq_Info& CSeq_entry_Info::SelectSeq(CBioseq_Info& seq) { if ( Which() != CSeq_entry::e_not_set ) { NCBI_THROW(CObjMgrException, eModifyDataError, "Reset CSeq_entry_Handle before selecting seq"); } x_Select(CSeq_entry::e_Seq, &seq); return SetSeq(); } CBioseq_Info& CSeq_entry_Info::SelectSeq(CBioseq& seq) { return SelectSeq(*new CBioseq_Info(seq)); } void CSeq_entry_Info::x_DoUpdate(TNeedUpdateFlags flags) { if ( flags & fNeedUpdate_bioseq ) { x_LoadChunk(kBioseqChunkId); } if ( (flags & fNeedUpdate_children) && m_Contents ) { m_Contents->x_Update((flags & fNeedUpdate_children) | (flags >> kNeedUpdate_bits)); _ASSERT(Which()==m_Object->Which()); } TParent::x_DoUpdate(flags); } void CSeq_entry_Info::x_SetNeedUpdateContents(TNeedUpdateFlags flags) { x_SetNeedUpdate(flags); } CConstRef CSeq_entry_Info::GetCompleteSeq_entry(void) const { x_UpdateComplete(); return m_Object; } CConstRef CSeq_entry_Info::GetSeq_entryCore(void) const { x_UpdateCore(); return m_Object; } void CSeq_entry_Info::x_ParentAttach(CBioseq_set_Info& parent) { x_BaseParentAttach(parent); if ( parent.HasParent_Info() ) { CSeq_entry& entry = parent.GetParentSeq_entry_Info().x_GetObject(); if ( m_Object->GetParentEntry() != &entry ) { m_Object->SetParentEntry(&entry); //entry.ParentizeOneLevel(); this call is too slow } _ASSERT(m_Object->GetParentEntry() == &entry); } } void CSeq_entry_Info::x_ParentDetach(CBioseq_set_Info& parent) { m_Object->ResetParentEntry(); x_BaseParentDetach(parent); } void CSeq_entry_Info::x_TSEAttachContents(CTSE_Info& tse) { TParent::x_TSEAttachContents(tse); if ( m_Contents ) { m_Contents->x_TSEAttach(tse); } } void CSeq_entry_Info::x_TSEDetachContents(CTSE_Info& tse) { if ( m_Contents ) { m_Contents->x_TSEDetach(tse); } TParent::x_TSEDetachContents(tse); } void CSeq_entry_Info::x_DSAttachContents(CDataSource& ds) { TParent::x_DSAttachContents(ds); if ( m_Object ) { x_DSMapObject(m_Object, ds); } if ( m_Contents ) { m_Contents->x_DSAttach(ds); } } void CSeq_entry_Info::x_DSDetachContents(CDataSource& ds) { if ( m_Contents ) { m_Contents->x_DSDetach(ds); } if ( m_Object ) { x_DSUnmapObject(m_Object, ds); } TParent::x_DSDetachContents(ds); } void CSeq_entry_Info::x_DSMapObject(CConstRef obj, CDataSource& ds) { ds.x_Map(obj, this); } void CSeq_entry_Info::x_DSUnmapObject(CConstRef obj, CDataSource& ds) { ds.x_Unmap(obj, this); } void CSeq_entry_Info::x_SetObject(TObject& obj) { // x_CheckWhich(CSeq_entry::e_not_set); _ASSERT(!m_Object); _ASSERT(!m_Contents); m_Object.Reset(&obj); if ( HasDataSource() ) { x_DSMapObject(m_Object, GetDataSource()); } switch ( (m_Which = obj.Which()) ) { case CSeq_entry::e_Seq: m_Contents.Reset(new CBioseq_Info(obj.SetSeq())); break; case CSeq_entry::e_Set: m_Contents.Reset(new CBioseq_set_Info(obj.SetSet())); break; default: break; } x_AttachContents(); } void CSeq_entry_Info::x_SetObject(const CSeq_entry_Info& info, TObjectCopyMap* copy_map) { //x_CheckWhich(CSeq_entry::e_not_set); _ASSERT(!m_Object); _ASSERT(!m_Contents); m_Object.Reset(new CSeq_entry); if ( HasDataSource() ) { x_DSMapObject(m_Object, GetDataSource()); } CRef cinfo; switch ( info.Which() ) { case CSeq_entry::e_Seq: cinfo.Reset(new CBioseq_Info(info.GetSeq(), copy_map)); break; case CSeq_entry::e_Set: cinfo.Reset(new CBioseq_set_Info(info.GetSet(), copy_map)); break; default: break; } x_Select(info.Which(), cinfo); } void CSeq_entry_Info::x_AttachContents(void) { if ( m_Contents ) { m_Contents->x_ParentAttach(*this); x_AttachObject(*m_Contents); } } void CSeq_entry_Info::x_DetachContents(void) { if ( m_Contents ) { x_DetachObject(*m_Contents); m_Contents->x_ParentDetach(*this); } } void CSeq_entry_Info::UpdateAnnotIndex(void) const { if ( x_DirtyAnnotIndex() ) { GetTSE_Info().UpdateAnnotIndex(*this); } } void CSeq_entry_Info::x_UpdateAnnotIndexContents(CTSE_Info& tse) { if ( m_Contents ) { m_Contents->x_UpdateAnnotIndex(tse); } TParent::x_UpdateAnnotIndexContents(tse); } inline void CSeq_entry_Info::x_UpdateSkeleton() const { if ( !m_Object ) { GetTSE_Info().x_LoadDelayedMainChunk(); } } void CSeq_entry_Info::x_Update(TNeedUpdateFlags flags) const { x_UpdateSkeleton(); TParent::x_Update(flags); } CSeq_entry::E_Choice CSeq_entry_Info::Which(void) const { x_UpdateSkeleton(); return m_Which; } CConstRef CSeq_entry_Info::GetSeq_entrySkeleton(void) const { x_UpdateSkeleton(); return m_Object; } CSeq_entry& CSeq_entry_Info::x_GetObject(void) { x_UpdateSkeleton(); return *m_Object; } const CSeq_entry& CSeq_entry_Info::x_GetObject(void) const { x_UpdateSkeleton(); return *m_Object; } const CBioseq_Base_Info& CSeq_entry_Info::x_GetBaseInfo(void) const { x_UpdateSkeleton(); return *m_Contents; } bool CSeq_entry_Info::IsSetDescr(void) const { x_UpdateSkeleton(); // x_Update(fNeedUpdate_descr); return m_Contents && m_Contents->IsSetDescr(); } const CSeq_descr& CSeq_entry_Info::GetDescr(void) const { x_Update(fNeedUpdate_descr); return m_Contents->GetDescr(); } void CSeq_entry_Info::SetDescr(TDescr& v) { x_Update(fNeedUpdate_descr); m_Contents->SetDescr(v); } CSeq_entry_Info::TDescr& CSeq_entry_Info::SetDescr(void) { x_Update(fNeedUpdate_descr); return m_Contents->SetDescr(); } void CSeq_entry_Info::ResetDescr(void) { x_Update(fNeedUpdate_descr); m_Contents->ResetDescr(); } bool CSeq_entry_Info::AddSeqdesc(CSeqdesc& d) { x_Update(fNeedUpdate_descr); return m_Contents->AddSeqdesc(d); } CRef CSeq_entry_Info::RemoveSeqdesc(const CSeqdesc& d) { x_Update(fNeedUpdate_descr); return m_Contents->RemoveSeqdesc(d); } CRef CSeq_entry_Info::ReplaceSeqdesc(const CSeqdesc& old_desc, CSeqdesc& new_desc) { x_Update(fNeedUpdate_descr); return m_Contents->ReplaceSeqdesc(old_desc, new_desc); } /* void CSeq_entry_Info::AddDescr(CSeq_entry_Info& src) { x_Update(fNeedUpdate_descr); if ( src.IsSetDescr() ) { m_Contents->AddSeq_descr(src.m_Contents->SetDescr()); } } */ void CSeq_entry_Info::AddSeq_descr(const TDescr& v) { x_Update(fNeedUpdate_descr); m_Contents->AddSeq_descr(v); } bool CSeq_entry_Info::x_IsEndDesc(TDesc_CI iter) const { return m_Contents->x_IsEndDesc(iter); } CSeq_entry_Info::TDesc_CI CSeq_entry_Info::x_GetFirstDesc(TDescTypeMask types) const { return m_Contents->x_GetFirstDesc(types); } CSeq_entry_Info::TDesc_CI CSeq_entry_Info::x_GetNextDesc(TDesc_CI iter, TDescTypeMask types) const { return m_Contents->x_GetNextDesc(iter, types); } CRef CSeq_entry_Info::AddAnnot(CSeq_annot& annot) { return m_Contents->AddAnnot(annot); } void CSeq_entry_Info::AddAnnot(CRef annot) { m_Contents->AddAnnot(annot); } void CSeq_entry_Info::RemoveAnnot(CRef annot) { m_Contents->RemoveAnnot(annot); } void CSeq_entry_Info::x_SetBioseqChunkId(TChunkId _DEBUG_ARG(chunk_id)) { _ASSERT(chunk_id == kBioseqChunkId); //x_CheckWhich(CSeq_entry::e_not_set); _ASSERT(!m_Object); _ASSERT(!m_Contents); x_SetNeedUpdate(CTSE_Info::fNeedUpdate_bioseq); m_Which = CSeq_entry::e_Seq; } CRef CSeq_entry_Info::AddEntry(CSeq_entry& entry, int index) { x_CheckWhich(CSeq_entry::e_Set); return SetSet().AddEntry(entry, index); } void CSeq_entry_Info::AddEntry(CRef entry, int index) { x_CheckWhich(CSeq_entry::e_Set); SetSet().AddEntry(entry, index); } void CSeq_entry_Info::RemoveEntry(CRef entry) { x_CheckWhich(CSeq_entry::e_Set); SetSet().RemoveEntry(entry); } const CBioObjectId& CSeq_entry_Info::GetBioObjectId(void) const { if (m_Contents) return m_Contents->GetBioObjectId(); return TParent::GetBioObjectId(); } const CSeq_entry_Info::TAnnot& CSeq_entry_Info::GetLoadedAnnot(void) const { _ASSERT(m_Contents); if (!m_Contents) NCBI_THROW(CObjMgrException, eInvalidHandle, "The CSeq_entry_Handle must be selected first."); return m_Contents->GetLoadedAnnot(); } namespace { static inline void x_SortUnique(CTSE_Info::TSeqIds& ids) { sort(ids.begin(), ids.end()); ids.erase(unique(ids.begin(), ids.end()), ids.end()); } } void CSeq_entry_Info::x_GetBioseqsIds(TSeqIds& ids) const { if ( IsSet() ) { const CBioseq_set_Info& seqset = GetSet(); ITERATE ( CBioseq_set_Info::TSeq_set, it, seqset.GetSeq_set() ) { (*it)->x_GetBioseqsIds(ids); } } if ( IsSeq() ) { const CBioseq_Info::TId& seq_ids = GetSeq().GetId(); ids.insert(ids.end(), seq_ids.begin(), seq_ids.end()); } } void CSeq_entry_Info::x_GetAnnotIds(TSeqIds& ids) const { if ( IsSet() ) { const CBioseq_set_Info& seqset = GetSet(); ITERATE ( CBioseq_set_Info::TSeq_set, it, seqset.GetSeq_set() ) { (*it)->x_GetBioseqsIds(ids); } } if ( Which() != CSeq_entry::e_not_set ) { const CBioseq_Base_Info::TAnnot& annots = x_GetBaseInfo().GetAnnot(); ITERATE ( CBioseq_Base_Info::TAnnot, it, annots ) { const CSeq_annot_Info::TAnnotObjectKeys& keys = (*it)->GetAnnotObjectKeys(); ITERATE ( CSeq_annot_Info::TAnnotObjectKeys, kit, keys ) { const CSeq_id_Handle id = kit->m_Handle; if ( !id ) { continue; } if ( !ids.empty() && id == ids.back() ) { continue; } ids.push_back(id); } } } } void CSeq_entry_Info::GetBioseqsIds(TSeqIds& ids) const { x_GetBioseqsIds(ids); x_SortUnique(ids); } void CSeq_entry_Info::GetAnnotIds(TSeqIds& ids) const { GetTSE_Info().UpdateAnnotIndex(*this); x_GetAnnotIds(ids); x_SortUnique(ids); } void CSeq_entry_Info::GetSeqAndAnnotIds(TSeqIds& seq_ids, TSeqIds& annot_ids) const { GetBioseqsIds(seq_ids); GetAnnotIds(annot_ids); } END_SCOPE(objects) END_NCBI_SCOPE