1 /*  $Id: discrepancy_core.hpp 629257 2021-04-13 13:28:26Z 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  * Authors:  Sema
27  * Created:  01/29/2015
28  */
29 
30 #ifndef _MISC_DISCREPANCY_DISCREPANCY_CORE_H_
31 #define _MISC_DISCREPANCY_DISCREPANCY_CORE_H_
32 
33 #include <misc/discrepancy/discrepancy.hpp>
34 #include <objects/biblio/Auth_list.hpp>
35 #include <objects/biblio/Cit_sub.hpp>
36 #include <objects/general/Person_id.hpp>
37 #include <objects/macro/Suspect_rule_set.hpp>
38 #include <objects/pub/Pub.hpp>
39 #include <objects/pub/Pub_equiv.hpp>
40 #include <objects/seq/Pubdesc.hpp>
41 #include <objects/seqfeat/BioSource.hpp>
42 #include <objects/seqfeat/OrgName.hpp>
43 #include <objects/seqfeat/RNA_ref.hpp>
44 #include <objects/submit/Submit_block.hpp>
45 #include <objmgr/util/sequence.hpp>
46 
47 BEGIN_NCBI_SCOPE
48 USING_SCOPE(objects);
49 BEGIN_SCOPE(NDiscrepancy)
50 
51 /// Housekeeping classes
52 class CDiscrepancyConstructor;
53 
54 struct CDiscrepancyCaseProps
55 {
56     CDiscrepancyConstructor* Constructor;
57     string Descr;
58     TGroup Group;
59     vector<string> AliasList;
60 };
61 
62 class CDiscrepancyConstructor
63 {
64 protected:
~CDiscrepancyConstructor()65     virtual ~CDiscrepancyConstructor() {}
66     virtual CRef<CDiscrepancyCase> Create() const = 0;
67     static void Register(const string& name, const string& descr, TGroup group, CDiscrepancyConstructor& obj);
68     static string GetDiscrepancyCaseName(const string&);
69     static const CDiscrepancyConstructor* GetDiscrepancyConstructor(const string& name);
GetTable()70     static map<string, CDiscrepancyCaseProps>& GetTable() { return sm_Table.Get(); }
GetAliasTable()71     static map<string, string>& GetAliasTable() { return sm_AliasTable.Get(); }
72 private:
73     static CSafeStatic<map<string, CDiscrepancyCaseProps>> sm_Table;
74     static CSafeStatic<map<string, string>> sm_AliasTable;
75 
76 friend NCBI_DISCREPANCY_EXPORT string GetDiscrepancyCaseName(const string&);
77 friend NCBI_DISCREPANCY_EXPORT string GetDiscrepancyDescr(const string&);
78 friend NCBI_DISCREPANCY_EXPORT TGroup GetDiscrepancyGroup(const string&);
79 friend NCBI_DISCREPANCY_EXPORT vector<string> GetDiscrepancyNames(TGroup group);
80 friend NCBI_DISCREPANCY_EXPORT vector<string> GetDiscrepancyAliases(const string& name);
81 friend class CDiscrepancyAlias;
82 friend class CDiscrepancyContext;
83 friend class CReportItem;
84 };
85 
86 
Register(const string & name,const string & descr,TGroup group,CDiscrepancyConstructor & obj)87 inline void CDiscrepancyConstructor::Register(const string& name, const string& descr, TGroup group, CDiscrepancyConstructor& obj)
88 {
89     auto& entry = GetTable()[name];
90     entry.Constructor = &obj;
91     entry.Descr = descr;
92     entry.Group = group;
93 }
94 
95 
96 class CDiscrepancyAlias : public CDiscrepancyConstructor
97 {
98 protected:
Create() const99     CRef<CDiscrepancyCase> Create() const { return CRef<CDiscrepancyCase>(); }
Register(const string & name,const string & alias)100     static void Register(const string& name, const string& alias)
101     {
102         map<string, string>& AliasTable = GetAliasTable();
103         if (AliasTable.find(alias) != AliasTable.end()) {
104             return;
105         }
106         AliasTable[alias] = name;
107         map<string, CDiscrepancyCaseProps>& Table = GetTable();
108         Table[name].AliasList.push_back(alias);
109     }
110 };
111 
112 
113 /// CDiscrepancyItem and CReportObject
114 class CDiscrepancyContext;
115 class CDiscrepancyObject;
116 
117 template<typename T> struct CSimpleTypeObject : public CObject
118 {
CSimpleTypeObjectCSimpleTypeObject119     CSimpleTypeObject() {};
CSimpleTypeObjectCSimpleTypeObject120     CSimpleTypeObject(const T& v) : Value(v) {};
121     T Value;
122 };
123 
124 
125 class CReportNode;
126 
127 class CDiscrepancyItem : public CReportItem
128 {
129 public:
CDiscrepancyItem(const string & m)130     CDiscrepancyItem(const string& m) : m_Msg(m), m_Count(0) {}
CDiscrepancyItem(CDiscrepancyCase & t,const string & s,const string & m,const string & x,const string & o,size_t n)131     CDiscrepancyItem(CDiscrepancyCase& t, const string& s, const string& m, const string& x, const string& o, size_t n)
132       : m_Str(s), m_Msg(m), m_Xml(x), m_Unit(o), m_Count(n), m_Test(&t) {}
GetTitle() const133     string GetTitle() const override { return m_Test ? m_Test->GetName() : kEmptyStr; }
GetStr() const134     string GetStr() const override { return m_Str; }
GetMsg() const135     string GetMsg() const override { return m_Msg; }
GetXml() const136     string GetXml() const override { return m_Xml; }
GetUnit() const137     string GetUnit() const override { return m_Unit; }
GetCount() const138     size_t GetCount() const override { return m_Count; }
GetDetails() const139     TReportObjectList GetDetails() const override { return m_Objs; }
GetSubitems() const140     TReportItemList GetSubitems() const override { return m_Subs; }
CanAutofix() const141     bool CanAutofix() const override { return m_Autofix; }
GetSeverity() const142     ESeverity GetSeverity() const override { return m_Severity; }
IsFatal() const143     bool IsFatal() const override { return m_Severity == eSeverity_error; }
IsInfo() const144     bool IsInfo() const override { return m_Severity == eSeverity_info; }
IsExtended() const145     bool IsExtended() const override { return m_Ext; }
IsSummary() const146     bool IsSummary() const override { return m_Summ; }
IsReal() const147     bool IsReal() const override { return !m_Test.Empty(); }
148 
149 protected:
150     string m_Str;
151     string m_Msg;
152     string m_Xml;
153     string m_Unit;
154     size_t m_Count{ 0 };
155     mutable bool m_Autofix{ false };
156     ESeverity m_Severity{ eSeverity_warning };
157     bool m_Ext{ false };
158     bool m_Summ{ false };
159     TReportObjectList m_Objs;
160     TReportItemList m_Subs;
161     CRef<CDiscrepancyCase> m_Test;
162 friend class CReportNode;
163 friend class CDiscrepancyGroup;
164 friend class CReportItem;
165 friend class CDiscrepancyObject;
166 };
167 
168 
169 /// CDiscrepancyCore and CDiscrepancyVisitor - parents for CDiscrepancyCase_* classes
170 
171 struct CReportObjPtr
172 {
173     const CReportObj* P;
CReportObjPtrCReportObjPtr174     CReportObjPtr(const CReportObj* p) : P(p) {}
175     friend bool operator<(const CReportObjPtr& one, const CReportObjPtr& another);
176 };
177 typedef set<CReportObjPtr> TReportObjectSet;
178 
179 
180 class CReportNode : public CObject
181 {
182 public:
183     typedef map<string, CRef<CReportNode>> TNodeMap;
184 
CReportNode(const string & name=kEmptyStr)185     CReportNode(const string& name = kEmptyStr) : m_Name(name), m_Count(0) {}
186 
187     CReportNode& operator[](const string& name);
188 
Severity(CReportItem::ESeverity s)189     CReportNode& Severity(CReportItem::ESeverity s) { m_Severity = s; return *this; }
Fatal()190     CReportNode& Fatal() { m_Severity = CReportItem::eSeverity_error; return *this; }
Info()191     CReportNode& Info() { m_Severity = CReportItem::eSeverity_info; return *this; }
Ext(bool b=true)192     CReportNode& Ext(bool b = true) { m_Ext = b; return *this; }
Summ(bool b=true)193     CReportNode& Summ(bool b = true) { m_Summ = b; return *this; }
NoRec(bool b=true)194     CReportNode& NoRec(bool b = true) { m_NoRec = b; return *this; }
Incr()195     CReportNode& Incr() { m_Count++; return *this; }
196 
Exist(TReportObjectList & list,TReportObjectSet & hash,CReportObj & obj)197     static bool Exist(TReportObjectList& list, TReportObjectSet& hash, CReportObj& obj) { return hash.find(&obj) != hash.end(); }
Exist(const string & name) const198     bool Exist(const string& name) const { return m_Map.find(name) != m_Map.end(); }
Exist(CReportObj & obj)199     bool Exist(CReportObj& obj) { return Exist(m_Objs, m_Hash, obj); }
200     static void Add(TReportObjectList& list, TReportObjectSet& hash, CReportObj& obj, bool unique = true);
Add(CReportObj & obj,bool unique=true)201     CReportNode& Add(CReportObj& obj, bool unique = true) { Add(m_Objs, m_Hash, obj, unique);  return *this; }
202     static void Add(TReportObjectList& list, TReportObjectSet& hash, TReportObjectList& objs, bool unique = true);
Add(TReportObjectList & objs,bool unique=true)203     CReportNode& Add(TReportObjectList& objs, bool unique = true) { Add(m_Objs, m_Hash, objs, unique);  return *this; }
204 
GetObjects()205     TReportObjectList& GetObjects() { return m_Objs; }
GetMap()206     TNodeMap& GetMap() { return m_Map; }
GetCount() const207     size_t GetCount() const { return m_Count > 0 ? m_Count : m_Objs.size(); }
SetCount(size_t n)208     void SetCount(size_t n) { m_Count = n; }
209     CRef<CReportItem> Export(CDiscrepancyCase& test, bool unique = true) const;
210     void Copy(CRef<CReportNode> other);
211     bool Promote();
212 
empty() const213     bool empty() const { return m_Map.empty() && m_Objs.empty(); }
clear()214     void clear() { m_Map.clear(); m_Objs.clear(); m_Hash.clear(); }
clearObjs()215     void clearObjs() { m_Objs.clear(); }
216 protected:
217     string m_Name;
218     TNodeMap m_Map;
219     TReportObjectList m_Objs;
220     TReportObjectSet m_Hash;
221     CReportItem::ESeverity m_Severity{ CReportItem::eSeverity_warning };
222     bool m_Autofix{ false };
223     bool m_Ext{ false };
224     bool m_Summ{ false };
225     bool m_NoRec{ false };   // don't collect objects recursively
226     size_t m_Count{ 0 };
227 };
228 
229 
230 class CDiscrepancyCore : public CDiscrepancyCase
231 {
232 public:
CDiscrepancyCore()233     CDiscrepancyCore() : m_Count(0) {}
Summarize(CDiscrepancyContext & context)234     virtual void Summarize(CDiscrepancyContext& context){}
GetReport() const235     TReportItemList GetReport() const override { return m_ReportItems; }
236     TReportObjectList GetObjects() const override;
Autofix(CDiscrepancyObject * obj,CDiscrepancyContext & context) const237     virtual CRef<CAutofixReport> Autofix(CDiscrepancyObject* obj, CDiscrepancyContext& context) const { return CRef<CAutofixReport>(); }
238 protected:
239     CReportNode m_Objs;
240     TReportItemList m_ReportItems;
241     size_t m_Count;
242 };
243 
244 
245 //inline CRef<CAutofixReport> CDiscrepancyItem::Autofix(CScope& scope) const
246 //{
247 //    if (m_Autofix) {
248 //        CRef<CAutofixReport> ret = ((CDiscrepancyCore&)*m_Test).Autofix(this, scope);
249 //        m_Autofix = false;
250 //        return ret;
251 //    }
252 //    return CRef<CAutofixReport>();
253 //}
254 
255 
256 template<typename T> class CDiscrepancyVisitor : public CDiscrepancyCore
257 {
258 public:
259     void Call(const T& node, CDiscrepancyContext& context);
260     virtual void Visit(const T& node, CDiscrepancyContext& context) = 0;
261 };
262 
263 
264 /// BIG FILE
265 /// will change to enum when possible
266 class SEQUENCE {};
267 class SEQ_SET {};
268 class FEAT {};
269 class DESC {};
270 class BIOSRC {};
271 class PUBDESC {};
272 class AUTHORS {};
273 class SUBMIT {};
274 class STRING {};
275 
276 
277 struct CSeqSummary
278 {
279     static const size_t WINDOW_SIZE = 30;
CSeqSummaryCSeqSummary280     CSeqSummary() { clear(); }
clearCSeqSummary281     void clear() {
282         Len = 0; A = 0; C = 0; G = 0; T = 0; N = 0; Other = 0; Gaps = 0;
283         First = true; StartsWithGap = false; EndsWithGap = false; HasRef = false;
284         Label.clear(); Stats.clear(); NRuns.clear();
285         MaxN = 0; MinQ = 0;
286         _Pos = 0; _Ns = 0;
287         _QS = 0; _CBscore[0] = 0; _CBposition[0] = 0; _CBread = 0; _CBwrite = 0;
288     }
289     size_t Len;
290     size_t A;
291     size_t C;
292     size_t G;
293     size_t T;
294     size_t N;
295     size_t Other;
296     size_t Gaps;
297     size_t MaxN;
298     size_t MinQ;
299     bool First;
300     bool StartsWithGap;
301     bool EndsWithGap;
302     bool HasRef;
303     string Label;
304     // add more counters if needed
305     vector<pair<size_t, size_t>> NRuns;
306     size_t _QS;
307     size_t _CBscore[WINDOW_SIZE];
308     size_t _CBposition[WINDOW_SIZE];
309     size_t _CBread; // read pointer
310     size_t _CBwrite; // write pointer
311     size_t _Pos;
312     size_t _Ns;
313 
314     mutable string Stats;
315     string GetStats() const;
316 };
317 
318 /// CDiscrepancyContext - manage and run the list of tests
319 
320 // GENE_PRODUCT_CONFLICT
321 typedef list<pair<CRef<CDiscrepancyObject>, string>> TGenesList;
322 typedef map<string, TGenesList> TGeneLocusMap;
323 
324 /// BIG FILE
325 class CReadHook_Bioseq_set;
326 class CReadHook_Bioseq;
327 class CCopyHook_Bioseq_set;
328 class CCopyHook_Bioseq;
329 class CCopyHook_Seq_descr;
330 class CCopyHook_Seq_annot;
331 
332 class CDiscrepancyContext : public CDiscrepancySet
333 {
334 protected:
335     struct CParseNode;
336     struct CRefNode;
337 
338 public:
339     enum EFlag {
340         eHasRearranged = 1 << 0,
341         eHasSatFeat = 1 << 1,
342         eHasNonSatFeat = 1 << 2
343     };
344 
CDiscrepancyContext(objects::CScope & scope)345     CDiscrepancyContext(objects::CScope& scope) : m_Scope(&scope) {}
346 
347     bool AddTest(const string& name) override;
348     void Push(const CSerialObject& root, const string& fname) override;
Parse()349     void Parse() override { ParseAll(*m_RootNode); }
350     //void Parse(const CSerialObject& root, const string& fname) override;
351     void ParseObject(const CBioseq& root);
352     void ParseObject(const CBioseq_set& root);
353     void ParseObject(const CSeq_entry& root);
354     void ParseObject(const CSeq_submit& root);
355     void ParseStream(CObjectIStream& stream, const string& fname, bool skip, const string& default_header = kEmptyStr) override;
356     void ParseStrings(const string& fname) override;
357     void TestString(const string& str) override;
358     unsigned Summarize() override;
359     void Autofix(TReportObjectList& tofix, map<string, size_t>& rep, const string& default_header = kEmptyStr) override;
360     void AutofixFile(vector<CDiscrepancyObject*>&fixes, const string& default_header);
GetTests() const361     const TDiscrepancyCaseMap& GetTests() const override { return m_Tests; }
362     void OutputText(CNcbiOstream& out, unsigned short flags, char group) override;
363     void OutputXML(CNcbiOstream& out, unsigned short flags) override;
364     CParseNode* FindNode(const CRefNode& obj);
365     const CObject* GetMore(CReportObj& obj);
366     const CSerialObject* FindObject(CReportObj& obj, bool alt = false) override;
367     void ReplaceObject(CReportObj& obj, CSerialObject*, bool alt = false);
368     void ReplaceSeq_feat(CReportObj& obj, const CSeq_feat& old_feat, CSeq_feat& new_feat, bool alt = false);
GetBioseq_setHandle(const CBioseq_set & bss)369     CBioseq_set_Handle GetBioseq_setHandle(const CBioseq_set& bss) { return m_Scope->GetBioseq_setHandle(bss); }
GetBioseqHandle(const CBioseq & bs)370     CBioseq_EditHandle GetBioseqHandle(const CBioseq& bs) { return m_Scope->GetBioseqEditHandle(bs); }
371 
CurrentText() const372     const string& CurrentText() const { return m_CurrentNode->m_Ref->m_Text; }
CurrentBioseq() const373     const CBioseq& CurrentBioseq() const { return *dynamic_cast<const CBioseq*>(&*m_CurrentNode->m_Obj); }
CurrentBioseq_set() const374     const CBioseq_set& CurrentBioseq_set() const { return *dynamic_cast<const CBioseq_set*>(&*m_CurrentNode->m_Obj); }
375     const CSeqSummary& CurrentBioseqSummary() const;
ReadFlags() const376     unsigned char ReadFlags() const { return m_CurrentNode->m_Flags; }
PropagateFlags(unsigned char f)377     void PropagateFlags(unsigned char f) { for (CParseNode* node = m_CurrentNode; node; node = node->m_Parent) node->m_Flags |= f; }
378 
Call(CDiscrepancyVisitor<T> & disc,const T & obj)379     template<typename T> void Call(CDiscrepancyVisitor<T>& disc, const T& obj){ disc.Call(obj, *this); }
380 
GetScope() const381     objects::CScope& GetScope() const { return const_cast<objects::CScope&>(*m_Scope); }
382 
383     //void SetFile(const string& fname);
384     void SetSuspectRules(const string& name, bool read = true) override;
385     CConstRef<CSuspect_rule_set> GetProductRules();
386     CConstRef<CSuspect_rule_set> GetOrganelleProductRules();
387 
388     // Lazy
389     static bool IsUnculturedNonOrganelleName(const string& taxname);
390     static bool HasLineage(const CBioSource& biosrc, const string& def_lineage, const string& type);
391     bool HasLineage(const CBioSource* biosrc, const string& lineage) const;
392     static bool IsOrganelle(const CBioSource* biosrc);
393     bool IsEukaryotic(const CBioSource* biosrc) const;
394     bool IsBacterial(const CBioSource* biosrc) const;
395     bool IsViral(const CBioSource* biosrc) const;
GetSeqSummary()396     const CSeqSummary& GetSeqSummary() { return *m_CurrentNode->m_BioseqSummary; }
397     void BuildSeqSummary(const CBioseq& bs, CSeqSummary& summary);
InGenProdSet() const398     bool InGenProdSet() const { return m_CurrentNode->InGenProdSet(); }
GetTitle() const399     CConstRef<CSeqdesc> GetTitle() const { return m_CurrentNode->GetTitle(); }
GetMolinfo() const400     CConstRef<CSeqdesc> GetMolinfo() const { return m_CurrentNode->GetMolinfo(); }
GetBiosource() const401     CConstRef<CSeqdesc> GetBiosource() const { return m_CurrentNode->GetBiosource(); }
GetSetBiosources() const402     const vector<CConstRef<CSeqdesc>>& GetSetBiosources() const { return m_CurrentNode->m_SetBiosources; }
403 
404     static string GetGenomeName(unsigned n);
405     static string GetAminoacidName(const CSeq_feat& feat); // from tRNA
406     bool IsBadLocusTagFormat(const string& locus_tag) const;
407     bool IsRefseq() const;
408     bool IsBGPipe();
409     bool IsPseudo(const CSeq_feat& feat);
410     const CSeq_feat* GetGeneForFeature(const CSeq_feat& feat);
411     string GetProdForFeature(const CSeq_feat& feat);
412     void CollectFeature(const CSeq_feat& feat);
413     void ClearFeatureList();
FeatAll()414     const vector<const CSeq_feat*>& FeatAll() { return m_FeatAll; }
FeatGenes()415     const vector<const CSeq_feat*>& FeatGenes() { return m_FeatGenes; }
FeatPseudo()416     const vector<const CSeq_feat*>& FeatPseudo() { return m_FeatPseudo; }
FeatCDS()417     const vector<const CSeq_feat*>& FeatCDS() { return m_FeatCDS; }
FeatMRNAs()418     const vector<const CSeq_feat*>& FeatMRNAs() { return m_FeatMRNAs; }
FeatRRNAs()419     const vector<const CSeq_feat*>& FeatRRNAs() { return m_FeatRRNAs; }
FeatTRNAs()420     const vector<const CSeq_feat*>& FeatTRNAs() { return m_FeatTRNAs; }
Feat_RNAs()421     const vector<const CSeq_feat*>& Feat_RNAs() { return m_Feat_RNAs; }
FeatExons()422     const vector<const CSeq_feat*>& FeatExons() { return m_FeatExons; }
FeatIntrons()423     const vector<const CSeq_feat*>& FeatIntrons() { return m_FeatIntrons; }
FeatMisc()424     const vector<const CSeq_feat*>& FeatMisc() { return m_FeatMisc; }
425 
426     sequence::ECompare Compare(const CSeq_loc& loc1, const CSeq_loc& loc2) const;
427 
428 /// BIG FILE
429     enum EFixType {
430         eFixNone,
431         eFixSelf,
432         eFixParent,
433         eFixSet
434     };
435 
436     CRefNode* ContainingSet(CRefNode& ref);
437     CRef<CDiscrepancyObject> BioseqObjRef(EFixType fix = eFixNone, const CObject* more = nullptr);
438     CRef<CDiscrepancyObject> BioseqSetObjRef(bool fix = false, const CObject* more = nullptr);
439     CRef<CDiscrepancyObject> SubmitBlockObjRef(bool fix = false, const CObject* more = nullptr);
440     CRef<CDiscrepancyObject> SeqFeatObjRef(const CSeq_feat& feat, EFixType fix = eFixNone, const CObject* more = nullptr);
441     CRef<CDiscrepancyObject> SeqFeatObjRef(const CSeq_feat& feat, const CObject* fix, const CObject* more = nullptr);
442     CRef<CDiscrepancyObject> SeqdescObjRef(const CSeqdesc& desc, const CObject* fix = nullptr, const CObject* more = nullptr);
443     CRef<CDiscrepancyObject> BiosourceObjRef(const CBioSource& biosrc, bool fix = false, const CObject* more = nullptr);
444     CRef<CDiscrepancyObject> PubdescObjRef(const CPubdesc& pubdesc, bool fix = false, const CObject* more = nullptr);
445     CRef<CDiscrepancyObject> AuthorsObjRef(const CAuth_list& authors, bool fix = false, const CObject* more = nullptr);
446     CRef<CDiscrepancyObject> StringObjRef(const CObject* fix = nullptr, const CObject* more = nullptr);
IsBioseq() const447     bool IsBioseq() const { return m_CurrentNode->m_Type == eBioseq; }
AuthPub(const CAuth_list * a) const448     const CPub* AuthPub(const CAuth_list* a) const { auto& apm = m_CurrentNode->m_AuthorPubMap; auto it = apm.find(a); return it == apm.end() ? nullptr : it->second; }
449 
450     // GENE_PRODUCT_CONFLICT
GetGeneLocusMap()451     TGeneLocusMap& GetGeneLocusMap() { return m_GeneLocusMap; }
452 
453     struct CSeqdesc_vec
454     {
455         CParseNode& node;
CSeqdesc_vecCDiscrepancyContext::CSeqdesc_vec456         CSeqdesc_vec(CParseNode& n) : node(n) {}
457         struct iterator
458         {
459             vector<CRef<CParseNode>>::iterator it;
iteratorCDiscrepancyContext::CSeqdesc_vec::iterator460             iterator(vector<CRef<CParseNode>>::iterator x) : it(x) {}
operator ++CDiscrepancyContext::CSeqdesc_vec::iterator461             void operator++() { ++it; }
operator !=CDiscrepancyContext::CSeqdesc_vec::iterator462             bool operator!=(const iterator& x) const { return it != x.it; }
operator ==CDiscrepancyContext::CSeqdesc_vec::iterator463             bool operator==(const iterator& x) const { return !(x != *this); }
operator *CDiscrepancyContext::CSeqdesc_vec::iterator464             const CSeqdesc& operator*() { return static_cast<const CSeqdesc&>(*(*it)->m_Obj); }
465         };
beginCDiscrepancyContext::CSeqdesc_vec466         iterator begin() { return iterator(node.m_Descriptors.begin()); }
endCDiscrepancyContext::CSeqdesc_vec467         iterator end() { return iterator(node.m_Descriptors.end()); }
468     };
469 
470     struct CSeq_feat_vec
471     {
472         CParseNode& node;
CSeq_feat_vecCDiscrepancyContext::CSeq_feat_vec473         CSeq_feat_vec(CParseNode& n) : node(n) {}
474         struct iterator
475         {
476             vector<CRef<CParseNode>>::iterator it;
iteratorCDiscrepancyContext::CSeq_feat_vec::iterator477             iterator(vector<CRef<CParseNode>>::iterator x) : it(x) {}
operator ++CDiscrepancyContext::CSeq_feat_vec::iterator478             void operator++() { ++it; }
operator !=CDiscrepancyContext::CSeq_feat_vec::iterator479             bool operator!=(const iterator& x) const { return it != x.it; }
operator ==CDiscrepancyContext::CSeq_feat_vec::iterator480             bool operator==(const iterator& x) const { return !(x != *this); }
operator *CDiscrepancyContext::CSeq_feat_vec::iterator481             const CSeq_feat& operator*() { return static_cast<const CSeq_feat&>(*(*it)->m_Obj); }
482         };
beginCDiscrepancyContext::CSeq_feat_vec483         iterator begin() { return iterator(node.m_Features.begin()); }
endCDiscrepancyContext::CSeq_feat_vec484         iterator end() { return iterator(node.m_Features.end()); }
485     };
486 
487     struct CSeqdesc_run
488     {
489         CParseNode& node;
CSeqdesc_runCDiscrepancyContext::CSeqdesc_run490         CSeqdesc_run(CParseNode& n) : node(n) {}
491         struct iterator
492         {
493             CParseNode* node;
494             vector<CRef<CParseNode>>::iterator it;
iteratorCDiscrepancyContext::CSeqdesc_run::iterator495             iterator(CParseNode* n) : node(n) {
496                 while (node) {
497                     it = node->m_Descriptors.begin();
498                     if (it != node->m_Descriptors.end()) return;
499                     node = node->m_Parent;
500                 }
501             }
operator ++CDiscrepancyContext::CSeqdesc_run::iterator502             void operator++() {
503                 ++it;
504                 while (node) {
505                     if (it != node->m_Descriptors.end()) return;
506                     node = node->m_Parent;
507                     if (node) it = node->m_Descriptors.begin();
508                 }
509             }
operator !=CDiscrepancyContext::CSeqdesc_run::iterator510             bool operator!=(const iterator& x) const { return node != x.node || (node && it != x.it); }
operator ==CDiscrepancyContext::CSeqdesc_run::iterator511             bool operator==(const iterator& x) const { return !(x != *this); }
operator *CDiscrepancyContext::CSeqdesc_run::iterator512             const CSeqdesc& operator*() { return static_cast<const CSeqdesc&>(*(*it)->m_Obj); }
513         };
beginCDiscrepancyContext::CSeqdesc_run514         iterator begin() { return iterator(&node); }
endCDiscrepancyContext::CSeqdesc_run515         iterator end() { return iterator(nullptr); }
516     };
517 
518     struct CSeq_feat_run
519     {
520         CParseNode& node;
CSeq_feat_runCDiscrepancyContext::CSeq_feat_run521         CSeq_feat_run(CParseNode& n) : node(n) {}
522         struct iterator
523         {
524             CParseNode* node;
525             bool follow;
526             vector<CRef<CParseNode>>::iterator it;
iteratorCDiscrepancyContext::CSeq_feat_run::iterator527             iterator(CParseNode* n) : node(n), follow(n && n->m_Type == eBioseq && static_cast<const CBioseq&>(*n->m_Obj).IsNa()) {
528                 while (node) {
529                     it = node->m_Features.begin();
530                     if (it != node->m_Features.end()) return;
531                     node = follow ? node->m_Parent : nullptr;
532                 }
533             }
operator ++CDiscrepancyContext::CSeq_feat_run::iterator534             void operator++() {
535                 ++it;
536                 while (node) {
537                     if (it != node->m_Features.end()) return;
538                     node = follow ? node->m_Parent : nullptr;
539                     if (node) it = node->m_Features.begin();
540                 }
541             }
operator !=CDiscrepancyContext::CSeq_feat_run::iterator542             bool operator!=(const iterator& x) const { return node != x.node || (node && it != x.it); }
operator ==CDiscrepancyContext::CSeq_feat_run::iterator543             bool operator==(const iterator& x) const { return !(x != *this); }
operator *CDiscrepancyContext::CSeq_feat_run::iterator544             const CSeq_feat& operator*() { return static_cast<const CSeq_feat&>(*(*it)->m_Obj); }
545         };
beginCDiscrepancyContext::CSeq_feat_run546         iterator begin() { return iterator(&node); }
endCDiscrepancyContext::CSeq_feat_run547         iterator end() { return iterator(nullptr); }
548     };
GetSeqdesc()549     CSeqdesc_vec GetSeqdesc() { return CSeqdesc_vec(*m_CurrentNode); }
GetFeat()550     CSeq_feat_vec GetFeat() { return CSeq_feat_vec(*m_CurrentNode); }
GetAllSeqdesc()551     CSeqdesc_run GetAllSeqdesc() { return CSeqdesc_run(*m_CurrentNode); }
GetAllFeat()552     CSeq_feat_run GetAllFeat() { return CSeq_feat_run(*m_CurrentNode); }
GetBiosources() const553     const vector<const CBioSource*>& GetBiosources() const { return m_CurrentNode->m_Biosources; }
GetPubdescs() const554     const vector<const CPubdesc*>& GetPubdescs() const { return m_CurrentNode->m_Pubdescs; }
GetAuthors() const555     const vector<const CAuth_list*>& GetAuthors() const { return m_CurrentNode->m_Authors; }
556     const CPerson_id* GetPerson_id() const;
557     const CSubmit_block* GetSubmit_block() const;
558 
559 protected:
560     CRef<objects::CScope> m_Scope;
561     CRef<feature::CFeatTree> m_FeatTree;
562     TDiscrepancyCaseMap m_Tests;
563     vector<CConstRef<CBioseq_set>> m_Bioseq_set_Stack;
564     CBioseq_Handle m_Current_Bioseq_Handle;
565     CConstRef<CBioseq> m_Current_Bioseq;
566     CConstRef<CSubmit_block> m_Current_Submit_block;
567     CRef<CSimpleTypeObject<string>> m_Current_Submit_block_StringObj;
568     CRef<CSimpleTypeObject<string>> m_Current_Cit_sub_StringObj;
569     CConstRef<CSeqdesc> m_Current_Seqdesc;
570     CConstRef<CSeq_feat> m_Current_Seq_feat;
571     CConstRef<CPub> m_Current_Pub;
572     CConstRef<CPub_equiv> m_Current_Pub_equiv;
573     CConstRef<CSuspect_rule_set> m_ProductRules;
574     CConstRef<CSuspect_rule_set> m_OrganelleProductRules;
575     string m_SuspectRules;
576     vector<const CSeq_feat*> m_FeatAll;
577     vector<const CSeq_feat*> m_FeatGenes;
578     vector<const CSeq_feat*> m_FeatPseudo;
579     vector<const CSeq_feat*> m_FeatCDS;
580     vector<const CSeq_feat*> m_FeatMRNAs;
581     vector<const CSeq_feat*> m_FeatRRNAs;
582     vector<const CSeq_feat*> m_FeatTRNAs;
583     vector<const CSeq_feat*> m_Feat_RNAs;  // other RNA
584     vector<const CSeq_feat*> m_FeatExons;
585     vector<const CSeq_feat*> m_FeatIntrons;
586     vector<const CSeq_feat*> m_FeatMisc;
587     map<const CRefNode*, CParseNode*> m_NodeMap;
588     vector<CDiscrepancyObject*>* m_Fixes;
589 
590     CParseNode* FindLocalNode(const CParseNode& node, const CSeq_feat& feat) const;
591     CParseNode* FindNode(const CObject* obj) const;
592     CParseNode* FindNode(const CSeq_feat& feat) const;
593     CParseNode* FindNode(const CSeqdesc& desc) const;
InNucProtSet(const CParseNode * node)594     static bool InNucProtSet(const CParseNode* node) { for (; node; node = node->m_Parent) if (node->m_Type == eSeqSet_NucProt) return true; return false; }
InGenProdSet(const CParseNode * node)595     static bool InGenProdSet(const CParseNode* node) { for (; node; node = node->m_Parent) if (node->m_Type == eSeqSet_GenProd) return true; return false; }
596     bool CanFix();
597     bool CanFixBioseq_set();
598     bool CanFixBioseq();
599     bool CanFixSeq_annot();
600     bool CanFixSeqdesc();
601     bool CanFixSubmit_block();
602     bool CanFixBioseq(CRefNode& refnode);
603     bool CanFixBioseq_set(CRefNode& refnode);
604     bool CanFixFeat(CRefNode& refnode);
605     bool CanFixDesc(CRefNode& refnode);
606     bool CanFixSubmit_block(CRefNode& refnode);
607     void AutofixBioseq();
608     void AutofixBioseq_set();
609     void AutofixSeq_annot();
610     void AutofixSeq_descr();
611     void AutofixSubmit_block();
612     CRef<CBioseq_set> m_AF_Bioseq_set;
613     CRef<CBioseq> m_AF_Bioseq;
614     CRef<CSeq_annot> m_AF_Seq_annot;
615     CRef<CSeq_descr> m_AF_Seq_descr;
616     CRef<CSubmit_block> m_AF_Submit_block;
617 
618     CRef<CDiscrepancyGroup> m_Order;
619     const CDiscrepancyGroup& x_OutputOrder();
620 
621     //map<const CSerialObject*, CConstRef<CReportObjectData>> m_DataMap;
622 
623     // GENE_PRODUCT_CONFLICT
624     TGeneLocusMap m_GeneLocusMap;
625 
626 #define ADD_DISCREPANCY_TYPE(type) bool m_Enable_##type{ false }; vector<CDiscrepancyVisitor<type>*> m_All_##type;
627     //ADD_DISCREPANCY_TYPE(CSeq_inst)
628     //ADD_DISCREPANCY_TYPE(CSeqdesc)
629     //ADD_DISCREPANCY_TYPE(CSeq_feat)
630     //ADD_DISCREPANCY_TYPE(CSubmit_block)
631     //ADD_DISCREPANCY_TYPE(CSeqFeatData)
632     //ADD_DISCREPANCY_TYPE(CSeq_feat_BY_BIOSEQ)
633     //ADD_DISCREPANCY_TYPE(COverlappingFeatures)
634     //ADD_DISCREPANCY_TYPE(CBioSource)
635     //ADD_DISCREPANCY_TYPE(COrgName)
636     //ADD_DISCREPANCY_TYPE(CSeq_annot)
637     //ADD_DISCREPANCY_TYPE(CPubdesc)
638     //ADD_DISCREPANCY_TYPE(CAuth_list)
639     //ADD_DISCREPANCY_TYPE(CPerson_id)
640     ADD_DISCREPANCY_TYPE(string)
641 
642 /// BIG FILE
643 ADD_DISCREPANCY_TYPE(SEQUENCE)
644 ADD_DISCREPANCY_TYPE(SEQ_SET)
645 ADD_DISCREPANCY_TYPE(FEAT)
646 ADD_DISCREPANCY_TYPE(DESC)
647 ADD_DISCREPANCY_TYPE(BIOSRC)
648 ADD_DISCREPANCY_TYPE(PUBDESC)
649 ADD_DISCREPANCY_TYPE(AUTHORS)
650 ADD_DISCREPANCY_TYPE(SUBMIT)
651 ADD_DISCREPANCY_TYPE(STRING)
652 
653     mutable TReportItemList m_Group0;
654     mutable TReportItemList m_Group1;
655 
656 /// BIG FILE
657 friend class CReadHook_Bioseq_set;
658 friend class CReadHook_Bioseq_set_class;
659 friend class CReadHook_Bioseq;
660 friend class CCopyHook_Bioseq_set;
661 friend class CCopyHook_Bioseq;
662 friend class CCopyHook_Seq_descr;
663 friend class CCopyHook_Seq_annot;
664 friend class CCopyHook_Submit_block;
665 
666     enum EObjType {
667         eNone,
668         eFile,
669         eSubmit,
670         eSeqSet,
671         eSeqSet_NucProt,
672         eSeqSet_GenProd,
673         eSeqSet_SegSet,
674         eSeqSet_Genome,
675         eSeqSet_Funny,
676         eBioseq,
677         eSeqFeat,
678         eSeqDesc,
679         eSubmitBlock,
680         eString
681     };
682 
IsSeqSet(EObjType n)683     static bool IsSeqSet(EObjType n) {
684         switch (n) {
685             case eSeqSet:
686             case eSeqSet_NucProt:
687             case eSeqSet_GenProd:
688             case eSeqSet_SegSet:
689             case eSeqSet_Genome:
690             case eSeqSet_Funny:
691                 return true;
692             default:
693                 return false;
694         }
695     }
TypeName(EObjType n)696     static string TypeName(EObjType n) {
697         static const char* names[] =
698         {
699             "None",
700             "File",
701             "Submit",
702             "SeqSet",
703             "SeqSet_NucProt",
704             "SeqSet_GenProd",
705             "SeqSet_SegSet",
706             "SeqSet_Genome",
707             "SeqSet_Funny",
708             "Bioseq",
709             "SeqFeat",
710             "SeqDesc",
711             "SubmitBlock",
712             "String"
713         };
714         return names[n];
715     }
716 
717     struct CRefNode : public CObject
718     {
CRefNodeCDiscrepancyContext::CRefNode719         CRefNode(EObjType type, unsigned index) : m_Type(type), m_Index(index) {}
720 
721         EObjType m_Type;
722         size_t m_Index;
723         CRef<CRefNode> m_Parent;
724         mutable string m_Text;
725 
726         string GetText() const;
727         string GetBioseqLabel() const;
728         //bool operator<(const CRefNode&) const;
729     };
730 
731     struct CParseNode : public CObject
732     {
733         enum EInfo {
734             eIsPseudo = 1 << 0,
735             eKnownPseudo = 1 << 1,
736             eKnownGene = 1 << 2,
737             eKnownProduct = 1 << 3
738         };
739 
CParseNodeCDiscrepancyContext::CParseNode740         CParseNode(EObjType type, unsigned index, CParseNode* parent = nullptr) : m_Type(type), m_Index(index), m_Repeat(false), m_Info(0), m_Flags(0), m_Parent(parent) {
741             m_Ref.Reset(new CRefNode(type, index));
742             if (parent) {
743                 m_Ref->m_Parent.Reset(parent->m_Ref);
744             }
745         }
746 
AddDescriptorCDiscrepancyContext::CParseNode747         CParseNode& AddDescriptor(const CSeqdesc& seqdesc) {
748             CRef<CParseNode> new_node(new CParseNode(eSeqDesc, (unsigned)m_Descriptors.size(), this));
749             new_node->m_Obj = &seqdesc;
750             m_Descriptors.push_back(new_node);
751             m_DescriptorMap[&seqdesc] = new_node;
752             if (seqdesc.IsSource()) {
753                 const CBioSource* biosrc = &seqdesc.GetSource();
754                 m_Biosources.push_back(biosrc);
755                 m_BiosourceMap[biosrc] = new_node;
756             }
757             if (seqdesc.IsPub()) {
758                 const CPubdesc* pub = &seqdesc.GetPub();
759                 m_Pubdescs.push_back(pub);
760                 m_PubdescMap[pub] = new_node;
761                 if (pub->IsSetPub()) {
762                     for (auto& it : pub->GetPub().Get()) {
763                         if (it->IsSetAuthors()) {
764                             const CAuth_list* auth = &it->GetAuthors();
765                             m_Authors.push_back(auth);
766                             m_AuthorMap[auth] = new_node;
767                             m_AuthorPubMap[auth] = &*it;
768                         }
769                     }
770                 }
771             }
772             return *new_node;
773         }
774 
AddFeatureCDiscrepancyContext::CParseNode775         CParseNode& AddFeature(const CSeq_feat& feat) {
776             CRef<CParseNode> new_node(new CParseNode(eSeqFeat, (unsigned)m_Features.size(), this));
777             new_node->m_Obj = &feat;
778             m_Features.push_back(new_node);
779             m_FeatureMap[&feat] = new_node;
780             if (feat.IsSetData() && feat.GetData().IsBiosrc()) {
781                 const CBioSource* biosrc = &feat.GetData().GetBiosrc();
782                 m_Biosources.push_back(biosrc);
783                 m_BiosourceMap[biosrc] = new_node;
784             }
785             if (feat.IsSetData() && feat.GetData().IsPub()) {
786                 const CPubdesc* pub = &feat.GetData().GetPub();
787                 m_Pubdescs.push_back(pub);
788                 m_PubdescMap[pub] = new_node;
789                 if (pub->IsSetPub()) {
790                     for (auto& it : pub->GetPub().Get()) {
791                         if (it->IsSetAuthors()) {
792                             const CAuth_list* auth = &it->GetAuthors();
793                             m_Authors.push_back(auth);
794                             m_AuthorMap[auth] = new_node;
795                             m_AuthorPubMap[auth] = &*it;
796                         }
797                     }
798                 }
799             }
800             return *new_node;
801         }
802 
SetTypeCDiscrepancyContext::CParseNode803         void SetType(EObjType type) { m_Type = type; m_Ref->m_Type = type; }
804 
GetTitleCDiscrepancyContext::CParseNode805         CConstRef<CSeqdesc> GetTitle() const { return (m_Title || !m_Parent) ? m_Title : m_Parent->GetTitle(); }
GetMolinfoCDiscrepancyContext::CParseNode806         CConstRef<CSeqdesc> GetMolinfo() const { return (m_Molinfo || !m_Parent) ? m_Molinfo : m_Parent->GetMolinfo(); }
GetBiosourceCDiscrepancyContext::CParseNode807         CConstRef<CSeqdesc> GetBiosource() const { return (m_Biosource || !m_Parent) ? m_Biosource : m_Parent->GetBiosource(); }
InGenProdSetCDiscrepancyContext::CParseNode808         bool InGenProdSet() const { return m_Type == eSeqSet_GenProd ? true : m_Parent ? m_Parent->InGenProdSet() : false; }
809 
810         EObjType m_Type;
811         size_t m_Index;
812         bool m_Repeat;
813         mutable unsigned char m_Info;
814         unsigned char m_Flags;
815         CNcbiStreampos m_Pos;
816         CRef<CRefNode> m_Ref;
817         CConstRef<CObject> m_Obj;
818         CParseNode* m_Parent;
819         mutable const CParseNode* m_Gene;
820         mutable string m_Product;
821         vector<CRef<CParseNode>> m_Children;
822         vector<CRef<CParseNode>> m_Descriptors;
823         vector<CRef<CParseNode>> m_Features;
824         vector<const CBioSource*> m_Biosources;
825         vector<const CPubdesc*> m_Pubdescs;
826         vector<const CAuth_list*> m_Authors;
827         map<const CSeqdesc*, CParseNode*> m_DescriptorMap;
828         map<const CSeq_feat*, CParseNode*> m_FeatureMap;
829         map<const CBioSource*, CParseNode*> m_BiosourceMap;
830         map<const CPubdesc*, CParseNode*> m_PubdescMap;
831         map<const CAuth_list*, CParseNode*> m_AuthorMap;
832         map<const CAuth_list*, const CPub*> m_AuthorPubMap;
833         shared_ptr<CSeqSummary> m_BioseqSummary;
834         CConstRef<CSeqdesc> m_Title;
835         CConstRef<CSeqdesc> m_Molinfo;
836         CConstRef<CSeqdesc> m_Biosource;
837         vector<CConstRef<CSeqdesc>> m_SetBiosources;
838 
PathCDiscrepancyContext::CParseNode839 string Path() { return m_Parent ? m_Parent->Path() + " => " + TypeName(m_Type) + ": " + to_string(m_Index) : TypeName(m_Type) + ": " + to_string(m_Index); }
840     };
841 
842     bool Skip();
843     void Extend(CParseNode& node, CObjectIStream& stream);
844     void ParseAll(CParseNode& node);
845     void Populate(CParseNode& node);
846     void PopulateBioseq(CParseNode& node);
847     void PopulateSeqSet(CParseNode& node);
848     void PopulateSubmit(CParseNode& node);
849     void RunTests();
850 
851     void PushNode(EObjType);
PopNode()852     void PopNode() { m_CurrentNode.Reset(m_CurrentNode->m_Parent); }
853 
854     bool m_Skip;
855     CRef<CParseNode> m_RootNode;
856     CRef<CParseNode> m_CurrentNode;
857     bool IsPseudo(const CParseNode& node);
858     const CParseNode* GeneForFeature(const CParseNode& node);
859     string ProdForFeature(const CParseNode& node);
860     static bool CompareRefs(CRef<CReportObj> a, CRef<CReportObj> b);
861 
862 friend class CDiscrepancyObject;
863 };
864 
865 
866 class CDiscrepancyObject : public CReportObj
867 {
868 protected:
CDiscrepancyObject(CDiscrepancyContext::CRefNode * ref,CDiscrepancyContext::CRefNode * fix=nullptr,const CObject * more=nullptr)869     CDiscrepancyObject(CDiscrepancyContext::CRefNode* ref, CDiscrepancyContext::CRefNode* fix = nullptr, const CObject* more = nullptr) : m_Ref(ref), m_Fix(fix), m_More(more), m_Fixed(false) {}
870 
871 public:
GetText() const872     string GetText() const override { return m_Ref->GetText(); }
GetPath() const873     string GetPath() const override { for (auto ref = m_Ref; ref; ref = ref->m_Parent) if (ref->m_Type == CDiscrepancyContext::eFile) return ref->m_Text; return kEmptyStr; }
874     string GetFeatureType() const override;
875     string GetProductName() const override;
876     string GetLocation() const override;
877     string GetLocusTag() const override;
GetShort() const878     string GetShort() const override { return m_Ref->GetBioseqLabel(); }
SetMoreInfo(CObject * data)879     void SetMoreInfo(CObject* data) override { m_More.Reset(data); }
880 
GetType() const881     EType GetType() const override // Can we use the same enum?
882     {
883         //eType_feature,
884         //eType_descriptor,
885         //eType_sequence,
886         //eType_seq_set,
887         //eType_submit_block,
888         //eType_string
889 
890         switch (m_Ref->m_Type) {
891             case CDiscrepancyContext::eSeqSet: return eType_seq_set;
892             case CDiscrepancyContext::eBioseq: return eType_sequence;
893             case CDiscrepancyContext::eSeqFeat: return eType_feature;
894             case CDiscrepancyContext::eSeqDesc: return eType_descriptor;
895             case CDiscrepancyContext::eSubmitBlock: return eType_submit_block;
896             case CDiscrepancyContext::eString: return eType_string;
897             default: break;
898         }
899         return eType_string;
900     }
901 
CanAutofix() const902     bool CanAutofix() const override { return m_Fix && !m_Fixed; }
IsFixed() const903     bool IsFixed() const override { return m_Fixed; }
SetFixed()904     void SetFixed() { m_Fixed = true; }
GetMoreInfo()905     CConstRef<CObject> GetMoreInfo() { return m_More; }
906     CReportObj* Clone(bool fix, CConstRef<CObject> data) const;
907 
908     static string GetTextObjectDescription(const CSeq_feat& seq_feat, CScope& scope);
909     static string GetTextObjectDescription(const CSeq_feat& seq_feat, CScope& scope, const string& product);
910     static string GetTextObjectDescription(const CSeqdesc& sd);
911     static string GetTextObjectDescription(const CBioseq& bs, CScope& scope);
912     static string GetTextObjectDescription(CBioseq_set_Handle bssh);
913     static void GetTextObjectDescription(const CSeq_feat& seq_feat, CScope& scope, string &type, string &context, string &location, string &locus_tag);
914     static void GetTextObjectDescription(const CSeq_feat& seq_feat, CScope& scope, string &type, string &location, string &locus_tag);
915 
916 protected:
917     CRef<CDiscrepancyCase> m_Case;
918     CRef<CDiscrepancyContext::CRefNode> m_Ref;
919     CRef<CDiscrepancyContext::CRefNode> m_Fix;
920     CConstRef<CObject> m_More;
921     bool m_Fixed;
922     friend class CDiscrepancyContext;
923     friend class CReportNode;
924     friend class CReportItem;
operator <(const CReportObjPtr & one,const CReportObjPtr & another)925     friend bool operator<(const CReportObjPtr& one, const CReportObjPtr& another) { return ((const CDiscrepancyObject*)one.P)->m_Ref < ((const CDiscrepancyObject*)another.P)->m_Ref; }
926 };
927 
928 
GetMore(CReportObj & obj)929 inline const CObject* CDiscrepancyContext::GetMore(CReportObj& obj) { return static_cast<CDiscrepancyObject*>(&obj)->m_More; }
930 
931 // MACRO definitions
932 
933 // The following two macros are required to make sure all modules get loaded from the library
934 // Use this in discrepancy_core.cpp when adding a new module
935 #define DISCREPANCY_LINK_MODULE(name) \
936     struct CDiscrepancyModule_##name { static void* dummy; CDiscrepancyModule_##name(){ dummy=nullptr; } };         \
937     static CDiscrepancyModule_##name module_##name
938 
939 // Use this in the new module
940 #define DISCREPANCY_MODULE(name) \
941     struct CDiscrepancyModule_##name { static void* dummy; CDiscrepancyModule_##name(){ dummy=nullptr; } };         \
942     void* CDiscrepancyModule_##name::dummy=nullptr
943 
944 
945 #define DISCREPANCY_CASE(name, type, group, descr, ...) \
946     class CDiscrepancyCase_##name : public CDiscrepancyVisitor<type>                                                \
947     {                                                                                                               \
948     public:                                                                                                         \
949         void Visit(const type&, CDiscrepancyContext&) override;                                                     \
950         void Summarize(CDiscrepancyContext&) override;                                                              \
951         string GetName() const override { return #name; }                                                           \
952         string GetType() const override { return #type; }                                                           \
953     protected:                                                                                                      \
954         __VA_ARGS__;                                                                                                \
955     };                                                                                                              \
956     static const char* descr_for_##name = descr;                                                                    \
957     static TGroup group_for_##name = group;                                                                         \
958     class CDiscrepancyConstructor_##name : public CDiscrepancyConstructor                                           \
959     {                                                                                                               \
960     public:                                                                                                         \
961         CDiscrepancyConstructor_##name(){ Register(#name, descr_for_##name, group_for_##name, *this); }             \
962     protected:                                                                                                      \
963         CRef<CDiscrepancyCase> Create() const { return CRef<CDiscrepancyCase>(new CDiscrepancyCase_##name); }       \
964     };                                                                                                              \
965     static CDiscrepancyConstructor_##name DiscrepancyConstructor_##name;                                            \
966     void CDiscrepancyCase_##name::Visit(const type& obj, CDiscrepancyContext& context)
967 
968 
969 #define DISCREPANCY_SUMMARIZE(name) \
970     void CDiscrepancyCase_##name::Summarize(CDiscrepancyContext& context)
971 
972 
973 #define DISCREPANCY_AUTOFIX(name) \
974     class CDiscrepancyCaseA_##name : public CDiscrepancyCase_##name                                                 \
975     {                                                                                                               \
976     public:                                                                                                         \
977         CDiscrepancyCaseA_##name() {}                                                                               \
978         CRef<CAutofixReport> Autofix(CDiscrepancyObject* obj, CDiscrepancyContext& context) const;                  \
979     };                                                                                                              \
980     class CDiscrepancyCaseAConstructor_##name : public CDiscrepancyConstructor                                      \
981     {                                                                                                               \
982     public:                                                                                                         \
983         CDiscrepancyCaseAConstructor_##name(){ Register(#name, descr_for_##name, group_for_##name | eAutofix, *this); }     \
984     protected:                                                                                                      \
985         CRef<CDiscrepancyCase> Create() const { return CRef<CDiscrepancyCase>(new CDiscrepancyCaseA_##name); }      \
986     };                                                                                                              \
987     static CDiscrepancyCaseAConstructor_##name DiscrepancyCaseAConstructor_##name;                                  \
988     CRef<CAutofixReport> CDiscrepancyCaseA_##name::Autofix(CDiscrepancyObject* obj, CDiscrepancyContext& context) const
989 
990 
991 #define DISCREPANCY_ALIAS(name, alias) \
992     class CDiscrepancyCase_##alias { void* name; }; /* prevent name conflicts */                                    \
993     class CDiscrepancyAlias_##alias : public CDiscrepancyAlias                                                      \
994     {                                                                                                               \
995     public:                                                                                                         \
996         CDiscrepancyAlias_##alias() { Register(#name, #alias); }                                                    \
997     };                                                                                                              \
998     static CDiscrepancyAlias_##alias DiscrepancyAlias_##alias;
999 
1000 
1001 // Unit test functions
1002 NCBI_DISCREPANCY_EXPORT void UnitTest_FLATFILE_FIND();
1003 
1004 
1005 END_SCOPE(NDiscrepancy)
1006 END_NCBI_SCOPE
1007 
1008 #endif  // _MISC_DISCREPANCY_DISCREPANCY_CORE_H_
1009