1 /*  $Id: apply_object.cpp 632623 2021-06-03 17:38:11Z ivanov $
2 * ===========================================================================
3 *
4 *                            PUBLIC DOMAIN NOTICE
5 *               National Center for Biotechnology Information
6 *
7 *  This software/database is a "United States Government Work" under the
8 *  terms of the United States Copyright Act.  It was written as part of
9 *  the author's official duties as a United States Government employee and
10 *  thus cannot be copyrighted.  This software/database is freely available
11 *  to the public for use. The National Library of Medicine and the U.S.
12 *  Government have not placed any restriction on its use or reproduction.
13 *
14 *  Although all reasonable efforts have been taken to ensure the accuracy
15 *  and reliability of the software and data, the NLM and the U.S.
16 *  Government do not and cannot warrant the performance or results that
17 *  may be obtained by using this software or data. The NLM and the U.S.
18 *  Government disclaim all warranties, express or implied, including
19 *  warranties of performance, merchantability or fitness for any particular
20 *  purpose.
21 *
22 *  Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * Author: Colleen Bollin, NCBI
27 *
28 * File Description:
29 *   CApplyObject class
30 */
31 #include <ncbi_pch.hpp>
32 #include <corelib/ncbistd.hpp>
33 #include <corelib/ncbiobj.hpp>
34 #include <objects/seqfeat/Seq_feat.hpp>
35 #include <objects/seq/Seq_descr.hpp>
36 #include <objects/general/User_object.hpp>
37 #include <objects/general/Object_id.hpp>
38 #include <objmgr/seq_entry_ci.hpp>
39 #include <objmgr/seq_feat_handle.hpp>
40 #include <objmgr/feat_ci.hpp>
41 #include <objmgr/seq_annot_ci.hpp>
42 #include <objmgr/seq_annot_handle.hpp>
43 #include <objtools/edit/apply_object.hpp>
44 
45 BEGIN_NCBI_SCOPE
BEGIN_SCOPE(objects)46 BEGIN_SCOPE(objects)
47 BEGIN_SCOPE(edit)
48 
49 CApplyObject::CApplyObject(CBioseq_Handle bsh, const CSeqdesc& desc) : m_Delete(false)
50 {
51     m_SEH = bsh.GetParentEntry();
52     if (!desc.IsMolinfo() && !desc.IsTitle()) {
53         CBioseq_set_Handle bssh = bsh.GetParentBioseq_set();
54         if (bssh && bssh.IsSetClass() && bssh.GetClass() == objects::CBioseq_set::eClass_nuc_prot) {
55             m_SEH = bssh.GetParentEntry();
56         }
57     }
58 
59     m_Original.Reset(&desc);
60     CRef<CSeqdesc> new_desc(new CSeqdesc());
61     new_desc->Assign(desc);
62     m_Editable = new_desc.GetPointer();
63 }
64 
65 
CApplyObject(CBioseq_Handle bsh,CSeqdesc::E_Choice subtype)66 CApplyObject::CApplyObject(CBioseq_Handle bsh, CSeqdesc::E_Choice subtype): m_Delete(false)
67 {
68     m_SEH = bsh.GetParentEntry();
69     if (subtype != CSeqdesc::e_Molinfo && subtype != CSeqdesc::e_Title) {
70         CBioseq_set_Handle bssh = bsh.GetParentBioseq_set();
71         if (bssh && bssh.IsSetClass() && bssh.GetClass() == objects::CBioseq_set::eClass_nuc_prot) {
72             m_SEH = bssh.GetParentEntry();
73         }
74     }
75 
76     m_Original.Reset(NULL);
77     CRef<CSeqdesc> new_desc(new CSeqdesc());
78     new_desc->Select(subtype);
79     m_Editable = new_desc.GetPointer();
80 }
81 
82 
CApplyObject(CBioseq_Handle bsh,const string & user_label)83 CApplyObject::CApplyObject(CBioseq_Handle bsh, const string& user_label) : m_Delete(false)
84 {
85     m_SEH = bsh.GetParentEntry();
86     CBioseq_set_Handle bssh = bsh.GetParentBioseq_set();
87     if (bssh && bssh.IsSetClass() && bssh.GetClass() == objects::CBioseq_set::eClass_nuc_prot) {
88         m_SEH = bssh.GetParentEntry();
89     }
90 
91     m_Original.Reset(NULL);
92     CRef<CSeqdesc> new_desc(new CSeqdesc());
93     new_desc->SetUser().SetType().SetStr(user_label);
94     m_Editable = new_desc.GetPointer();
95 }
96 
97 
CApplyObject(CBioseq_Handle bsh,const CSeq_feat & feat)98 CApplyObject::CApplyObject(CBioseq_Handle bsh, const CSeq_feat& feat) : m_Delete(false)
99 {
100     m_SEH = bsh.GetParentEntry();
101     m_Original.Reset(&feat);
102     CRef<CSeq_feat> new_feat(new CSeq_feat());
103     new_feat->Assign(feat);
104     m_Editable = new_feat.GetPointer();
105 }
106 
107 
CApplyObject(CBioseq_Handle bsh)108 CApplyObject::CApplyObject(CBioseq_Handle bsh) : m_Delete(false)
109 {
110     m_SEH = bsh.GetParentEntry();
111     m_Original.Reset(bsh.GetCompleteBioseq().GetPointer());
112     CRef<CBioseq> new_seq(new CBioseq());
113     new_seq->Assign(*(bsh.GetCompleteBioseq()));
114     m_Editable = new_seq.GetPointer();
115 }
116 
117 
ApplyChange()118 void CApplyObject::ApplyChange()
119 {
120     if (m_Delete) {
121         // deletion
122         if (m_Original) {
123             const CSeqdesc* orig_desc = dynamic_cast<const CSeqdesc * >(m_Original.GetPointer());
124             const CSeq_feat* orig_feat = dynamic_cast<const CSeq_feat * >(m_Original.GetPointer());
125             const CSeq_inst* orig_inst = dynamic_cast<const CSeq_inst * >(m_Original.GetPointer());
126             if (orig_desc) {
127                 CSeq_entry_Handle seh = GetSeqEntryForSeqdesc (CRef<CScope>(&(m_SEH.GetScope())), *orig_desc);
128                 if (!seh) {
129                     seh = m_SEH;
130                 }
131                 CSeq_entry_EditHandle eseh = seh.GetEditHandle();
132                 eseh.RemoveSeqdesc(*orig_desc);
133             } else if (orig_feat) {
134                 CSeq_feat_Handle oh = m_SEH.GetScope().GetSeq_featHandle(*orig_feat);
135                 CSeq_feat_EditHandle(oh).Remove();
136             } else if (orig_inst) {
137                 // not going to handle this for now
138             }
139         }
140         return;
141     }
142 
143     CSeqdesc* desc = dynamic_cast<CSeqdesc * >(m_Editable.GetPointer());
144     CSeq_feat* feat = dynamic_cast<CSeq_feat * >(m_Editable.GetPointer());
145     CSeq_inst* inst = dynamic_cast<CSeq_inst * >(m_Editable.GetPointer());
146 
147     if (desc) {
148         if (m_Original) {
149             const CSeqdesc* orig_desc = dynamic_cast<const CSeqdesc* >(m_Original.GetPointer());
150             CSeqdesc* change_desc = const_cast<CSeqdesc* >(orig_desc);
151             change_desc->Assign(*desc);
152         } else {
153             CSeq_entry_EditHandle eseh = m_SEH.GetEditHandle();
154             eseh.AddSeqdesc(const_cast<CSeqdesc&>(*desc));
155         }
156     } else if (feat) {
157         if (m_Original) {
158             const CSeq_feat* old_feat = dynamic_cast<const CSeq_feat * >(m_Original.GetPointer());
159             CSeq_feat_Handle oh = m_SEH.GetScope().GetSeq_featHandle(*old_feat);
160             // This is necessary, to make sure that we are in "editing mode"
161             const CSeq_annot_Handle& annot_handle = oh.GetAnnot();
162             CSeq_entry_EditHandle eh = annot_handle.GetParentEntry().GetEditHandle();
163 
164             // Now actually edit the feature
165             CSeq_feat_EditHandle feh(oh);
166             CSeq_entry_Handle parent_entry = feh.GetAnnot().GetParentEntry();
167 
168             feh.Replace(*feat);
169             if (feh.IsSetData() && feh.GetData().IsCdregion() && feh.IsSetProduct()) {
170                 if (parent_entry.IsSet()
171                      && parent_entry.GetSet().IsSetClass()
172                      && parent_entry.GetSet().GetClass() == CBioseq_set::eClass_nuc_prot) {
173                     // already on nuc-prot set, leave it alone
174                 } else {
175                     CBioseq_set_Handle nuc_parent = parent_entry.GetParentBioseq_set();
176                     if (nuc_parent && nuc_parent.IsSetClass() && nuc_parent.GetClass() == CBioseq_set::eClass_nuc_prot) {
177                         CSeq_annot_Handle ftable;
178                         CSeq_entry_Handle parent_seh = nuc_parent.GetParentEntry();
179                         CSeq_annot_CI annot_ci(parent_seh, CSeq_annot_CI::eSearch_entry);
180                         for (; annot_ci; ++annot_ci) {
181                             if ((*annot_ci).IsFtable()) {
182                                 ftable = *annot_ci;
183                                 break;
184                             }
185                         }
186 
187                         if (!ftable) {
188                             CRef<CSeq_annot> new_annot(new CSeq_annot());
189                             new_annot->SetData().SetFtable();
190                             CSeq_entry_EditHandle eh = parent_seh.GetEditHandle();
191                             ftable = eh.AttachAnnot(*new_annot);
192                         }
193 
194                         CSeq_annot_EditHandle new_annot = ftable.GetEditHandle();
195                         new_annot.TakeFeat(feh);
196                     }
197                 }
198             }
199         } else {
200             if (feat->IsSetData() && feat->GetData().IsCdregion() && feat->IsSetProduct()) {
201                 CBioseq_Handle bsh = m_SEH.GetScope().GetBioseqHandle(feat->GetProduct());
202                 if (bsh) {
203                     CBioseq_set_Handle nuc_parent = bsh.GetParentBioseq_set();
204                     if (nuc_parent && nuc_parent.IsSetClass() && nuc_parent.GetClass() == CBioseq_set::eClass_nuc_prot) {
205                         m_SEH = nuc_parent.GetParentEntry();
206                     }
207                 }
208             }
209             CSeq_annot_Handle ftable;
210             CSeq_annot_CI annot_ci(m_SEH, CSeq_annot_CI::eSearch_entry);
211             for (; annot_ci; ++annot_ci) {
212                 if ((*annot_ci).IsFtable()) {
213                     ftable = *annot_ci;
214                     break;
215                 }
216             }
217 
218             CSeq_entry_EditHandle eh = m_SEH.GetEditHandle();
219 
220             if (!ftable) {
221                 CRef<CSeq_annot> new_annot(new CSeq_annot());
222                 ftable = eh.AttachAnnot(*new_annot);
223             }
224 
225             CSeq_annot_EditHandle aeh(ftable);
226             aeh.AddFeat(*feat);
227 
228         }
229 
230     } else if (inst) {
231         CBioseq_EditHandle beeh = m_SEH.GetSeq().GetEditHandle();
232         beeh.SetInst(*inst);
233     }
234 }
235 
236 
GetSeqEntryForSeqdesc(CRef<CScope> scope,const CSeqdesc & seq_desc)237 CSeq_entry_Handle GetSeqEntryForSeqdesc (CRef<CScope> scope, const CSeqdesc& seq_desc)
238 {
239     CSeq_entry_Handle seh;
240 
241     if (!scope) {
242         return seh;
243     }
244 
245     CScope::TTSE_Handles tses;
246     scope->GetAllTSEs(tses, CScope::eAllTSEs);
247     ITERATE (CScope::TTSE_Handles, handle, tses) {
248         for (CSeq_entry_CI entry_ci(*handle, CSeq_entry_CI::fRecursive | CSeq_entry_CI::fIncludeGivenEntry); entry_ci; ++entry_ci) {
249             if (entry_ci->IsSetDescr()) {
250                 ITERATE (CBioseq::TDescr::Tdata, dit, entry_ci->GetDescr().Get()) {
251                     if (dit->GetPointer() == &seq_desc) {
252                         return *entry_ci;
253                     }
254                 }
255             }
256         }
257     }
258     return seh;
259 }
260 
261 
262 
263 
264 END_SCOPE(edit)
265 END_SCOPE(objects)
266 END_NCBI_SCOPE
267 
268