validatorp.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:77k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: validatorp.cpp,v $
  4.  * PRODUCTION Revision 1000.3  2004/06/01 19:47:39  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.52
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: validatorp.cpp,v 1000.3 2004/06/01 19:47:39 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software/database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's official duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software/database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Author:  Jonathan Kans, Clifford Clausen, Aaron Ucko, Mati Shomrat, ....
  35.  *
  36.  * File Description:
  37.  *   Implementation of private parts of the validator
  38.  *   .......
  39.  *
  40.  */
  41. #include <ncbi_pch.hpp>
  42. #include <corelib/ncbistd.hpp>
  43. #include <corelib/ncbistr.hpp>
  44. #include <objmgr/object_manager.hpp>
  45. #include "validatorp.hpp"
  46. #include "utilities.hpp"
  47. #include <serial/iterator.hpp>
  48. #include <serial/enumvalues.hpp>
  49. #include <objects/general/Dbtag.hpp>
  50. #include <objects/general/Person_id.hpp>
  51. #include <objects/general/Name_std.hpp>
  52. #include <objects/seqalign/Seq_align.hpp>
  53. #include <objects/seqset/Bioseq_set.hpp>
  54. #include <objects/seqset/Seq_entry.hpp>
  55. #include <objects/seq/Bioseq.hpp>
  56. #include <objects/seq/Seq_annot.hpp>
  57. #include <objects/seq/Seqdesc.hpp>
  58. #include <objects/seq/Seq_descr.hpp>
  59. #include <objects/seq/Pubdesc.hpp>
  60. #include <objects/seqfeat/BioSource.hpp>
  61. #include <objects/seqfeat/OrgMod.hpp>
  62. #include <objects/seqfeat/OrgName.hpp>
  63. #include <objects/seqfeat/Org_ref.hpp>
  64. #include <objects/seqfeat/Seq_feat.hpp>
  65. #include <objects/seqfeat/SubSource.hpp>
  66. #include <objects/seqloc/Seq_loc.hpp>
  67. #include <objects/seqloc/Seq_interval.hpp>
  68. #include <objects/seqloc/Seq_point.hpp>
  69. #include <objects/seqloc/Textseq_id.hpp>
  70. #include <objects/seqres/Seq_graph.hpp>
  71. #include <objects/submit/Seq_submit.hpp>
  72. #include <objects/submit/Submit_block.hpp>
  73. #include <objmgr/util/feature.hpp>
  74. #include <objmgr/util/sequence.hpp>
  75. #include <objmgr/feat_ci.hpp>
  76. #include <objmgr/seq_vector.hpp>
  77. #include <objmgr/scope.hpp>
  78. #include <objects/pub/Pub.hpp>
  79. #include <objects/pub/Pub_equiv.hpp>
  80. #include <objects/biblio/Author.hpp>
  81. #include <objects/biblio/Auth_list.hpp>
  82. #include <objects/biblio/Cit_art.hpp>
  83. #include <objects/biblio/Cit_book.hpp>
  84. #include <objects/biblio/Cit_gen.hpp>
  85. #include <objects/biblio/Cit_jour.hpp>
  86. #include <objects/biblio/Cit_let.hpp>
  87. #include <objects/biblio/Cit_proc.hpp>
  88. #include <objects/biblio/Cit_sub.hpp>
  89. #include <objects/biblio/PubMedId.hpp>
  90. #include <objects/biblio/PubStatus.hpp>
  91. #include <objects/biblio/Title.hpp>
  92. #include <objects/biblio/Imprint.hpp>
  93. #include <objects/biblio/Affil.hpp>
  94. #include <algorithm>
  95. BEGIN_NCBI_SCOPE
  96. BEGIN_SCOPE(objects)
  97. BEGIN_SCOPE(validator)
  98. using namespace sequence;
  99. auto_ptr<CTextFsa> CValidError_imp::m_SourceQualTags;
  100. // =============================================================================
  101. //                            CValidError_imp Public
  102. // =============================================================================
  103. // Constructor
  104. CValidError_imp::CValidError_imp
  105. (CObjectManager& objmgr, 
  106.  CValidError*       errs,
  107.  Uint4              options) :
  108.       m_ObjMgr(&objmgr),
  109.       m_Scope(0),
  110.       m_TSE(0),
  111.       m_ErrRepository(errs),
  112.       m_NonASCII((options & CValidator::eVal_non_ascii) != 0),
  113.       m_SuppressContext((options & CValidator::eVal_no_context) != 0),
  114.       m_ValidateAlignments((options & CValidator::eVal_val_align) != 0),
  115.       m_ValidateExons((options & CValidator::eVal_val_exons) != 0),
  116.       m_SpliceErr((options & CValidator::eVal_splice_err) != 0),
  117.       m_OvlPepErr((options & CValidator::eVal_ovl_pep_err) != 0),
  118.       m_RequireTaxonID((options & CValidator::eVal_need_taxid) != 0),
  119.       m_RequireISOJTA((options & CValidator::eVal_need_isojta) != 0),
  120.       m_ValidateIdSet((options & CValidator::eVal_validate_id_set) != 0),
  121.       m_RemoteFetch((options & CValidator::eVal_remote_fetch) != 0),
  122.       m_PerfBottlenecks((options & CValidator::eVal_perf_bottlenecks) != 0),
  123.       m_IsStandaloneAnnot(false),
  124.       m_NoPubs(false),
  125.       m_NoBioSource(false),
  126.       m_IsGPS(false),
  127.       m_IsGED(false),
  128.       m_IsPDB(false),
  129.       m_IsTPA(false),
  130.       m_IsPatent(false),
  131.       m_IsRefSeq(false),
  132.       m_IsNC(false),
  133.       m_IsNG(false),
  134.       m_IsNM(false),
  135.       m_IsNP(false),
  136.       m_IsNR(false),
  137.       m_IsNS(false),
  138.       m_IsNT(false),
  139.       m_IsNW(false),
  140.       m_IsXR(false),
  141.       m_IsGI(false),
  142.       m_PrgCallback(0),
  143.       m_NumAlign(0),
  144.       m_NumAnnot(0),
  145.       m_NumBioseq(0),
  146.       m_NumBioseq_set(0),
  147.       m_NumDesc(0),
  148.       m_NumDescr(0),
  149.       m_NumFeat(0),
  150.       m_NumGraph(0)
  151. {
  152.     if ( m_SourceQualTags.get() == 0 ) {
  153.         InitializeSourceQualTags();
  154.     }
  155. }
  156. // Destructor
  157. CValidError_imp::~CValidError_imp()
  158. {
  159. }
  160. // Error post methods
  161. void CValidError_imp::PostErr
  162. (EDiagSev sv,
  163.  EErrType et,
  164.  const string&  msg,
  165.  const CSerialObject& obj)
  166. {
  167.     const CSeqdesc* desc = dynamic_cast < const CSeqdesc* > (&obj);
  168.     if (desc != 0) {
  169.         PostErr (sv, et, msg, *desc);
  170.         return;
  171.     }
  172.     const CSeq_feat* feat = dynamic_cast < const CSeq_feat* > (&obj);
  173.     if (feat != 0) {
  174.         PostErr (sv, et, msg, *feat);
  175.         return;
  176.     }
  177.     const CBioseq* seq = dynamic_cast < const CBioseq* > (&obj);
  178.     if (seq != 0) {
  179.         PostErr (sv, et, msg, *seq);
  180.         return;
  181.     }
  182.     const CBioseq_set* set = dynamic_cast < const CBioseq_set* > (&obj);
  183.     if (set != 0) {
  184.         PostErr (sv, et, msg, *set);
  185.         return;
  186.     }
  187.     const CSeq_annot* annot = dynamic_cast < const CSeq_annot* > (&obj);
  188.     if (annot != 0) {
  189.         PostErr (sv, et, msg, *annot);
  190.         return;
  191.     }
  192.     const CSeq_graph* graph = dynamic_cast < const CSeq_graph* > (&obj);
  193.     if (graph != 0) {
  194.         PostErr (sv, et, msg, *graph);
  195.         return;
  196.     }
  197.     const CSeq_align* align = dynamic_cast < const CSeq_align* > (&obj);
  198.     if (align != 0) {
  199.         PostErr (sv, et, msg, *align);
  200.         return;
  201.     }
  202.     const CSeq_entry* entry = dynamic_cast < const CSeq_entry* > (&obj);
  203.     if (entry != 0) {
  204.         PostErr (sv, et, msg, *entry);
  205.         return;
  206.     }
  207. }
  208. void CValidError_imp::PostErr
  209. (EDiagSev sv,
  210.  EErrType et,
  211.  const string&   message,
  212.  TDesc    ds)
  213. {
  214.     // Append Descriptor label
  215.     string msg(message + " DESCRIPTOR: ");
  216.     ds.GetLabel (&msg, CSeqdesc::eBoth);
  217.     m_ErrRepository->AddValidErrItem(new CValidErrItem(sv, et, msg, ds));
  218. }
  219. void CValidError_imp::PostErr
  220. (EDiagSev sv,
  221.  EErrType et,
  222.  const string&   message,
  223.  TFeat    ft)
  224. {
  225.     // Add feature part of label
  226.     string msg(message + " FEATURE: ");
  227.     feature::GetLabel(ft, &msg, feature::eBoth, m_Scope);
  228.     // Add feature location part of label
  229.     string loc_label;
  230.     if (m_SuppressContext) {
  231.         CSeq_loc loc;
  232.         loc.Assign(ft.GetLocation());
  233.         ChangeSeqLocId(&loc, false, m_Scope.GetPointer());
  234.         loc.GetLabel(&loc_label);
  235.     } else {
  236.         ft.GetLocation().GetLabel(&loc_label);
  237.     }
  238.     if (loc_label.size() > 800) {
  239.         loc_label = loc_label.substr(0, 797) + "...";
  240.     }
  241.     if (!loc_label.empty()) {
  242.         loc_label = string("[") + loc_label + "]";
  243.         msg += loc_label;
  244.     }
  245.     // Append label for bioseq of feature location
  246.     if (!m_SuppressContext) {
  247.         try {
  248.             CBioseq_Handle hnd = m_Scope->GetBioseqHandle(ft.GetLocation());
  249.             if( hnd ) {
  250.                 CBioseq_Handle::TBioseqCore bc = hnd.GetBioseqCore();
  251.                 msg += "[";
  252.                 bc->GetLabel(&msg, CBioseq::eBoth);
  253.                 msg += "]";
  254.             }
  255.         } catch (...){
  256.         };
  257.     }
  258.     // Append label for product of feature
  259.     loc_label.erase();
  260.     if (ft.IsSetProduct()) {
  261.         if (m_SuppressContext) {
  262.             CSeq_loc loc;
  263.             loc.Assign(ft.GetProduct());
  264.             ChangeSeqLocId(&loc, false, m_Scope.GetPointer());
  265.             loc.GetLabel(&loc_label);
  266.         } else {
  267.             ft.GetProduct().GetLabel(&loc_label);
  268.         }
  269.         if (loc_label.size() > 800) {
  270.             loc_label = loc_label.substr(0, 797) + "...";
  271.         }
  272.         if (!loc_label.empty()) {
  273.             loc_label = string("[") + loc_label + "]";
  274.             msg += loc_label;
  275.         }
  276.     }
  277.     m_ErrRepository->AddValidErrItem(new CValidErrItem(sv, et, msg, ft));
  278. }
  279. void CValidError_imp::PostErr
  280. (EDiagSev sv,
  281.  EErrType et,
  282.  const string&   message,
  283.  TBioseq  sq)
  284. {
  285.     // Append bioseq label
  286.     string msg(message + " BIOSEQ: ");
  287.     if (m_SuppressContext) {
  288.         sq.GetLabel(&msg, CBioseq::eContent, true);
  289.     } else {
  290.         sq.GetLabel(&msg, CBioseq::eBoth, false);
  291.     }
  292.     m_ErrRepository->AddValidErrItem(new CValidErrItem(sv, et, msg, sq));
  293. }
  294. void CValidError_imp::PostErr
  295. (EDiagSev sv,
  296.  EErrType et,
  297.  const string&   message,
  298.  TBioseq  sq,
  299.  TDesc    ds)
  300. {
  301.     // Append Descriptor label
  302.     string msg(message + " DESCRIPTOR: ");
  303.     ds.GetLabel(&msg, CSeqdesc::eBoth);
  304.     PostErr(sv, et, msg, sq);
  305. }
  306. void CValidError_imp::PostErr
  307. (EDiagSev      sv,
  308.  EErrType      et,
  309.  const string& message,
  310.  TSet          set)
  311. {
  312.     // Append Bioseq_set label
  313.     string msg(message + " BIOSEQ-SET: ");
  314.     if (m_SuppressContext) {
  315.         set.GetLabel(&msg, CBioseq_set::eContent);
  316.     } else {
  317.         set.GetLabel(&msg, CBioseq_set::eBoth);
  318.     }
  319.     m_ErrRepository->AddValidErrItem(new CValidErrItem(sv, et, msg, set));
  320. }
  321. void CValidError_imp::PostErr
  322. (EDiagSev        sv,
  323.  EErrType        et,
  324.  const string&   message,
  325.  TSet            set,
  326.  TDesc           ds)
  327. {
  328.     // Append Descriptor label
  329.     string msg(message + " DESCRIPTOR: ");
  330.     ds.GetLabel(&msg, CSeqdesc::eBoth);
  331.     PostErr(sv, et, msg, set);
  332. }
  333. void CValidError_imp::PostErr
  334. (EDiagSev sv,
  335.  EErrType et,
  336.  const string&   message,
  337.  TAnnot    an)
  338. {
  339.     // Append Annotation label
  340.     string msg(message + " ANNOTATION: ");
  341.     // !!! need to decide on the message
  342.     m_ErrRepository->AddValidErrItem(new CValidErrItem(sv, et, msg, an));
  343. }
  344. void CValidError_imp::PostErr
  345. (EDiagSev sv,
  346.  EErrType et,
  347.  const string& message,
  348.  TGraph graph)
  349. {
  350.     // Append Graph label
  351.     string msg(message + " GRAPH: ");
  352.     if ( graph.IsSetTitle() ) {
  353.         msg += graph.GetTitle();
  354.     } else {
  355.         msg += "Not Named";
  356.     }
  357.     msg += " ";
  358.     graph.GetLoc().GetLabel(&msg);
  359.     m_ErrRepository->AddValidErrItem(new CValidErrItem(sv, et, msg, graph));
  360. }
  361. void CValidError_imp::PostErr
  362. (EDiagSev sv,
  363.  EErrType et,
  364.  const string& message,
  365.  TBioseq sq,
  366.  TGraph graph)
  367. {
  368.     // Append Graph label
  369.     string msg(message + " GRAPH: ");
  370.     if ( graph.IsSetTitle() ) {
  371.         msg += graph.GetTitle();
  372.     } else {
  373.         msg += "Not Named";
  374.     }
  375.     msg += " ";
  376.     graph.GetLoc().GetLabel(&msg);
  377.     PostErr(sv, et, msg, sq);
  378. }
  379. void CValidError_imp::PostErr
  380. (EDiagSev sv,
  381.  EErrType et,
  382.  const string& message,
  383.  TAlign align)
  384. {
  385.     // Append Alignment label
  386.     string msg(message + " ALIGNMENT: ");
  387.     msg += align.ENUM_METHOD_NAME(EType)()->FindName(align.GetType(), true);
  388.     msg += ", dim=" + NStr::IntToString(align.GetDim());
  389.     msg+= " SEGS: ";
  390.     msg += align.GetSegs().SelectionName(align.GetSegs().Which());
  391.     m_ErrRepository->AddValidErrItem(new CValidErrItem(sv, et, msg, align));
  392. }
  393. void CValidError_imp::PostErr
  394. (EDiagSev sv,
  395.  EErrType et,
  396.  const string& message,
  397.  TEntry entry)
  398. {
  399.     m_ErrRepository->AddValidErrItem(new CValidErrItem(sv, et, message, entry));
  400. }
  401. bool CValidError_imp::Validate
  402. (const CSeq_entry& se,
  403.  const CCit_sub* cs,
  404.  CScope* scope)
  405. {
  406.     if ( m_PrgCallback ) {
  407.         m_PrgInfo.m_State = CValidator::CProgressInfo::eState_Initializing;
  408.         if ( m_PrgCallback(&m_PrgInfo) ) {
  409.             return false;
  410.         }
  411.     }
  412.     // Check that CSeq_entry has data
  413.     if (se.Which() == CSeq_entry::e_not_set) {
  414.         ERR_POST(Warning << "Seq_entry not set");
  415.         return false;
  416.     }
  417.     // Get first CBioseq object pointer for PostErr below.
  418.     CTypeConstIterator<CBioseq> seq(ConstBegin(se));
  419.     if (!seq) {
  420.         ERR_POST("No Bioseq anywhere on this Seq-entry");
  421.         return false;
  422.     }
  423.     Setup(se, scope);
  424.  
  425.     // If m_NonASCII is true, then this flag was set by the caller
  426.     // of validate to indicate that a non ascii character had been
  427.     // read from a file being used to create a CSeq_entry, that the
  428.     // error had been corrected, but that the error needs to be reported
  429.     // by Validate. Note, Validate is not doing anything other than
  430.     // reporting an error if m_NonASCII is true;
  431.     if (m_NonASCII) {
  432.         PostErr(eDiag_Critical, eErr_GENERIC_NonAsciiAsn,
  433.                   "Non-ascii chars in input ASN.1 strings", *seq);
  434.         // Only report the error once
  435.         m_NonASCII = false;
  436.     }
  437.     // Iterate thru components of record and validate each
  438.     // Features:
  439.     if ( m_PrgCallback ) {
  440.         m_PrgInfo.m_State = CValidator::CProgressInfo::eState_Feat;
  441.         m_PrgInfo.m_Current = m_NumFeat;
  442.         m_PrgInfo.m_CurrentDone = 0;
  443.         if ( m_PrgCallback(&m_PrgInfo) ) {
  444.             return false;
  445.         }
  446.     }
  447.     CValidError_feat feat_validator(*this);
  448.     for (CTypeConstIterator<CSeq_feat> fi(se); fi; ++fi) {
  449.         try {
  450.             feat_validator.ValidateSeqFeat(*fi);
  451.             if ( m_PrgCallback ) {
  452.                 m_PrgInfo.m_CurrentDone++;
  453.                 m_PrgInfo.m_TotalDone++;
  454.                 if ( m_PrgCallback(&m_PrgInfo) ) {
  455.                     return false;
  456.                 }
  457.             }
  458.         } catch ( const exception& e ) {
  459.         PostErr(eDiag_Fatal, eErr_Internal_Exception,
  460.             string("Exeption while validating feature. EXCEPTION: ") +
  461.                 e.what(), *fi);
  462.             return true;
  463.         }
  464.     }
  465.     if ( feat_validator.GetNumGenes() == 0  &&  
  466.          feat_validator.GetNumGeneXrefs() > 0 ) {
  467.         PostErr(eDiag_Warning, eErr_SEQ_FEAT_OnlyGeneXrefs,
  468.             "There are " + NStr::IntToString(feat_validator.GetNumGeneXrefs()) +
  469.             " gene xrefs and no gene features in this record.", se);
  470.     }
  471.     // Descriptors:
  472.     if ( m_PrgCallback ) {
  473.         m_PrgInfo.m_State = CValidator::CProgressInfo::eState_Desc;
  474.         m_PrgInfo.m_Current = m_NumDesc;
  475.         m_PrgInfo.m_CurrentDone = 0;
  476.         m_PrgCallback(&m_PrgInfo);
  477.     }
  478.     CValidError_desc desc_validator(*this);
  479.     for (CTypeConstIterator<CSeqdesc> di(se); di; ++di) {
  480.         try {
  481.             desc_validator.ValidateSeqDesc(*di);
  482.             if ( m_PrgCallback ) {
  483.                 m_PrgInfo.m_CurrentDone++;
  484.                 m_PrgInfo.m_TotalDone++;
  485.                 if ( m_PrgCallback(&m_PrgInfo) ) {
  486.                     return false;
  487.                 }
  488.             }
  489.         } catch ( const exception& e ) {
  490.         PostErr(eDiag_Fatal, eErr_Internal_Exception,
  491.             string("Exeption while validating descriptor. EXCEPTION: ") +
  492.                 e.what(), *di);
  493.             return true;
  494.         }
  495.     }
  496.     
  497.     // Bioseqs:
  498.     if ( m_PrgCallback ) {
  499.         m_PrgInfo.m_State = CValidator::CProgressInfo::eState_Bioseq;
  500.         m_PrgInfo.m_Current = m_NumBioseq;
  501.         m_PrgInfo.m_CurrentDone = 0;
  502.         m_PrgCallback(&m_PrgInfo);
  503.     }
  504.     CValidError_bioseq bioseq_validator(*this);
  505.     for (CTypeConstIterator<CBioseq> bi(se); bi; ++bi) {
  506.         try {
  507.             bioseq_validator.ValidateSeqIds(*bi);
  508.             bioseq_validator.ValidateInst(*bi);
  509.             bioseq_validator.ValidateBioseqContext(*bi);
  510.             bioseq_validator.ValidateHistory(*bi);
  511.             if ( m_PrgCallback ) {
  512.                 m_PrgInfo.m_CurrentDone++;
  513.                 m_PrgInfo.m_TotalDone++;
  514.                 if ( m_PrgCallback(&m_PrgInfo) ) {
  515.                     return false;
  516.                 }
  517.             }
  518.         } catch ( const exception& e ) {
  519.         PostErr(eDiag_Fatal, eErr_Internal_Exception,
  520.             string("Exeption while validating bioseq. EXCEPTION: ") +
  521.                 e.what(), *bi);
  522.             return true;
  523.         }
  524.     }
  525.     if ( bioseq_validator.GetTpaWithHistory() > 0  &&
  526.          bioseq_validator.GetTpaWithoutHistory() > 0 ) {
  527.         PostErr(eDiag_Error, eErr_SEQ_INST_TpaAssmeblyProblem,
  528.             "There are " +
  529.             NStr::IntToString(bioseq_validator.GetTpaWithHistory()) +
  530.             " TPAs with history and " + 
  531.             NStr::IntToString(bioseq_validator.GetTpaWithoutHistory()) +
  532.             " without history in this record.", se);
  533.     }
  534.     // Bioseq sets:
  535.     if ( m_PrgCallback ) {
  536.         m_PrgInfo.m_State = CValidator::CProgressInfo::eState_Bioseq_set;
  537.         m_PrgInfo.m_Current = m_NumBioseq_set;
  538.         m_PrgInfo.m_CurrentDone = 0;
  539.         m_PrgCallback(&m_PrgInfo);
  540.     }
  541.     CValidError_bioseqset bioseqset_validator(*this);
  542.     for (CTypeConstIterator<CBioseq_set> si(se); si; ++si) {
  543.         try {
  544.             bioseqset_validator.ValidateBioseqSet(*si);
  545.             if ( m_PrgCallback ) {
  546.                 m_PrgInfo.m_CurrentDone++;
  547.                 m_PrgInfo.m_TotalDone++;
  548.                 if ( m_PrgCallback(&m_PrgInfo) ) {
  549.                     return false;
  550.                 }
  551.             }
  552.         } catch ( const exception& e ) {
  553.         PostErr(eDiag_Fatal, eErr_Internal_Exception,
  554.             string("Exeption while validating bioseq set. EXCEPTION: ") +
  555.                 e.what(), *si);
  556.             return true;
  557.         }
  558.     }
  559.     // Alignments:
  560.     if ( m_PrgCallback ) {
  561.         m_PrgInfo.m_State = CValidator::CProgressInfo::eState_Align;
  562.         m_PrgInfo.m_Current = m_NumAlign;
  563.         m_PrgInfo.m_CurrentDone = 0;
  564.         m_PrgCallback(&m_PrgInfo);
  565.     }
  566.     CValidError_align align_validator(*this);
  567.     for (CTypeConstIterator<CSeq_align> ai(se); ai; ++ai) {
  568.         try {
  569.             align_validator.ValidateSeqAlign(*ai);
  570.             if ( m_PrgCallback ) {
  571.                 m_PrgInfo.m_CurrentDone++;
  572.                 m_PrgInfo.m_TotalDone++;
  573.                 if ( m_PrgCallback(&m_PrgInfo) ) {
  574.                     return false;
  575.                 }
  576.             }
  577.         } catch ( const exception& e ) {
  578.         PostErr(eDiag_Fatal, eErr_Internal_Exception,
  579.             string("Exeption while validating alignment. EXCEPTION: ") +
  580.                 e.what(), *ai);
  581.             return true;
  582.         }
  583.     }
  584.     // Graphs:
  585.     if ( m_PrgCallback ) {
  586.         m_PrgInfo.m_State = CValidator::CProgressInfo::eState_Graph;
  587.         m_PrgInfo.m_Current = m_NumGraph;
  588.         m_PrgInfo.m_CurrentDone = 0;
  589.         m_PrgCallback(&m_PrgInfo);
  590.     }
  591.     CValidError_graph graph_validator(*this);
  592.     for (CTypeConstIterator<CSeq_graph> gi(se); gi; ++gi) {
  593.         try {
  594.             graph_validator.ValidateSeqGraph(*gi);
  595.             if ( m_PrgCallback ) {
  596.                 m_PrgInfo.m_CurrentDone++;
  597.                 m_PrgInfo.m_TotalDone++;
  598.                 if ( m_PrgCallback(&m_PrgInfo) ) {
  599.                     return false;
  600.                 }
  601.             }
  602.         } catch ( const exception& e ) {
  603.         PostErr(eDiag_Fatal, eErr_Internal_Exception,
  604.             string("Exeption while validating graph. EXCEPTION: ") +
  605.                 e.what(), *gi);
  606.             return true;
  607.         }
  608.     }
  609.     SIZE_TYPE misplaced = graph_validator.GetNumMisplacedGraphs();
  610.     if ( misplaced > 0 ) {
  611.         string num = NStr::IntToString(misplaced);
  612.         PostErr(eDiag_Critical, eErr_SEQ_PKG_GraphPackagingProblem,
  613.             string("There ") + ((misplaced > 1) ? "are" : "is") + num + 
  614.             " mispackaged graph" + ((misplaced > 1) ? "s" : "") + " in this record.",
  615.             se);
  616.     }
  617.     // Annotation:
  618.     if ( m_PrgCallback ) {
  619.         m_PrgInfo.m_State = CValidator::CProgressInfo::eState_Annot;
  620.         m_PrgInfo.m_Current = m_NumAnnot;
  621.         m_PrgInfo.m_CurrentDone = 0;
  622.         m_PrgCallback(&m_PrgInfo);
  623.     }
  624.     CValidError_annot annot_validator(*this);
  625.     for (CTypeConstIterator<CSeq_annot> ni(se); ni; ++ni) {
  626.         try {
  627.             annot_validator.ValidateSeqAnnot(*ni);
  628.             if ( m_PrgCallback ) {
  629.                 m_PrgInfo.m_CurrentDone++;
  630.                 m_PrgInfo.m_TotalDone++;
  631.                 if ( m_PrgCallback(&m_PrgInfo) ) {
  632.                     return false;
  633.                 }
  634.             }
  635.         } catch ( const exception& e ) {
  636.         PostErr(eDiag_Fatal, eErr_Internal_Exception,
  637.             string("Exeption while validating annotation. EXCEPTION: ") +
  638.                 e.what(), *ni);
  639.             return true;
  640.         }
  641.     }
  642.     // Descriptor lists:
  643.     if ( m_PrgCallback ) {
  644.         m_PrgInfo.m_State = CValidator::CProgressInfo::eState_Descr;
  645.         m_PrgInfo.m_Current = m_NumDescr;
  646.         m_PrgInfo.m_CurrentDone = 0;
  647.         m_PrgCallback(&m_PrgInfo);
  648.     }
  649.     CValidError_descr descr_validator(*this);
  650.     for (CTypeConstIterator<CSeq_descr> ei(se); ei; ++ei) {
  651.         try {
  652.             descr_validator.ValidateSeqDescr(*ei);
  653.             if ( m_PrgCallback ) {
  654.                 m_PrgInfo.m_CurrentDone++;
  655.                 m_PrgInfo.m_TotalDone++;
  656.                 if ( m_PrgCallback(&m_PrgInfo) ) {
  657.                     return false;
  658.                 }
  659.             }
  660.         } catch ( const exception& e ) {
  661.         PostErr(eDiag_Fatal, eErr_Internal_Exception,
  662.             string("Exeption while validating annotation. EXCEPTION: ") +
  663.                 e.what(), *ei);
  664.             return true;
  665.         }
  666.     }
  667.     ReportMissingPubs(se, cs);
  668.     ReportMissingBiosource(se);
  669.     ReportProtWithoutFullRef();
  670.     ReportBioseqsWithNoMolinfo();
  671.     return true;
  672. }
  673. void CValidError_imp::Validate(const CSeq_submit& ss, CScope* scope)
  674. {
  675.     // Check that ss is type e_Entrys
  676.     if ( ss.GetData().Which() != CSeq_submit::C_Data::e_Entrys ) {
  677.         return;
  678.     }
  679.     // Get CCit_sub pointer
  680.     const CCit_sub* cs = &ss.GetSub().GetCit();
  681.     // Just loop thru CSeq_entrys
  682.     ITERATE( list< CRef< CSeq_entry > >, se, ss.GetData().GetEntrys() ) {
  683.         Validate(**se, cs, scope);
  684.     }
  685. }
  686. // Validate standalone Seq-annot objects
  687. void CValidError_imp::Validate(const CSeq_annot& sa, CScope* scope)
  688. {
  689.     Setup(sa, scope);
  690.     // Iterate thru components of record and validate each
  691.     CValidError_annot annot_validator(*this);
  692.     annot_validator.ValidateSeqAnnot(sa);
  693.     CValidError_feat feat_validator(*this);
  694.     for (CTypeConstIterator <CSeq_feat> fi (sa); fi; ++fi) {
  695.         feat_validator.ValidateSeqFeat(*fi);
  696.     }
  697.     CValidError_align align_validator(*this);
  698.     for (CTypeConstIterator <CSeq_align> ai (sa); ai; ++ai) {
  699.         align_validator.ValidateSeqAlign(*ai);
  700.     }
  701.     CValidError_graph graph_validator(*this);
  702.     for (CTypeConstIterator <CSeq_graph> gi (sa); gi; ++gi) {
  703.         graph_validator.ValidateSeqGraph(*gi);
  704.     }
  705. }
  706. void CValidError_imp::SetProgressCallback
  707. (CValidator::TProgressCallback callback,
  708.  void* user_data)
  709. {
  710.     m_PrgCallback = callback;
  711.     m_PrgInfo.m_UserData = user_data;
  712. }
  713. void CValidError_imp::ValidatePubdesc
  714. (const CPubdesc& pubdesc,
  715.  const CSerialObject& obj)
  716. {
  717.     int uid = 0;
  718.     ITERATE( CPub_equiv::Tdata, pub_iter, pubdesc.GetPub().Get() ) {
  719.         const CPub& pub = **pub_iter;
  720.         switch( pub.Which() ) {
  721.         case CPub::e_Gen:
  722.             ValidatePubGen(pub.GetGen(), obj);
  723.             break;
  724.         case CPub::e_Sub:
  725.             ValidateCitSub(pub.GetSub(), obj);
  726.             break;
  727.         case CPub::e_Muid:
  728.             if ( uid == 0 ) {
  729.                 uid = pub.GetMuid();
  730.             }
  731.             break;
  732.         case CPub::e_Pmid:
  733.             if ( uid == 0 ) {
  734.                 uid = pub.GetPmid();
  735.             }
  736.             break;
  737.             
  738.         case CPub::e_Article:
  739.             ValidatePubArticle(pub.GetArticle(), uid, obj);
  740.             break;
  741.         case CPub::e_Equiv:
  742.             PostErr(eDiag_Warning, eErr_GENERIC_UnnecessaryPubEquiv,
  743.                 "Publication has unexpected internal Pub-equiv", obj);
  744.             break;
  745.         default:
  746.             break;
  747.         }
  748.     }
  749.     ValidateEtAl(pubdesc, obj);
  750. }
  751. void CValidError_imp::ValidatePubGen
  752. (const CCit_gen& gen,
  753.  const CSerialObject& obj)
  754. {
  755.     if ( gen.IsSetCit()  &&  !gen.GetCit().empty() ) {
  756.         const string& cit = gen.GetCit();
  757.         if ( (NStr::CompareNocase(cit, 0, 8,  "submitted") != 0)          &&
  758.              (NStr::CompareNocase(cit, 0, 11, "unpublished") != 0)        &&
  759.              (NStr::CompareNocase(cit, 0, 18, "Online Publication") != 0) &&
  760.              (NStr::CompareNocase(cit, 0, 26, "Published Only in DataBase") != 0) ) {
  761.             PostErr(eDiag_Error, eErr_GENERIC_MissingPubInfo,
  762.                 "Unpublished citation text invalid", obj);
  763.         }
  764.     }
  765. }
  766. void CValidError_imp::ValidatePubArticle
  767. (const CCit_art& art,
  768.  int uid,
  769.  const CSerialObject& obj)
  770. {
  771.     if ( !art.IsSetTitle()  ||  !HasTitle(art.GetTitle()) ) { 
  772.         PostErr(eDiag_Error, eErr_GENERIC_MissingPubInfo,
  773.             "Publication has no title", obj);
  774.     }
  775.     
  776.     if ( art.IsSetAuthors() ) {
  777.         const CAuth_list::C_Names& names = art.GetAuthors().GetNames();
  778.         bool has_name = false;
  779.         if ( names.IsStd() ) {
  780.             has_name = HasName(names.GetStd());
  781.         } 
  782.         if ( names.IsMl() ) {
  783.             has_name = !IsBlankStringList(names.GetMl());
  784.         }
  785.         if ( names.IsStr() ) {
  786.             has_name = !IsBlankStringList(names.GetStr());
  787.         }
  788.         if ( !has_name ) {
  789.             PostErr(eDiag_Error, eErr_GENERIC_MissingPubInfo,
  790.                 "Publication has no author names", obj);
  791.         }
  792.     }
  793.     
  794.     
  795.     if ( art.GetFrom().IsJournal() ) {
  796.         const CCit_jour& jour = art.GetFrom().GetJournal();
  797.         
  798.         bool has_iso_jta = HasIsoJTA(jour.GetTitle());
  799.         bool in_press = false;
  800.         if ( !HasTitle(jour.GetTitle()) ) {
  801.             PostErr(eDiag_Error, eErr_GENERIC_MissingPubInfo,
  802.             "Journal title missing", obj);
  803.         }
  804.         if ( jour.CanGetImp() ) {
  805.             const CImprint& imp = jour.GetImp();
  806.             if ( imp.CanGetPrepub() ) {
  807.                 in_press =  imp.GetPrepub() == CImprint::ePrepub_in_press;
  808.             }
  809.             if ( !imp.IsSetPrepub()        &&  
  810.                  (!imp.CanGetPubstatus()   ||  
  811.                   imp.GetPubstatus() != ePubStatus_aheadofprint) ) {
  812.                 bool no_vol = !imp.IsSetVolume()  || 
  813.                               IsBlankString(imp.GetVolume());
  814.                 bool no_pages = !imp.IsSetPages()  ||
  815.                                 IsBlankString(imp.GetPages());
  816.                 EDiagSev sev = IsRefSeq() ? eDiag_Warning : eDiag_Error;
  817.                 if ( no_vol  &&  no_pages ) {
  818.                     PostErr(sev, eErr_GENERIC_MissingPubInfo, 
  819.                         "Journal volume and pages missing", obj);
  820.                 } else if ( no_vol ) {
  821.                     PostErr(sev, eErr_GENERIC_MissingPubInfo,
  822.                         "Journal volume missing", obj);
  823.                 } else if ( no_pages ) {
  824.                     PostErr(sev, eErr_GENERIC_MissingPubInfo,
  825.                         "Journal pages missing", obj);
  826.                 }
  827.                 
  828.                 if ( !no_pages ) {
  829.                     sev = eDiag_Warning;
  830.                     string pages = imp.GetPages();
  831.                     size_t pos = pages.find('-');
  832.                     if ( pos != string::npos ) {
  833.                         try {
  834.                             int start = 
  835.                                 NStr::StringToInt(pages.substr(0, pos), 
  836.                                                   10, NStr::eCheck_Skip);
  837.                             
  838.                             try {
  839.                                 int stop = NStr::StringToInt(
  840.                                         pages.substr(pos + 1, pages.length()),
  841.                                         10, NStr::eCheck_Skip);
  842.                                 
  843.                                 if ( start == 0  ||  stop == 0 ) {
  844.                                     PostErr(sev, eErr_GENERIC_BadPageNumbering,
  845.                                         "Page numbering has zero value", obj);
  846.                                 } else if ( start < 0  ||  stop < 0 ) {
  847.                                     PostErr(sev, eErr_GENERIC_BadPageNumbering,
  848.                                         "Page numbering has negative value", obj);
  849.                                 } else if ( start > stop ) {
  850.                                     PostErr(sev, eErr_GENERIC_BadPageNumbering,
  851.                                         "Page numbering out of order", obj);
  852.                                 } else if ( stop - start > 50 ) {
  853.                                     PostErr(sev, eErr_GENERIC_BadPageNumbering,
  854.                                         "Page numbering greater than 50", obj);
  855.                                 }
  856.                             } catch ( CStringException& ) {
  857.                                 PostErr(sev, eErr_GENERIC_BadPageNumbering,
  858.                                     "Page numbering stop looks strange", obj);
  859.                             }
  860.                         } catch ( CStringException& ) {
  861.                             if ( !isalpha(pages[0]) ) {
  862.                                 PostErr(sev, eErr_GENERIC_BadPageNumbering,
  863.                                     "Page numbering start looks strange", obj);
  864.                             }
  865.                         }
  866.                     }
  867.                 }
  868.             }
  869.         }
  870.         if ( !has_iso_jta  &&  (uid > 0  ||  in_press  ||  IsRequireISOJTA()) ) {
  871.             PostErr(eDiag_Warning, eErr_GENERIC_MissingPubInfo,
  872.                 "ISO journal title abbreviation missing", obj);
  873.         }
  874.     }
  875. }
  876. bool CValidError_imp::HasTitle(const CTitle& title)
  877. {
  878.     ITERATE (CTitle::Tdata, item, title.Get() ) {
  879.         const string *str = 0;
  880.         switch ( (*item)->Which() ) {
  881.         case CTitle::C_E::e_Name:
  882.             str = &(*item)->GetName();
  883.             break;
  884.         case CTitle::C_E::e_Tsub:
  885.             str = &(*item)->GetTsub();
  886.             break;
  887.         case CTitle::C_E::e_Trans:
  888.             str = &(*item)->GetTrans();
  889.             break;
  890.         case CTitle::C_E::e_Jta:
  891.             str = &(*item)->GetJta();
  892.             break;
  893.         case CTitle::C_E::e_Iso_jta:
  894.             str = &(*item)->GetIso_jta();
  895.             break;
  896.         case CTitle::C_E::e_Ml_jta:
  897.             str = &(*item)->GetMl_jta();
  898.             break;
  899.         case CTitle::C_E::e_Coden:
  900.             str = &(*item)->GetCoden();
  901.             break;
  902.         case CTitle::C_E::e_Issn:
  903.             str = &(*item)->GetIssn();
  904.             break;
  905.         case CTitle::C_E::e_Abr:
  906.             str = &(*item)->GetAbr();
  907.             break;
  908.         case CTitle::C_E::e_Isbn:
  909.             str = &(*item)->GetIsbn();
  910.             break;
  911.         default:
  912.             break;
  913.         };
  914.         if ( IsBlankString(*str) ) {
  915.             return false;
  916.         }
  917.     }
  918.     return true;
  919. }
  920. bool CValidError_imp::HasIsoJTA(const CTitle& title)
  921. {
  922.     ITERATE (CTitle::Tdata, item, title.Get() ) {
  923.         if ( (*item)->IsIso_jta() ) {
  924.             return true;
  925.         }
  926.     }
  927.     return false;
  928. }
  929. bool CValidError_imp::HasName(const list< CRef< CAuthor > >& authors)
  930. {
  931.     ITERATE ( list< CRef< CAuthor > >, auth, authors ) {
  932.         const CPerson_id& pid = (*auth)->GetName();
  933.         if ( pid.IsName() ) {
  934.             if ( !IsBlankString(pid.GetName().GetLast()) ) {
  935.                 return true;
  936.             }
  937.         }
  938.     }
  939.     return false;
  940. }
  941. void CValidError_imp::ValidateEtAl
  942. (const CPubdesc& pubdesc,
  943.  const CSerialObject& obj)
  944. {
  945.     ITERATE( CPub_equiv::Tdata, pub, pubdesc.GetPub().Get() ) {
  946.         const CAuth_list* authors = 0;
  947.         switch ( (*pub)->Which() ) {
  948.         case CPub::e_Gen:
  949.             if ( (*pub)->GetGen().IsSetAuthors() ) {
  950.                 authors = &((*pub)->GetGen().GetAuthors());
  951.             }
  952.             break;
  953.         case CPub::e_Sub:
  954.             authors = &((*pub)->GetSub().GetAuthors());
  955.             break;
  956.         case CPub::e_Article:
  957.             if ( (*pub)->GetArticle().IsSetAuthors() ) {
  958.                 authors = &((*pub)->GetArticle().GetAuthors());
  959.             }
  960.             break;
  961.         case CPub::e_Book:
  962.             authors = &((*pub)->GetBook().GetAuthors());
  963.             break;
  964.         case CPub::e_Proc:
  965.             authors = &((*pub)->GetProc().GetBook().GetAuthors());
  966.             break;
  967.         case CPub::e_Man:
  968.             authors = &((*pub)->GetMan().GetCit().GetAuthors());
  969.             break;
  970.         default:
  971.             break;
  972.         }
  973.         if ( !authors ) {
  974.             continue;
  975.         }
  976.         const CAuth_list::C_Names& names = authors->GetNames();
  977.         if ( !names.IsStd() ) {
  978.             continue;
  979.         }
  980.         ITERATE ( CAuth_list::C_Names::TStd, name, names.GetStd() ) {
  981.             if ( (*name)->GetName().IsName() ) {
  982.                 const CName_std& nstd = (*name)->GetName().GetName();
  983.                 if ( (NStr::CompareNocase(nstd.GetLast(), "et al.") == 0)  ||
  984.                      (nstd.GetLast() == "et."  &&  nstd.GetInitials() == "al"  &&
  985.                       nstd.GetFirst().empty()) ) {
  986.                     CAuth_list::C_Names::TStd::const_iterator temp = name;
  987.                     if ( ++temp == names.GetStd().end() ) {
  988.                         PostErr(eDiag_Warning, eErr_GENERIC_AuthorListHasEtAl,
  989.                             "Author list ends in et al.", obj);
  990.                     } else {
  991.                         PostErr(eDiag_Warning, eErr_GENERIC_AuthorListHasEtAl,
  992.                             "Author list contains et al.", obj);
  993.                     }
  994.                 }
  995.             }
  996.         }
  997.     }
  998. }
  999. void CValidError_imp::ValidateDbxref
  1000. (const CDbtag& xref,
  1001.  const CSerialObject& obj,
  1002.  bool biosource)
  1003. {
  1004.     if ( !xref.CanGetDb() ) {
  1005.         return;
  1006.     }
  1007.     const string& db = xref.GetDb();
  1008.     CDbtag::EDbtagType db_type = xref.GetType();
  1009.     bool is_pid = db_type == CDbtag::eDbtagType_PID   ||
  1010.                   db_type == CDbtag::eDbtagType_PIDd  ||
  1011.                   db_type == CDbtag::eDbtagType_PIDe  ||
  1012.                   db_type == CDbtag::eDbtagType_PIDg;
  1013.     if ( biosource ) {
  1014.         if ( !xref.IsApproved() || is_pid ) {
  1015.             PostErr(eDiag_Warning, eErr_SEQ_FEAT_IllegalDbXref,
  1016.                 "Illegal db_xref type " + db, obj);
  1017.         }
  1018.     } else {  // Seq_feat
  1019.         const CSeq_feat* feat = dynamic_cast<const CSeq_feat*>(&obj);
  1020.         if ( feat != 0 ) {
  1021.             bool is_cdregion = 
  1022.                 feat->CanGetData()  &&  feat->GetData().IsCdregion();
  1023.             bool refseq = IsRefSeq();
  1024.             if ( !xref.IsApproved(refseq)  ||  (!is_cdregion  &&  is_pid) ) {
  1025.                 const char* legal = xref.IsApprovedNoCase(refseq);
  1026.                 if ( legal != 0 ) {
  1027.                     PostErr(eDiag_Warning, eErr_SEQ_FEAT_IllegalDbXref,
  1028.                         "Illegal db_xref type " + db +
  1029.                         ", legal capitalization is " + legal, obj);
  1030.                 } else {
  1031.                     PostErr(eDiag_Warning, eErr_SEQ_FEAT_IllegalDbXref,
  1032.                         "Illegal db_xref type " + db, obj);
  1033.                 }
  1034.             }
  1035.         }
  1036.     }
  1037. }
  1038. void CValidError_imp::ValidateDbxref
  1039. (TDbtags& xref_list,
  1040.  const CSerialObject& obj,
  1041.  bool biosource)
  1042. {
  1043.     ITERATE( TDbtags, xref, xref_list) {
  1044.         ValidateDbxref(**xref, obj, biosource);
  1045.     }
  1046. }
  1047. void CValidError_imp::ValidateBioSource
  1048. (const CBioSource&    bsrc,
  1049.  const CSerialObject& obj)
  1050. {
  1051.     if ( !bsrc.CanGetOrg() ) {
  1052.         PostErr(eDiag_Error, eErr_SEQ_DESCR_NoOrgFound,
  1053.             "No organism has been applied to this Bioseq.", obj);
  1054.         return;
  1055.     }
  1056. const COrg_ref& orgref = bsrc.GetOrg();
  1057.   
  1058. // Organism must have a name.
  1059. if ( (!orgref.IsSetTaxname()  ||  orgref.GetTaxname().empty())  &&
  1060.          (!orgref.IsSetCommon()   ||  orgref.GetCommon().empty()) ) {
  1061. PostErr(eDiag_Error, eErr_SEQ_DESCR_NoOrgFound,
  1062.             "No organism name has been applied to this Bioseq.", obj);
  1063. }
  1064. // validate legal locations.
  1065. if ( bsrc.GetGenome() == CBioSource::eGenome_transposon  ||
  1066.  bsrc.GetGenome() == CBioSource::eGenome_insertion_seq ) {
  1067. PostErr(eDiag_Warning, eErr_SEQ_DESCR_ObsoleteSourceLocation,
  1068.             "Transposon and insertion sequence are no longer legal locations.",
  1069.             obj);
  1070. }
  1071. int chrom_count = 0;
  1072. bool chrom_conflict = false;
  1073.     const CSubSource *chromosome = 0;
  1074. string countryname;
  1075.     bool germline = false;
  1076.     bool rearranged = false;
  1077.     if ( bsrc.IsSetSubtype() ) {
  1078.         ITERATE( CBioSource::TSubtype, ssit, bsrc.GetSubtype() ) {
  1079.             switch ( (**ssit).GetSubtype() ) {
  1080.                 
  1081.             case CSubSource::eSubtype_country:
  1082.                 countryname = (**ssit).GetName();
  1083.                 if ( !CCountries::IsValid(countryname) ) {
  1084.                     if ( countryname.empty() ) {
  1085.                         countryname = "?";
  1086.                     }
  1087.                     PostErr(eDiag_Warning, eErr_SEQ_DESCR_BadCountryCode,
  1088.                         "Bad country name " + countryname, obj);
  1089.                 }
  1090.                 break;
  1091.                 
  1092.             case CSubSource::eSubtype_chromosome:
  1093.                 ++chrom_count;
  1094.                 if ( chromosome != 0 ) {
  1095.                     if ( NStr::CompareNocase((**ssit).GetName(), chromosome->GetName()) != 0) {
  1096.                         chrom_conflict = true;
  1097.                     }          
  1098.                 } else {
  1099.                     chromosome = ssit->GetPointer();
  1100.                 }
  1101.                 break;
  1102.                 
  1103.             case CSubSource::eSubtype_transposon_name:
  1104.             case CSubSource::eSubtype_insertion_seq_name:
  1105.                 PostErr(eDiag_Warning, eErr_SEQ_DESCR_ObsoleteSourceQual,
  1106.                     "Transposon name and insertion sequence name are no "
  1107.                     "longer legal qualifiers.", obj);
  1108.                 break;
  1109.                 
  1110.             case 0:
  1111.                 PostErr(eDiag_Warning, eErr_SEQ_DESCR_BadSubSource,
  1112.                     "Unknown subsource subtype 0.", obj);
  1113.                 break;
  1114.                 
  1115.             case CSubSource::eSubtype_other:
  1116.                 ValidateSourceQualTags((**ssit).GetName(), obj);
  1117.                 break;
  1118.             case CSubSource::eSubtype_germline:
  1119.                 germline = true;
  1120.                 break;
  1121.             case CSubSource::eSubtype_rearranged:
  1122.                 rearranged = true;
  1123.                 break;
  1124.             default:
  1125.                 break;
  1126.             }
  1127.         }
  1128.     }
  1129.     if ( germline  &&  rearranged ) {
  1130.         PostErr(eDiag_Warning, eErr_SEQ_DESCR_BadSubSource,
  1131.             "Germline and rearranged should not both be present", obj);
  1132.     }
  1133. if ( chrom_count > 1 ) {
  1134. string msg = 
  1135.             chrom_conflict ? "Multiple conflicting chromosome qualifiers" :
  1136.                              "Multiple identical chromosome qualifiers";
  1137. PostErr(eDiag_Warning, eErr_SEQ_DESCR_MultipleChromosomes, msg, obj);
  1138. }
  1139.     if ( !orgref.IsSetOrgname()  ||
  1140.          !orgref.GetOrgname().IsSetLineage()  ||
  1141.          orgref.GetOrgname().GetLineage().empty() ) {
  1142. PostErr(eDiag_Error, eErr_SEQ_DESCR_MissingLineage, 
  1143.      "No lineage for this BioSource.", obj);
  1144. } else {
  1145.         const string& lineage = orgref.GetOrgname().GetLineage();
  1146. if ( bsrc.GetGenome() == CBioSource::eGenome_kinetoplast ) {
  1147. if ( lineage.find("Kinetoplastida") == string::npos ) {
  1148. PostErr(eDiag_Warning, eErr_SEQ_DESCR_BadOrganelle, 
  1149.  "Only Kinetoplastida have kinetoplasts", obj);
  1150. }
  1151. if ( bsrc.GetGenome() == CBioSource::eGenome_nucleomorph ) {
  1152. if ( lineage.find("Chlorarchniophyta") == string::npos  &&
  1153. lineage.find("Cryptophyta") == string::npos ) {
  1154. PostErr(eDiag_Warning, eErr_SEQ_DESCR_BadOrganelle, 
  1155.                     "Only Chlorarchniophyta and Cryptophyta have nucleomorphs", obj);
  1156. }
  1157. }
  1158. }
  1159.     if ( !orgref.IsSetOrgname() ) {
  1160.         return;
  1161.     }
  1162.     const COrgName& orgname = orgref.GetOrgname();
  1163.     if ( orgname.IsSetMod() ) {
  1164.         ITERATE ( COrgName::TMod, omit, orgname.GetMod() ) {
  1165.             int subtype = (**omit).GetSubtype();
  1166.             
  1167.             if ( (subtype == 0) || (subtype == 1) ) {
  1168.                 PostErr(eDiag_Warning, eErr_SEQ_DESCR_BadOrgMod, 
  1169.                     "Unknown orgmod subtype " + subtype, obj);
  1170.             }
  1171.             if ( subtype == COrgMod::eSubtype_variety ) {
  1172.                 if ( NStr::CompareNocase( orgname.GetDiv(), "PLN" ) != 0 ) {
  1173.                     PostErr(eDiag_Warning, eErr_SEQ_DESCR_BadOrgMod, 
  1174.                         "Orgmod variety should only be in plants or fungi", 
  1175.                         obj);
  1176.                 }
  1177.             }
  1178.             if ( subtype == COrgMod::eSubtype_other ) {
  1179.                 ValidateSourceQualTags( (**omit).GetSubname(), obj);
  1180.             }
  1181.         }
  1182.     }
  1183.     if ( orgref.IsSetDb() ) {
  1184.         ValidateDbxref(orgref.GetDb(), obj, true);
  1185.     }
  1186.     if ( IsRequireTaxonID() ) {
  1187.         bool found = false;
  1188.         if ( orgref.IsSetDb() ) {
  1189.             ITERATE( COrg_ref::TDb, dbt, orgref.GetDb() ) {
  1190.                 if ( NStr::CompareNocase((*dbt)->GetDb(), "taxon") == 0 ) {
  1191.                     found = true;
  1192.                     break;
  1193.                 }
  1194.             }
  1195.         }
  1196.         if ( !found ) {
  1197.             PostErr(eDiag_Warning, eErr_SEQ_DESCR_NoTaxonID,
  1198.                 "BioSource is missing taxon ID", obj);
  1199.         }
  1200.     }
  1201. }
  1202. void CValidError_imp::ValidateCitSub
  1203. (const CCit_sub& cs,
  1204.  const CSerialObject& obj)
  1205. {
  1206.     bool has_name  = false,
  1207.          has_affil = false;
  1208.     if ( cs.CanGetAuthors() ) {
  1209.         const CAuth_list& authors = cs.GetAuthors();
  1210.         if ( authors.CanGetNames() ) {
  1211.             const CAuth_list::TNames& names = cs.GetAuthors().GetNames();
  1212.             switch ( names.Which() ) {
  1213.             case CAuth_list::TNames::e_Std:
  1214.                 has_name = HasName(names.GetStd());
  1215.                 break;
  1216.                 
  1217.             case CAuth_list::TNames::e_Ml:
  1218.                 ITERATE( CAuth_list::TNames::TMl, it, names.GetMl() ) {
  1219.                     if ( !IsBlankString(*it) ) {
  1220.                         has_name = true;
  1221.                         break;
  1222.                     }
  1223.                 }
  1224.                 break;
  1225.                 
  1226.             case CAuth_list::TNames::e_Str:
  1227.                 ITERATE( CAuth_list::TNames::TStr, it, names.GetStr() ) {
  1228.                     if ( !IsBlankString(*it) ) {
  1229.                         has_name = true;
  1230.                         break;
  1231.                     }
  1232.                 }
  1233.                 break;
  1234.                 
  1235.             default:
  1236.                 break;
  1237.             }
  1238.         }
  1239.         if ( authors.CanGetAffil() ) {
  1240.             const CAffil& affil = authors.GetAffil();
  1241.             switch ( affil.Which() ) {
  1242.             case CAffil::e_Str:
  1243.                 {{
  1244.                     if ( !IsBlankString(affil.GetStr()) ) {
  1245.                         has_affil = true;
  1246.                     }
  1247.                 }}
  1248.                 break;
  1249.             case CAffil::e_Std:
  1250. #define HAS_VALUE(o, x) (o.CanGet##x()  &&  !IsBlankString(o.Get##x()))
  1251.                 {{
  1252.                     const CAffil::TStd& std = affil.GetStd();
  1253.                     if ( HAS_VALUE(std, Affil)    ||
  1254.                          HAS_VALUE(std, Div)      ||
  1255.                          HAS_VALUE(std, City)     ||
  1256.                          HAS_VALUE(std, Sub)      ||
  1257.                          HAS_VALUE(std, Country)  ||
  1258.                          HAS_VALUE(std, Street)   ||
  1259.                          HAS_VALUE(std, Email)    ||
  1260.                          HAS_VALUE(std, Fax)      ||
  1261.                          HAS_VALUE(std, Phone)    ||
  1262.                          HAS_VALUE(std, Postal_code) ) {
  1263.                         has_affil = true;
  1264.                     }
  1265.                 }}
  1266. #undef HAS_VALUE
  1267.                 break;
  1268.             }
  1269.         }
  1270.     }
  1271.     if ( !has_name ) {
  1272.         PostErr(eDiag_Error, eErr_GENERIC_MissingPubInfo,
  1273.             "Submission citation has no author names", obj);
  1274.     }
  1275.     if ( !has_affil ) {
  1276.         PostErr(eDiag_Error, eErr_GENERIC_MissingPubInfo,
  1277.             "Submission citation has no affiliation", obj);
  1278.     }
  1279. }
  1280. void CValidError_imp::ValidateSeqLoc
  1281. (const CSeq_loc& loc,
  1282.  const CBioseq_Handle&  seq,
  1283.  const string&   prefix,
  1284.  const CSerialObject& obj)
  1285. {
  1286.     bool circular = false;
  1287.     circular = seq  &&  seq.GetInst_Topology() == CSeq_inst::eTopology_circular;
  1288.     
  1289.     bool ordered = true, adjacent = false, chk = true,
  1290.         unmarked_strand = false, mixed_strand = false;
  1291.     const CSeq_id* id_cur = 0, *id_prv = 0;
  1292.     const CSeq_interval *int_cur = 0, *int_prv = 0;
  1293.     ENa_strand strand_cur = eNa_strand_unknown,
  1294.         strand_prv = eNa_strand_unknown;
  1295.     CTypeConstIterator<CSeq_loc> lit = ConstBegin(loc);
  1296.     for (; lit; ++lit) {
  1297.         try {
  1298.             switch (lit->Which()) {
  1299.             case CSeq_loc::e_Int:
  1300.                 int_cur = &lit->GetInt();
  1301.                 strand_cur = int_cur->IsSetStrand() ?
  1302.                     int_cur->GetStrand() : eNa_strand_unknown;
  1303.                 id_cur = &int_cur->GetId();
  1304.                 chk = IsValid(*int_cur, m_Scope);
  1305.                 if (chk  &&  int_prv  && ordered  &&
  1306.                     !circular  && id_prv) {
  1307.                     if (IsSameBioseq(*id_prv, *id_cur, m_Scope)) {
  1308.                         if (strand_cur == eNa_strand_minus) {
  1309.                             if (int_prv->GetTo() < int_cur->GetTo()) {
  1310.                                 ordered = false;
  1311.                             }
  1312.                             if (int_cur->GetTo() + 1 == int_prv->GetFrom()) {
  1313.                                 adjacent = true;
  1314.                             }
  1315.                         } else {
  1316.                             if (int_prv->GetTo() > int_cur->GetTo()) {
  1317.                                 ordered = false;
  1318.                             }
  1319.                             if (int_prv->GetTo() + 1 == int_cur->GetFrom()) {
  1320.                                 adjacent = true;
  1321.                             }
  1322.                         }
  1323.                     }
  1324.                 }
  1325.                 if (int_prv) {
  1326.                     if (IsSameBioseq(int_prv->GetId(), int_cur->GetId(), m_Scope)){
  1327.                         if (strand_prv == strand_cur  &&
  1328.                             int_prv->GetFrom() == int_cur->GetFrom()  &&
  1329.                             int_prv->GetTo() == int_cur->GetTo()) {
  1330.                             PostErr(eDiag_Error,
  1331.                                 eErr_SEQ_FEAT_DuplicateInterval,
  1332.                                 "Duplicate exons in location", obj);
  1333.                         }
  1334.                     }
  1335.                 }
  1336.                 int_prv = int_cur;
  1337.                 break;
  1338.             case CSeq_loc::e_Pnt:
  1339.                 strand_cur = lit->GetPnt().IsSetStrand() ?
  1340.                     lit->GetPnt().GetStrand() : eNa_strand_unknown;
  1341.                 id_cur = &lit->GetPnt().GetId();
  1342.                 chk = IsValid(lit->GetPnt(), m_Scope);
  1343.                 int_prv = 0;
  1344.                 break;
  1345.             case CSeq_loc::e_Packed_pnt:
  1346.                 strand_cur = lit->GetPacked_pnt().IsSetStrand() ?
  1347.                     lit->GetPacked_pnt().GetStrand() : eNa_strand_unknown;
  1348.                 id_cur = &lit->GetPacked_pnt().GetId();
  1349.                 chk = IsValid(lit->GetPacked_pnt(), m_Scope);
  1350.                 int_prv = 0;
  1351.                 break;
  1352.             case CSeq_loc::e_Null:
  1353.                 break;
  1354.             default:
  1355.                 strand_cur = eNa_strand_other;
  1356.                 id_cur = 0;
  1357.                 int_prv = 0;
  1358.                 break;
  1359.             }
  1360.             if (!chk) {
  1361.                 string lbl;
  1362.                 lit->GetLabel(&lbl);
  1363.                 PostErr(eDiag_Critical, eErr_SEQ_FEAT_Range,
  1364.                     prefix + ": Seq-loc " + lbl + " out of range", obj);
  1365.             }
  1366.             
  1367.             if (lit->Which() != CSeq_loc::e_Null) {
  1368.                 if (strand_prv != eNa_strand_other  &&
  1369.                     strand_cur != eNa_strand_other) {
  1370.                     if (id_cur  &&  id_prv  &&
  1371.                         IsSameBioseq(*id_cur, *id_prv, m_Scope)) {
  1372.                         if (strand_prv != strand_cur) {
  1373.                             if ((strand_prv == eNa_strand_plus  &&
  1374.                                 strand_cur == eNa_strand_unknown)  ||
  1375.                                 (strand_prv == eNa_strand_unknown  &&
  1376.                                 strand_cur == eNa_strand_plus)) {
  1377.                                 unmarked_strand = true;
  1378.                             } else {
  1379.                                 mixed_strand = true;
  1380.                             }
  1381.                         }
  1382.                     }
  1383.                 }                
  1384.                 strand_prv = strand_cur;
  1385.                 id_prv = id_cur;
  1386.             }
  1387.         } catch( const exception& e ) {
  1388.             string label;
  1389.             lit->GetLabel(&label);
  1390.             PostErr(eDiag_Error, eErr_Internal_Exception,  
  1391.                 "Exception caught while validating location " +
  1392.                 label + ". Exception: " + e.what(), obj);
  1393.                 
  1394.             strand_cur = eNa_strand_other;
  1395.             id_cur = 0;
  1396.             int_prv = 0;
  1397.         }
  1398.         
  1399.     }
  1400.     // Warn if different parts of a seq-loc refer to the same bioseq using 
  1401.     // differnt id types (i.e. gi and accession)
  1402.     ValidateSeqLocIds(loc, obj);
  1403.     
  1404.     bool exception = false;
  1405.     const CSeq_feat* sfp = dynamic_cast<const CSeq_feat*>(&obj);
  1406.     if (sfp != 0) {
  1407.         
  1408.         // Publication intervals ordering does not matter
  1409.         
  1410.         if ( sfp->GetData().GetSubtype() == CSeqFeatData::eSubtype_pub ) {
  1411.             ordered = true;
  1412.             adjacent = false;
  1413.         }
  1414.         
  1415.         // ignore ordering of heterogen bonds
  1416.         
  1417.         if ( sfp->GetData().GetSubtype() == CSeqFeatData::eSubtype_het ) {
  1418.             ordered = true;
  1419.             adjacent = false;
  1420.         }
  1421.         
  1422.         // misc_recomb intervals SHOULD be in reverse order
  1423.         if ( sfp->GetData().GetSubtype() == CSeqFeatData::eSubtype_misc_recomb ) {
  1424.             ordered = true;
  1425.         }
  1426.         
  1427.         // primer_bind intervals MAY be in on opposite strands
  1428.         
  1429.         if ( sfp->GetData().GetSubtype() == CSeqFeatData::eSubtype_primer_bind ) {
  1430.             mixed_strand = false;
  1431.             unmarked_strand = false;
  1432.             ordered = true;
  1433.         }
  1434.         
  1435.         exception = sfp->IsSetExcept() ?  sfp->GetExcept() : false;
  1436.     }
  1437.     string loc_lbl;
  1438.     if (adjacent) {
  1439.         loc.GetLabel(&loc_lbl);
  1440.         EDiagSev sev = exception ? eDiag_Warning : eDiag_Error;
  1441.         PostErr(sev, eErr_SEQ_FEAT_AbuttingIntervals,
  1442.             prefix + ": Adjacent intervals in SeqLoc [" +
  1443.             loc_lbl + "]", obj);
  1444.     }
  1445.     if (exception  &&  sfp->CanGetExcept_text()) {
  1446.         // trans splicing exception turns off both mixed_strand and
  1447.         // out_of_order messages
  1448.         if (NStr::FindNoCase(sfp->GetExcept_text(), "trans-splicing") != NPOS) {
  1449.             return;
  1450.         }
  1451.     }
  1452.     if (mixed_strand  ||  unmarked_strand  ||  !ordered) {
  1453.         if (loc_lbl.empty()) {
  1454.             loc.GetLabel(&loc_lbl);
  1455.         }
  1456.         if (mixed_strand) {
  1457.             PostErr(eDiag_Error, eErr_SEQ_FEAT_MixedStrand,
  1458.                 prefix + ": Mixed strands in SeqLoc [" +
  1459.                 loc_lbl + "]", obj);
  1460.         } else if (unmarked_strand) {
  1461.             PostErr(eDiag_Warning, eErr_SEQ_FEAT_MixedStrand,
  1462.                 prefix + ": Mixed plus and unknown strands in SeqLoc "
  1463.                 " [" + loc_lbl + "]", obj);
  1464.         }
  1465.         if (!ordered) {
  1466.             PostErr(eDiag_Error, eErr_SEQ_FEAT_SeqLocOrder,
  1467.                 prefix + ": Intervals out of order in SeqLoc [" +
  1468.                 loc_lbl + "]", obj);
  1469.         }
  1470.         return;
  1471.     }
  1472.     if ( seq  &&
  1473.          seq.IsSetInst_Repr()  &&
  1474.          seq.GetInst_Repr() != CSeq_inst::eRepr_seg ) {
  1475.         return;
  1476.     }
  1477.     // Check for intervals out of order on segmented Bioseq
  1478.     if ( seq  &&  BadSeqLocSortOrder(*seq.GetCompleteBioseq(), loc, m_Scope) ) {
  1479.         if (loc_lbl.empty()) {
  1480.             loc.GetLabel(&loc_lbl);
  1481.         }
  1482.         PostErr(eDiag_Error, eErr_SEQ_FEAT_SeqLocOrder,
  1483.             prefix + "Intervals out of order in SeqLoc [" +
  1484.             loc_lbl + "]", obj);
  1485.     }
  1486.     // Check for mixed strand on segmented Bioseq
  1487.     if ( IsMixedStrands(loc) ) {
  1488.         if (loc_lbl.empty()) {
  1489.             loc.GetLabel(&loc_lbl);
  1490.         }
  1491.         PostErr(eDiag_Error, eErr_SEQ_FEAT_MixedStrand,
  1492.             prefix + ": Mixed strands in SeqLoc [" +
  1493.             loc_lbl + "]", obj);
  1494.     }
  1495. }
  1496. void CValidError_imp::AddBioseqWithNoPub(const CBioseq& seq)
  1497. {
  1498.     m_BioseqWithNoPubs.push_back(CConstRef<CBioseq>(&seq));
  1499. }
  1500. void CValidError_imp::AddBioseqWithNoBiosource(const CBioseq& seq)
  1501. {
  1502.     m_BioseqWithNoSource.push_back(CConstRef<CBioseq>(&seq));
  1503. }
  1504. void CValidError_imp::AddBioseqWithNoMolinfo(const CBioseq& seq)
  1505. {
  1506.     m_BioseqWithNoMolinfo.push_back(CConstRef<CBioseq>(&seq));
  1507. }
  1508. void CValidError_imp::AddProtWithoutFullRef(const CBioseq_Handle& seq)
  1509. {
  1510.     const CSeq_feat* cds = GetCDSForProduct(seq);
  1511.     if ( cds != 0 ) {
  1512.         m_ProtWithNoFullRef.push_back(CConstRef<CSeq_feat>(cds));
  1513.     }
  1514. }
  1515. void CValidError_imp::ReportMissingPubs(const CSeq_entry& se, const CCit_sub* cs)
  1516. {
  1517.     if ( m_NoPubs ) {
  1518.         if ( !m_IsGPS  &&  !m_IsRefSeq  &&  !cs) {
  1519.             PostErr(eDiag_Error, eErr_SEQ_DESCR_NoPubFound, 
  1520.                 "No publications anywhere on this entire record", se);
  1521.         } 
  1522.         return;
  1523.     }
  1524.     size_t num_no_pubs = m_BioseqWithNoPubs.size();
  1525.     EDiagSev sev = IsCuratedRefSeq() ? eDiag_Error : eDiag_Warning;
  1526.     if ( num_no_pubs == 1 ) {
  1527.         PostErr(sev, eErr_SEQ_DESCR_NoPubFound, 
  1528.             "No publications refer to this Bioseq.",
  1529.             *(m_BioseqWithNoPubs[0]));
  1530.     } else if ( num_no_pubs > 10 ) {
  1531.         PostErr(sev, eErr_SEQ_DESCR_NoPubFound, 
  1532.             NStr::IntToString(num_no_pubs) + 
  1533.             " Bioseqs without publication in this record  (first reported)",
  1534.             *(m_BioseqWithNoPubs[0]));
  1535.     } else {
  1536.         string msg;
  1537.         for ( size_t i = 0; i < num_no_pubs; ++i ) {
  1538.             msg = NStr::IntToString(i + 1) + " of " + 
  1539.                 NStr::IntToString(num_no_pubs) + 
  1540.                 " Bioseqs without publication";
  1541.             PostErr(sev, eErr_SEQ_DESCR_NoPubFound, msg, 
  1542.                 *(m_BioseqWithNoPubs[i]));
  1543.         }
  1544.     }
  1545. }
  1546. void CValidError_imp::ReportMissingBiosource(const CSeq_entry& se)
  1547. {
  1548.     if(m_NoBioSource  &&  !m_IsPatent  &&  !m_IsPDB) {
  1549.         PostErr(eDiag_Error, eErr_SEQ_DESCR_NoOrgFound,
  1550.             "No organism name anywhere on this entire record", se);
  1551.         return;
  1552.     }
  1553.     
  1554.     size_t num_no_source = m_BioseqWithNoSource.size();
  1555.     
  1556.     if ( num_no_source == 1 ) {
  1557.         PostErr(eDiag_Error, eErr_SEQ_DESCR_NoOrgFound, 
  1558.             "No organism name has been applied to this Bioseq.",
  1559.             *(m_BioseqWithNoSource[0]));
  1560.     } else if ( num_no_source > 10 ) {
  1561.         PostErr(eDiag_Error, eErr_SEQ_DESCR_NoOrgFound, 
  1562.             NStr::IntToString(num_no_source) + 
  1563.             " Bioseqs without organism name in this record (first reported)",
  1564.             *(m_BioseqWithNoSource[0]));
  1565.     } else {
  1566.         string msg;
  1567.         for ( size_t i = 0; i < num_no_source; ++i ) {
  1568.             msg = NStr::IntToString(i + 1) + " of " + 
  1569.                 NStr::IntToString(num_no_source) + 
  1570.                 " Bioseqs without organism name";
  1571.             PostErr(eDiag_Error, eErr_SEQ_DESCR_NoOrgFound, msg, 
  1572.                 *(m_BioseqWithNoSource[i]));
  1573.         }
  1574.     }
  1575. }
  1576. void CValidError_imp::ReportProtWithoutFullRef(void)
  1577. {
  1578.     size_t num = m_ProtWithNoFullRef.size();
  1579.     
  1580.     if ( num == 1 ) {
  1581.         PostErr(eDiag_Error, eErr_SEQ_FEAT_NoProtRefFound, 
  1582.             "No full length Prot-ref feature applied to this Bioseq",
  1583.             *(m_ProtWithNoFullRef[0]));
  1584.     } else if ( num > 10 ) {
  1585.         PostErr(eDiag_Error, eErr_SEQ_FEAT_NoProtRefFound, 
  1586.             NStr::IntToString(num) + " Bioseqs with no full length " 
  1587.             "Prot-ref feature applied to them (first reported)",
  1588.             *(m_ProtWithNoFullRef[0]));
  1589.     } else {
  1590.         string msg;
  1591.         for ( size_t i = 0; i < num; ++i ) {
  1592.             msg = NStr::IntToString(i + 1) + " of " + 
  1593.                 NStr::IntToString(num) + 
  1594.                 " Bioseqs without full length Prot-ref feature applied to";
  1595.             PostErr(eDiag_Error, eErr_SEQ_FEAT_NoProtRefFound, msg, 
  1596.                 *(m_ProtWithNoFullRef[i]));
  1597.         }
  1598.     }
  1599. }   
  1600. void CValidError_imp::ReportBioseqsWithNoMolinfo(void)
  1601. {
  1602.     if ( m_BioseqWithNoMolinfo.empty() ) {
  1603.         return;
  1604.     }
  1605.     size_t num = m_BioseqWithNoMolinfo.size();
  1606.     
  1607.     if ( num == 1 ) {
  1608.         PostErr(eDiag_Error, eErr_SEQ_DESCR_NoMolInfoFound, 
  1609.             "No Mol-info applies to this Bioseq",
  1610.             *(m_BioseqWithNoMolinfo[0]));
  1611.     } else if ( num > 10 ) {
  1612.         PostErr(eDiag_Error, eErr_SEQ_DESCR_NoMolInfoFound, 
  1613.             NStr::IntToString(num) + " Bioseqs with no Mol-info " 
  1614.             "applied to them (first reported)",
  1615.             *(m_BioseqWithNoMolinfo[0]));
  1616.     } else {
  1617.         string msg;
  1618.         for ( size_t i = 0; i < num; ++i ) {
  1619.             msg = NStr::IntToString(i + 1) + " of " + 
  1620.                 NStr::IntToString(num) + 
  1621.                 " Bioseqs with no Mol-info applied to";
  1622.             PostErr(eDiag_Error, eErr_SEQ_DESCR_NoMolInfoFound, msg, 
  1623.                 *(m_BioseqWithNoMolinfo[i]));
  1624.         }
  1625.     }
  1626. }   
  1627. bool CValidError_imp::IsNucAcc(const string& acc)
  1628. {
  1629.     if ( isupper(acc[0])  &&  acc.find('_') != NPOS ) {
  1630.         return true;
  1631.     }
  1632.     return false;
  1633. }
  1634. bool CValidError_imp::IsFarLocation(const CSeq_loc& loc)
  1635. {
  1636.     for ( CSeq_loc_CI citer(loc); citer; ++citer ) {
  1637.         CConstRef<CSeq_id> id(&citer.GetSeq_id());
  1638.         if ( id ) {
  1639.             CBioseq_Handle near_seq = 
  1640.                 m_Scope->GetBioseqHandleFromTSE(*id, *m_TSE);
  1641.             if ( !near_seq ) {
  1642.                 return true;
  1643.             }
  1644.         }
  1645.     }
  1646.     return false;
  1647. }
  1648. CConstRef<CSeq_feat> CValidError_imp::GetCDSGivenProduct(const CBioseq& seq)
  1649. {
  1650.     CConstRef<CSeq_feat> feat;
  1651.     CBioseq_Handle bsh = m_Scope->GetBioseqHandle(seq);
  1652.     // In case of a NT bioseq limit the search to features packaged on the 
  1653.     // NT (we assume features have been pulled from the segments to the NT).
  1654.     const CSeq_entry* limit = 0;
  1655.     if ( IsNT() ) {
  1656.         limit = m_TSE.GetPointerOrNull();
  1657.     }
  1658.     if ( bsh ) {
  1659.         CFeat_CI fi(bsh, 
  1660.                     0, 0,
  1661.                     CSeqFeatData::e_Cdregion,
  1662.                     SAnnotSelector::eOverlap_Intervals,
  1663.                     SAnnotSelector::eResolve_TSE,
  1664.                     CFeat_CI::e_Product,
  1665.                     limit);
  1666.         if ( fi ) {
  1667.             // return the first one (should be the one packaged on the
  1668.             // nuc-prot set).
  1669.             feat.Reset(&(fi->GetOriginalFeature()));
  1670.         }
  1671.     }
  1672.     return feat;
  1673. }
  1674. const CSeq_entry* CValidError_imp::GetAncestor
  1675. (const CBioseq& seq,
  1676.  CBioseq_set::EClass clss)
  1677. {
  1678.     const CSeq_entry* parent = 0;
  1679.     for ( parent = seq.GetParentEntry(); 
  1680.           parent != 0;
  1681.           parent = parent->GetParentEntry() ) {
  1682.         if ( parent->IsSet() ) {
  1683.             const CBioseq_set& set = parent->GetSet();
  1684.             if ( set.IsSetClass()  &&  set.GetClass() == clss ) {
  1685.                 break;
  1686.             }
  1687.         }
  1688.     }
  1689.     return parent;
  1690. }
  1691. bool CValidError_imp::IsSerialNumberInComment(const string& comment)
  1692. {
  1693.     size_t pos = comment.find('[', 0);
  1694.     while ( pos != string::npos ) {
  1695.         ++pos;
  1696.         if ( isdigit(comment[pos]) ) {
  1697.             while ( isdigit(comment[pos]) ) {
  1698.                 ++pos;
  1699.             }
  1700.             if ( comment[pos] == ']' ) {
  1701.                 return true;
  1702.             }
  1703.         }
  1704.         pos = comment.find('[', pos);
  1705.     }
  1706.     return false;
  1707. }
  1708. bool CValidError_imp::CheckSeqVector(const CSeqVector& vec)
  1709. {
  1710.     if ( IsSequenceAvaliable(vec) ) {
  1711.         return true;
  1712.     }
  1713.     if ( IsRemoteFetch() ) {
  1714.         // issue some sort of error
  1715.     }
  1716.     return false;
  1717. }
  1718. bool CValidError_imp::IsSequenceAvaliable(const CSeqVector& vec)
  1719. {
  1720.     // IMPORTANT: This is a temporary implementation, due to (yet) restricted
  1721.     // implementation of the Scope / object manager classes.
  1722.     // if the first and last elements are accesible the sequence is available.
  1723.     try {
  1724.         vec[0]; 
  1725.         vec[vec.size() - 1];
  1726.     } catch ( const exception& ) {
  1727.         // do something
  1728.         return false;
  1729.     }
  1730.     return true;
  1731. }
  1732. // =============================================================================
  1733. //                                  Private
  1734. // =============================================================================
  1735. bool CValidError_imp::IsMixedStrands(const CSeq_loc& loc)
  1736. {
  1737.     if ( SeqLocCheck(loc, m_Scope) == eSeqLocCheck_warning ) {
  1738.         return false;
  1739.     }
  1740.     CSeq_loc_CI curr(loc);
  1741.     if ( !curr ) {
  1742.         return false;
  1743.     }
  1744.     CSeq_loc_CI prev = curr;
  1745.     ++curr;
  1746.     
  1747.     while ( curr ) {
  1748.         ENa_strand curr_strand = curr.GetStrand();
  1749.         ENa_strand prev_strand = prev.GetStrand();
  1750.         if ( (prev_strand == eNa_strand_minus  &&  
  1751.               curr_strand != eNa_strand_minus)   ||
  1752.              (prev_strand != eNa_strand_minus  &&  
  1753.               curr_strand == eNa_strand_minus) ) {
  1754.             return true;
  1755.         }
  1756.         prev = curr;
  1757.         ++curr;
  1758.     }
  1759.     return false;
  1760. }
  1761. void CValidError_imp::Setup(const CSeq_entry& se, CScope* scope) 
  1762. {
  1763.     // "Save" the Seq-entry
  1764.     m_TSE = &se;
  1765.     if ( scope ) {
  1766.         m_Scope.Reset(scope);
  1767.     } else {
  1768.         SetScope(se);
  1769.     }
  1770.     // If no Pubs/BioSource in CSeq_entry, post only one error
  1771.     CTypeConstIterator<CPub> pub(ConstBegin(se));
  1772.     m_NoPubs = !pub;
  1773.     CTypeConstIterator<CBioSource> src(ConstBegin(se));
  1774.     m_NoBioSource = !src;
  1775.     
  1776.     // Look for genomic product set
  1777.     for (CTypeConstIterator <CBioseq_set> si (se); si; ++si) {
  1778.         if (si->IsSetClass ()) {
  1779.             if (si->GetClass () == CBioseq_set::eClass_gen_prod_set) {
  1780.                 m_IsGPS = true;
  1781.             }
  1782.         }
  1783.     }
  1784.     // Examine all Seq-ids on Bioseqs
  1785.     for (CTypeConstIterator <CBioseq> bi (se); bi; ++bi) {
  1786.         ITERATE (CBioseq::TId, id, bi->GetId()) {
  1787.             CSeq_id::E_Choice typ = (**id).Which();
  1788.             switch (typ) {
  1789.                 case CSeq_id::e_not_set:
  1790.                     break;
  1791.                 case CSeq_id::e_Local:
  1792.                     break;
  1793.                 case CSeq_id::e_Gibbsq:
  1794.                     break;
  1795.                 case CSeq_id::e_Gibbmt:
  1796.                     break;
  1797.                 case CSeq_id::e_Giim:
  1798.                     break;
  1799.                 case CSeq_id::e_Genbank:
  1800.                     m_IsGED = true;
  1801.                     break;
  1802.                 case CSeq_id::e_Embl:
  1803.                     m_IsGED = true;
  1804.                     break;
  1805.                 case CSeq_id::e_Pir:
  1806.                     break;
  1807.                 case CSeq_id::e_Swissprot:
  1808.                     break;
  1809.                 case CSeq_id::e_Patent:
  1810.                     m_IsPatent = true;
  1811.                     break;
  1812.                 case CSeq_id::e_Other:
  1813.                     m_IsRefSeq = true;
  1814.                     // and do RefSeq subclasses up front as well
  1815.                     if ((**id).GetOther().IsSetAccession()) {
  1816.                         string acc = (**id).GetOther().GetAccession().substr(0, 3);
  1817.                         if (acc == "NC_") {
  1818.                             m_IsNC = true;
  1819.                         } else if (acc == "NG_") {
  1820.                             m_IsNG = true;
  1821.                         } else if (acc == "NM_") {
  1822.                             m_IsNM = true;
  1823.                         } else if (acc == "NP_") {
  1824.                             m_IsNP = true;
  1825.                         } else if (acc == "NR_") {
  1826.                             m_IsNR = true;
  1827.                         } else if (acc == "NS_") {
  1828.                             m_IsNS = true;
  1829.                         } else if (acc == "NT_") {
  1830.                             m_IsNT = true;
  1831.                         } else if (acc == "NW_") {
  1832.                             m_IsNW = true;
  1833.                         } else if (acc == "XR_") {
  1834.                             m_IsXR = true;
  1835.                         }
  1836.                     }
  1837.                     break;
  1838.                 case CSeq_id::e_General:
  1839.                     if (!NStr::CompareCase((**id).GetGeneral().GetDb(), "BankIt")) {
  1840.                         m_IsTPA = true;
  1841.                     }
  1842.                     break;
  1843.                 case CSeq_id::e_Gi:
  1844.                     m_IsGI = true;
  1845.                     break;
  1846.                 case CSeq_id::e_Ddbj:
  1847.                     m_IsGED = true;
  1848.                     break;
  1849.                 case CSeq_id::e_Prf:
  1850.                     break;
  1851.                 case CSeq_id::e_Pdb:
  1852.                     m_IsPDB = true;
  1853.                     break;
  1854.                 case CSeq_id::e_Tpg:
  1855.                     m_IsTPA = true;
  1856.                     break;
  1857.                 case CSeq_id::e_Tpe:
  1858.                     m_IsTPA = true;
  1859.                     break;
  1860.                 case CSeq_id::e_Tpd:
  1861.                     m_IsTPA = true;
  1862.                     break;
  1863.                 default:
  1864.                     break;
  1865.             }
  1866.         }
  1867.     }
  1868.     
  1869.     if ( m_PrgCallback ) {
  1870.         m_NumAlign = 0;
  1871.         for (CTypeConstIterator<CSeq_align> i(se); i; ++i) {
  1872.             m_NumAlign++;
  1873.         }
  1874.         m_NumAnnot = 0;
  1875.         for (CTypeConstIterator<CSeq_annot> i(se); i; ++i) {
  1876.             m_NumAnnot++;
  1877.         }
  1878.         m_NumBioseq = 0;
  1879.         for (CTypeConstIterator<CBioseq> i(se); i; ++i) {
  1880.             m_NumBioseq++;
  1881.         }
  1882.         m_NumBioseq_set = 0;
  1883.         for (CTypeConstIterator<CBioseq_set> i(se); i; ++i) {
  1884.             m_NumBioseq_set++;
  1885.         }
  1886.         m_NumDesc = 0;
  1887.         for (CTypeConstIterator<CSeqdesc> i(se); i; ++i) {
  1888.             m_NumDesc++;
  1889.         }
  1890.         m_NumDescr = 0;
  1891.         for (CTypeConstIterator<CSeq_descr> i(se); i; ++i) {
  1892.             m_NumDescr++;
  1893.         }
  1894.         m_NumFeat = 0;
  1895.         for (CTypeConstIterator<CSeq_feat> i(se); i; ++i) {
  1896.             m_NumFeat++;
  1897.         }
  1898.         m_NumGraph = 0;
  1899.         for (CTypeConstIterator<CSeq_graph> i(se); i; ++i) {
  1900.             m_NumGraph++;
  1901.         }
  1902.         m_PrgInfo.m_Total = m_NumAlign + m_NumAnnot + m_NumBioseq + 
  1903.             m_NumBioseq_set + m_NumDesc + m_NumDescr + m_NumFeat + 
  1904.             m_NumGraph;
  1905.     } 
  1906. }
  1907. void CValidError_imp::SetScope(const CSeq_entry& se)
  1908. {
  1909.     m_Scope.Reset(new CScope(*m_ObjMgr));
  1910.     m_Scope->AddTopLevelSeqEntry(*const_cast<CSeq_entry*>(&se));
  1911.     m_Scope->AddDefaults();
  1912. }
  1913. void CValidError_imp::Setup(const CSeq_annot& sa, CScope* scope) 
  1914. {
  1915.     m_IsStandaloneAnnot = true;
  1916.     m_TSE.Reset(new CSeq_entry); // set a dummy Seq-entry
  1917.     if ( scope ) {
  1918.         m_Scope.Reset(scope);
  1919.     } else {
  1920.         SetScope(sa);
  1921.     }
  1922. }
  1923. void CValidError_imp::SetScope(const CSeq_annot& sa)
  1924. {
  1925.     CRef<CSeq_entry> se(new CSeq_entry);  // dummy Seq-entry
  1926.     m_Scope.Reset(new CScope(*m_ObjMgr));
  1927.     m_Scope->AttachAnnot(*se, const_cast<CSeq_annot&>(sa));
  1928.     m_Scope->AddDefaults();
  1929. }
  1930. const string CValidError_imp::sm_SourceQualPrefixes[] = {
  1931.   "acronym:",
  1932.   "anamorph:",
  1933.   "authority:",
  1934.   "biotype:",
  1935.   "biovar:",
  1936.   "breed:",
  1937.   "cell_line:",
  1938.   "cell_type:",
  1939.   "chemovar:",
  1940.   "chromosome:",
  1941.   "clone:",
  1942.   "clone_lib:",
  1943.   "common:",
  1944.   "country:",
  1945.   "cultivar:",
  1946.   "dev_stage:",
  1947.   "dosage:",
  1948.   "ecotype:",
  1949.   "endogenous_virus_name:",
  1950.   "environmental_sample:",
  1951.   "forma:",
  1952.   "forma_specialis:",
  1953.   "frequency:",
  1954.   "genotype:",
  1955.   "germline:",
  1956.   "group:",
  1957.   "haplotype:",
  1958.   "insertion_seq_name:",
  1959.   "isolate:",
  1960.   "isolation_source:",
  1961.   "lab_host:",
  1962.   "map:",
  1963.   "nat_host:",
  1964.   "pathovar:",
  1965.   "plasmid_name:",
  1966.   "plastid_name:",
  1967.   "pop_variant:",
  1968.   "rearranged:",
  1969.   "segment:",
  1970.   "serogroup:",
  1971.   "serotype:",
  1972.   "serovar:",
  1973.   "sex:",
  1974.   "specimen_voucher:",
  1975.   "strain:",
  1976.   "subclone:",
  1977.   "subgroup:",
  1978.   "substrain:",
  1979.   "subtype:",
  1980.   "sub_species:",
  1981.   "synonym:",
  1982.   "taxon:",
  1983.   "teleomorph:",
  1984.   "tissue_lib:",
  1985.   "tissue_type:",
  1986.   "transgenic:",
  1987.   "transposon_name:",
  1988.   "type:",
  1989.   "variety:",
  1990. };
  1991. void CValidError_imp::InitializeSourceQualTags() 
  1992. {
  1993.     m_SourceQualTags.reset(new CTextFsa);
  1994.     size_t size = sizeof(sm_SourceQualPrefixes) / sizeof(string);
  1995.     for (size_t i = 0; i < size; ++i ) {
  1996.         m_SourceQualTags->AddWord(sm_SourceQualPrefixes[i]);
  1997.     }
  1998.     m_SourceQualTags->Prime();
  1999. }
  2000. void CValidError_imp::ValidateSourceQualTags
  2001. (const string& str,
  2002.  const CSerialObject& obj)
  2003. {
  2004.     if ( str.empty() ) return;
  2005.     size_t str_len = str.length();
  2006.     int state = m_SourceQualTags->GetInitialState();
  2007.     for ( size_t i = 0; i < str_len; ++i ) {
  2008.         state = m_SourceQualTags->GetNextState(state, str[i]);
  2009.         if ( m_SourceQualTags->IsMatchFound(state) ) {
  2010.             string match = m_SourceQualTags->GetMatches(state)[0];
  2011.             if ( match.empty() ) {
  2012.                 match = "?";
  2013.             }
  2014.             bool okay = true;
  2015.             if ( (int)(i - str_len) >= 0 ) {
  2016.                 char ch = str[i - str_len];
  2017.                 if ( !isspace(ch) || ch != ';' ) {
  2018.                     okay = false;
  2019.                 }
  2020.             }
  2021.             if ( okay ) {
  2022.                 PostErr(eDiag_Warning, eErr_SEQ_DESCR_StructuredSourceNote,
  2023.                     "Source note has structured tag " + match, obj);
  2024.             }
  2025.         }
  2026.     }
  2027. }
  2028. bool CValidError_imp::IsCuratedRefSeq(void) const {
  2029.     return !(IsNM()  ||  IsNP()  || IsNG()  ||  IsNR());
  2030. }
  2031. void CValidError_imp::ValidateSeqLocIds
  2032. (const CSeq_loc& loc,
  2033.  const CSerialObject& obj)
  2034. {
  2035.     for ( CSeq_loc_CI lit(loc); lit; ++lit ) {
  2036.         const CSeq_id& id1 = lit.GetSeq_id();
  2037.         CSeq_loc_CI  lit2 = lit;
  2038.         for ( ++lit2; lit2; ++lit2 ) {
  2039.             const CSeq_id& id2 = lit2.GetSeq_id();
  2040.             if ( IsSameBioseq(id1, id2, m_Scope)  &&  !id1.Match(id2) ) {
  2041.                 PostErr(eDiag_Warning,
  2042.                     eErr_SEQ_FEAT_DifferntIdTypesInSeqLoc,
  2043.                     "Two ids refer to the same bioseq but are of "
  2044.                     "differnt type", obj);
  2045.             }
  2046.         }
  2047.     } 
  2048. }
  2049. // =============================================================================
  2050. //                         CValidError_base Implementation
  2051. // =============================================================================
  2052. CValidError_base::CValidError_base(CValidError_imp& imp) :
  2053.     m_Imp(imp), m_Scope(imp.GetScope())
  2054. {
  2055. }
  2056. CValidError_base::~CValidError_base()
  2057. {
  2058. }
  2059. void CValidError_base::PostErr
  2060. (EDiagSev sv,
  2061.  EErrType et,
  2062.  const string& msg,
  2063.  const CSerialObject& obj) 
  2064. {
  2065.     m_Imp.PostErr(sv, et, msg, obj);
  2066. }
  2067. void CValidError_base::PostErr
  2068. (EDiagSev sv,
  2069.  EErrType et,
  2070.  const string& msg,
  2071.  TDesc ds)
  2072. {
  2073.     m_Imp.PostErr(sv, et, msg, ds);
  2074. }
  2075. void CValidError_base::PostErr
  2076. (EDiagSev sv,
  2077.  EErrType et,
  2078.  const string& msg,
  2079.  TFeat ft)
  2080. {
  2081.     m_Imp.PostErr(sv, et, msg, ft);
  2082. }
  2083. void CValidError_base::PostErr
  2084. (EDiagSev sv,
  2085.  EErrType et,
  2086.  const string& msg,
  2087.  TBioseq sq)
  2088. {
  2089.     m_Imp.PostErr(sv, et, msg, sq);
  2090. }
  2091. void CValidError_base::PostErr
  2092. (EDiagSev sv,
  2093.  EErrType et,
  2094.  const string& msg,
  2095.  TBioseq sq,
  2096.  TDesc ds)
  2097. {
  2098.     m_Imp.PostErr(sv, et, msg, sq, ds);
  2099. }
  2100. void CValidError_base::PostErr
  2101. (EDiagSev sv,
  2102.  EErrType et,
  2103.  const string& msg, 
  2104.  TSet set)
  2105. {
  2106.     m_Imp.PostErr(sv, et, msg, set);
  2107. }
  2108. void CValidError_base::PostErr
  2109. (EDiagSev sv, 
  2110.  EErrType et, 
  2111.  const string& msg, 
  2112.  TSet set,
  2113.  TDesc ds)
  2114. {
  2115.     m_Imp.PostErr(sv, et, msg, set, ds);
  2116. }
  2117. void CValidError_base::PostErr
  2118. (EDiagSev sv,
  2119.  EErrType et,
  2120.  const string& msg,
  2121.  TAnnot annot)
  2122. {
  2123.     m_Imp.PostErr(sv, et, msg, annot);
  2124. }
  2125. void CValidError_base::PostErr
  2126. (EDiagSev sv,
  2127.  EErrType et,
  2128.  const string& msg,
  2129.  TGraph graph)
  2130. {
  2131.     m_Imp.PostErr(sv, et, msg, graph);
  2132. }
  2133. void CValidError_base::PostErr
  2134. (EDiagSev sv,
  2135.  EErrType et,
  2136.  const string& msg,
  2137.  TBioseq sq,
  2138.  TGraph graph)
  2139. {
  2140.     m_Imp.PostErr(sv, et, msg, sq, graph);
  2141. }
  2142. void CValidError_base::PostErr
  2143. (EDiagSev sv,
  2144.  EErrType et,
  2145.  const string& msg,
  2146.  TAlign align)
  2147. {
  2148.     m_Imp.PostErr(sv, et, msg, align);
  2149. }
  2150. void CValidError_base::PostErr
  2151. (EDiagSev sv,
  2152.  EErrType et,
  2153.  const string& msg,
  2154.  TEntry entry)
  2155. {
  2156.     m_Imp.PostErr(sv, et, msg, entry);
  2157. }
  2158. END_SCOPE(validator)
  2159. END_SCOPE(objects)
  2160. END_NCBI_SCOPE
  2161. /*
  2162. * ===========================================================================
  2163. *
  2164. * $Log: validatorp.cpp,v $
  2165. * Revision 1000.3  2004/06/01 19:47:39  gouriano
  2166. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.52
  2167. *
  2168. * Revision 1.52  2004/05/26 14:52:59  shomrat
  2169. * trans-splice exception supress subsequent error messages
  2170. *
  2171. * Revision 1.51  2004/05/21 21:42:56  gorelenk
  2172. * Added PCH ncbi_pch.hpp
  2173. *
  2174. * Revision 1.50  2004/05/10 13:56:47  shomrat
  2175. * Use CSeq_feat_Handle instead of FeatAnnotMap
  2176. *
  2177. * Revision 1.49  2004/04/27 18:41:05  shomrat
  2178. * ProtWithoutFullRef report CDS feature instead of protein bioseq
  2179. *
  2180. * Revision 1.48  2004/04/23 16:25:30  shomrat
  2181. * Stop using CBioseq_Handle deprecated interface
  2182. *
  2183. * Revision 1.47  2004/04/05 15:56:15  grichenk
  2184. * Redesigned CAnnotTypes_CI: moved all data and data collecting
  2185. * functions to CAnnotDataCollector. CAnnotTypes_CI is no more
  2186. * inherited from SAnnotSelector.
  2187. *
  2188. * Revision 1.46  2004/03/01 18:40:28  shomrat
  2189. * Changed far location check
  2190. *
  2191. * Revision 1.45  2004/01/12 20:25:23  shomrat
  2192. * ValidateCitSub called from ValidatePubdesc, gives error if no affiliation fields set
  2193. *
  2194. * Revision 1.44  2003/12/17 19:16:15  shomrat
  2195. * Notify graph packaging problem
  2196. *
  2197. * Revision 1.43  2003/12/15 19:09:34  shomrat
  2198. * seq-id ordering not adequate for binary_search algorithm
  2199. *
  2200. * Revision 1.42  2003/11/14 15:56:47  shomrat
  2201. * report TPA assembly problem
  2202. *
  2203. * Revision 1.41  2003/10/27 17:02:01  shomrat
  2204. * fixes to ValidatePubdesc and ValidatePubArticle
  2205. *
  2206. * Revision 1.40  2003/10/20 16:12:32  shomrat
  2207. * Added SEQ_FEAT_OnlyGeneXrefs test
  2208. *
  2209. * Revision 1.39  2003/07/24 20:16:18  vasilche
  2210. * Fixed typedefs for dbxref: list<CRef<CDbtag>> -> vector<CRef<CDbtag>>
  2211. *
  2212. * Revision 1.38  2003/06/27 18:54:22  shomrat
  2213. * Modified ValidateDbxref to use CDbtag.IsApproved
  2214. *
  2215. * Revision 1.37  2003/06/18 20:58:44  shomrat
  2216. * germline and rearranged are mutually exclusive - proviral and virion are because there is only one biop->genome
  2217. *
  2218. * Revision 1.36  2003/06/02 16:06:43  dicuccio
  2219. * Rearranged src/objects/ subtree.  This includes the following shifts:
  2220. *     - src/objects/asn2asn --> arc/app/asn2asn
  2221. *     - src/objects/testmedline --> src/objects/ncbimime/test
  2222. *     - src/objects/objmgr --> src/objmgr
  2223. *     - src/objects/util --> src/objmgr/util
  2224. *     - src/objects/alnmgr --> src/objtools/alnmgr
  2225. *     - src/objects/flat --> src/objtools/flat
  2226. *     - src/objects/validator --> src/objtools/validator
  2227. *     - src/objects/cddalignview --> src/objtools/cddalignview
  2228. * In addition, libseq now includes six of the objects/seq... libs, and libmmdb
  2229. * replaces the three libmmdb? libs.
  2230. *
  2231. * Revision 1.35  2003/05/28 16:23:23  shomrat
  2232. * SourceQualTags mad static, to improve performance in batch mode; other minor corrections.
  2233. *
  2234. * Revision 1.34  2003/05/15 18:12:10  shomrat
  2235. * Bug fix in ValidatePubArticle
  2236. *
  2237. * Revision 1.33  2003/05/14 22:10:43  shomrat
  2238. * == -> !=
  2239. *
  2240. * Revision 1.32  2003/05/05 15:35:02  shomrat
  2241. * eErr_GENERIC_BadPageNumbering dropped to eDiag_warning
  2242. *
  2243. * Revision 1.31  2003/04/29 14:57:09  shomrat
  2244. * Added SeqAlign and SeqEntry error posting methods
  2245. *
  2246. * Revision 1.30  2003/04/15 14:53:57  shomrat
  2247. * Implemented a progress callback mechanism
  2248. *
  2249. * Revision 1.29  2003/04/07 14:56:33  shomrat
  2250. * Added Seq-loc ids validation
  2251. *
  2252. * Revision 1.28  2003/04/04 18:40:50  shomrat
  2253. * Increased robustness in face of exceptions.
  2254. *
  2255. * Revision 1.27  2003/03/28 16:30:33  shomrat
  2256. * Implemented PostErr method for graph errors.
  2257. *
  2258. * Revision 1.26  2003/03/21 21:11:09  shomrat
  2259. * Initialization of m_ValidateIdSet
  2260. *
  2261. * Revision 1.25  2003/03/21 20:36:34  shomrat
  2262. * Added SEQ_DESCR_UnnecessaryBioSourceFocus
  2263. *
  2264. * Revision 1.23  2003/03/20 18:55:55  shomrat
  2265. * Added validation of standalone Seq-annot objects
  2266. *
  2267. * Revision 1.22  2003/03/18 21:48:37  grichenk
  2268. * Removed obsolete class CAnnot_CI
  2269. *
  2270. * Revision 1.21  2003/03/11 16:04:09  kuznets
  2271. * iterate -> ITERATE
  2272. *
  2273. * Revision 1.20  2003/03/07 19:15:01  shomrat
  2274. * Using binary search in IsFarLocation
  2275. *
  2276. * Revision 1.19  2003/02/24 20:18:09  shomrat
  2277. * Pass the CValidError object to the implementation class instead of the internal TErrs vector
  2278. *
  2279. * Revision 1.18  2003/02/24 18:58:13  vasilche
  2280. * Use faster version of CSeq_id::Assign().
  2281. *
  2282. * Revision 1.17  2003/02/14 21:47:13  shomrat
  2283. * Added methods to report Bioseqs with no MolInfo
  2284. *
  2285. * Revision 1.16  2003/02/12 17:49:24  shomrat
  2286. * Added implementation of IsSerialNumberInComment; Changed implementation of IsFarLocation
  2287. *
  2288. * Revision 1.15  2003/02/10 15:54:02  grichenk
  2289. * Use CFeat_CI->GetMappedFeature() and GetOriginalFeature()
  2290. *
  2291. * Revision 1.14  2003/02/07 21:14:01  shomrat
  2292. * IsMixedStrands signature changed
  2293. *
  2294. * Revision 1.13  2003/02/04 01:41:24  ucko
  2295. * Fix compilation errors caused by trying to return a pointer as a CRef
  2296. * without explicit conversion (required these days).
  2297. *
  2298. * Revision 1.12  2003/02/03 20:20:19  shomrat
  2299. * If performance flag set skip check for far location (testing)
  2300. *
  2301. * Revision 1.11  2003/02/03 17:09:05  shomrat
  2302. * Changed return value for GetCDSGivenProduct
  2303. *
  2304. * Revision 1.10  2003/01/31 19:46:46  lavr
  2305. * Remove unused variable "e" from catch() clause
  2306. *
  2307. * Revision 1.9  2003/01/29 21:55:14  shomrat
  2308. * Added check for et al
  2309. *
  2310. * Revision 1.8  2003/01/24 20:38:51  shomrat
  2311. * Added call to ValidateHistory for each bioseq
  2312. *
  2313. * Revision 1.7  2003/01/24 19:14:47  ucko
  2314. * Catch exceptions by reference rather than value; fixes a build error
  2315. * with WorkShop in release mode.
  2316. *
  2317. * Revision 1.6  2003/01/21 20:19:07  shomrat
  2318. * Implemented ValidatePubDesc
  2319. *
  2320. * Revision 1.5  2003/01/08 18:35:39  shomrat
  2321. * Added mapping features to their enclosing annotation
  2322. *
  2323. * Revision 1.4  2003/01/02 22:01:20  shomrat
  2324. * Added GetCDSGivenProduct and GetAncestor
  2325. *
  2326. * Revision 1.3  2002/12/26 16:35:11  shomrat
  2327. * Typo
  2328. *
  2329. * Revision 1.2  2002/12/24 16:51:54  shomrat
  2330. * Changes to include directives
  2331. *
  2332. * Revision 1.1  2002/12/23 20:14:37  shomrat
  2333. * Initial submission after splitting former implementation
  2334. *
  2335. *
  2336. * ===========================================================================
  2337. */