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