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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: plugin_utils.cpp,v $
  4.  * PRODUCTION Revision 1000.5  2004/06/01 20:44:35  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.69
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: plugin_utils.cpp,v 1000.5 2004/06/01 20:44:35 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.  * Authors:  Mike DiCuccio
  35.  *
  36.  * File Description:
  37.  *    CPluginUtils -- utilities for managing the interface between the plugin
  38.  *                    architecture and the GBENCH framework
  39.  */
  40. #include <ncbi_pch.hpp>
  41. #include <gui/core/idocument.hpp>
  42. #include <gui/core/obj_convert.hpp>
  43. #include <gui/plugin/PluginValue.hpp>
  44. #include <gui/plugin/PluginValueConstraint.hpp>
  45. #include <gui/plugin/PluginValueRangeConstraint.hpp>
  46. #include <gui/plugin/PluginReply.hpp>
  47. #include <gui/plugin/PluginMessage.hpp>
  48. #include <gui/core/plugin_registry.hpp>
  49. #include <gui/core/plugin_utils.hpp>
  50. #include <gui/core/message_queue.hpp>
  51. #include <gui/core/doc_manager.hpp>
  52. #include <gui/objutils/label.hpp>
  53. #include <gui/utils/message_box.hpp>
  54. #include <gui/core/plugin_arg_dialog.hpp>
  55. #include <serial/iterator.hpp>
  56. #include <objects/seq/Bioseq.hpp>
  57. #include <objects/seq/Seq_annot.hpp>
  58. #include <objects/seqloc/Seq_loc.hpp>
  59. #include <objects/seqloc/Seq_point.hpp>
  60. #include <objects/seqset/Seq_entry.hpp>
  61. #include <objects/seqset/Seq_entry.hpp>
  62. #include <objects/seqalign/Seq_align.hpp>
  63. #include <objmgr/seq_vector.hpp>
  64. #include <objmgr/util/sequence.hpp>
  65. #include <objmgr/util/feature.hpp>
  66. #include <objmgr/annot_selector.hpp>
  67. #include <objmgr/annot_ci.hpp>
  68. #include <objmgr/align_ci.hpp>
  69. #include <algorithm>
  70. BEGIN_NCBI_SCOPE
  71. USING_SCOPE(objects);
  72. // simple functor to return the best argument in a list of arguments
  73. // 'best' is determined by a simple user-supplied rank
  74. struct SChoiceRank
  75. {
  76.     const vector<int>& m_Ranks;
  77.     SChoiceRank(const vector<int>& ranks)
  78.         : m_Ranks(ranks) {}
  79.     int operator() (CConstRef<CPluginArg> arg) const
  80.     {
  81.         if ( !arg ) {
  82.             return m_Ranks.size();
  83.         }
  84.         return m_Ranks[ arg->GetType() ];
  85.     }
  86. };
  87. //
  88. // call a plugin by name, passing in a selection buffer
  89. //
  90. template <class Command>
  91. void s_CallPlugin(const string& plugin_name, Command cmd,
  92.                   const CSelectionBuffer& selections,
  93.                   IReporter* reporter,
  94.                   const string& ctx_name,
  95.                   CPluginUtils::EDispatchWhen when)
  96. {
  97.     // prepare a plugin message to handle our command
  98.     CRef<objects::CPluginMessage> msg(new objects::CPluginMessage());
  99.     msg->SetDestination(plugin_name);
  100.     if ( !ctx_name.empty() ) {
  101.         msg->SetContext(ctx_name);
  102.     }
  103.     msg->SetReporter(reporter);
  104.     objects::CPluginRequest& request = msg->SetRequest();
  105.     objects::CPluginCommand& args    = request.SetCommand(cmd);
  106.     // don't forget to fill in our default arguments
  107.     CPluginHandle handle =
  108.         CPluginRegistry::GetPlugin(plugin_name);
  109.     if ( !handle ) {
  110.         LOG_POST(Error << "CallPlugin(): failed to find plugin named "
  111.                  << plugin_name);
  112.         return;
  113.     }
  114.     handle.FillDefaults(cmd, args);
  115.     // now, pass off to internal processing
  116.     CPluginUtils::CallPlugin(*msg, selections.DecomposeToPairs(), when);
  117. }
  118. //
  119. // call a plugin by name, passing in a document
  120. //
  121. template <class Command>
  122. void s_CallPlugin(const string& plugin_name, Command cmd,
  123.                   const IDocument* doc,
  124.                   IReporter* reporter,
  125.                   const string& ctx_name,
  126.                   CPluginUtils::EDispatchWhen when)
  127. {
  128.     CRef<CSelectionBuffer> buffer(new CSelectionBuffer());
  129.     if (doc) {
  130.         buffer->AddSelection(const_cast<IDocument*>(doc));
  131.     }
  132.     // pass off to a more intelligent CallPlugin() command
  133.     CPluginUtils::CallPlugin(plugin_name, cmd, *buffer,
  134.                              reporter, ctx_name, when);
  135. }
  136. void CPluginUtils::CallPlugin(const string& name, EAlgoCommand cmd,
  137.                               const CSelectionBuffer& buffer,
  138.                               IReporter* reporter,
  139.                               const string& ctx_name,
  140.                               EDispatchWhen when)
  141. {
  142.     s_CallPlugin(name, cmd, buffer, reporter, ctx_name, when);
  143. }
  144. void CPluginUtils::CallPlugin(const string& name, EDataCommand cmd,
  145.                               const CSelectionBuffer& buffer,
  146.                               IReporter* reporter,
  147.                               const string& ctx_name,
  148.                               EDispatchWhen when)
  149. {
  150.     s_CallPlugin(name, cmd, buffer, reporter, ctx_name, when);
  151. }
  152. void CPluginUtils::CallPlugin(const string& name, EViewCommand cmd,
  153.                               const CSelectionBuffer& buffer,
  154.                               IReporter* reporter,
  155.                               const string& ctx_name,
  156.                               EDispatchWhen when)
  157. {
  158.     s_CallPlugin(name, cmd, buffer, reporter, ctx_name, when);
  159. }
  160. void CPluginUtils::CallPlugin(const string& name, EAlgoCommand cmd,
  161.                               const IDocument* doc,
  162.                               IReporter* reporter,
  163.                               const string& ctx_name,
  164.                               EDispatchWhen when)
  165. {
  166.     s_CallPlugin(name, cmd, doc, reporter, ctx_name, when);
  167. }
  168. void CPluginUtils::CallPlugin(const string& name, EDataCommand cmd,
  169.                               const IDocument* doc,
  170.                               IReporter* reporter,
  171.                               const string& ctx_name,
  172.                               EDispatchWhen when)
  173. {
  174.     s_CallPlugin(name, cmd, doc, reporter, ctx_name, when);
  175. }
  176. void CPluginUtils::CallPlugin(const string& name, EViewCommand cmd,
  177.                               const IDocument* doc,
  178.                               IReporter* reporter,
  179.                               const string& ctx_name,
  180.                               EDispatchWhen when)
  181. {
  182.     s_CallPlugin(name, cmd, doc, reporter, ctx_name, when);
  183. }
  184. //
  185. // internal handler for plugin requests that use the CPluginMessage interface
  186. //
  187. void CPluginUtils::CallPlugin(CPluginMessage& msg,
  188.                               EDispatchWhen when)
  189. {
  190.     switch (when) {
  191.     case eDispatch_Deferred:
  192.         // now, place the request message in the message queue.
  193.         CPluginMessageQueue::Add(msg);
  194.         break;
  195.     case eDispatch_Now:
  196.         CPluginMessageQueue::ProcessMessage(msg);
  197.         break;
  198.     }
  199. }
  200. //
  201. // internal handler for all plugin requests
  202. //
  203. void CPluginUtils::CallPlugin(CPluginMessage& msg,
  204.                               const TConstScopedObjects& selections,
  205.                               EDispatchWhen when)
  206. {
  207.     try {
  208.         // first, fill our default values
  209.         string          plugin_name = msg.GetDestination();
  210.         CPluginHandle   handle      = CPluginRegistry::GetPlugin(plugin_name);
  211.         CPluginRequest& request     = msg.SetRequest();
  212.         CPluginCommand& cmd         = request.SetCommand();
  213.         CPluginArgSet&  args        = cmd.SetArgs();
  214.         // give the plugin the opportunity to modify it aguments
  215.         handle.FinalizeArgs(msg);
  216.         // now, try and add any object arguments to our list
  217.         if ( FillArgs(args, selections)  ||  !CPluginUtils::IsValid(args) ) {
  218.             // we have remaining arguments that need to be addressed
  219.             // pop up a form dialog to handle these
  220.             CPluginArgDialog dlg(handle, args, selections);
  221.             if (dlg.ShowModal() == eCancel) {
  222.                 msg.SetReply().SetStatus(eMessageStatus_ignored);
  223.                 return;
  224.             }
  225.         }
  226.         // now, place the request message in the message queue.
  227.         CallPlugin(msg, when);
  228.     }
  229.     catch (CException& e) {
  230.         NcbiMessageBox("Failed to execute plugin:n" + e.GetMsg());
  231.     }
  232.     catch (exception& e) {
  233.         NcbiMessageBox(string("Failed to execute plugin:n") + e.what());
  234.     }
  235. #ifndef _DEBUG
  236.     catch (...) {
  237.         NcbiMessageBox("Failed to execute plugin:nUnknown error");
  238.     }
  239. #endif
  240. }
  241. //
  242. // verify that a set of arguments is valid
  243. //
  244. bool CPluginUtils::IsValid(const CPluginArgSet& arg)
  245. {
  246.     ITERATE(CPluginArgSet::Tdata, iter, arg.Get()) {
  247.         if ( !IsValid(**iter) ) {
  248.             return false;
  249.         }
  250.     }
  251.     return true;
  252. }
  253. //
  254. // verify that a given argument's values are consistent with the argument's
  255. // specifications
  256. //
  257. bool CPluginUtils::IsValid(const CPluginArg& arg)
  258. {
  259.     if (arg.IsSetHidden()  && arg.GetHidden()) {
  260.         // hidden arguments are ignored for the sake of validity
  261.         return true;
  262.     }
  263.     CTypeConstIterator<CPluginValue> iter(arg);
  264.     if ( !iter ) {
  265.         return false;
  266.     }
  267.     CPluginValue::E_Choice type = iter->Which();
  268.     string subtype = iter->GetObjectSubtype();
  269.     for ( ;  iter;  ++iter) {
  270.         if (iter->Which() != type  ||
  271.             iter->GetObjectSubtype() != subtype) {
  272.             return false;
  273.         }
  274.         if ( !IsValid(*iter) ) {
  275.             return false;
  276.         }
  277.     }
  278.     return CheckConstraints(arg);
  279. }
  280. //
  281. // verify that a single plugin value is valid
  282. //
  283. bool CPluginUtils::IsValid(const CPluginValue& val)
  284. {
  285.     switch (val.Which()) {
  286.     default:
  287.     case CPluginValue::e_not_set:
  288.         return false;
  289.     case CPluginValue::e_Integer:
  290.     case CPluginValue::e_String:
  291.     case CPluginValue::e_Double:
  292.     case CPluginValue::e_Boolean:
  293.     case CPluginValue::e_File:
  294.         return !val.IsEmpty();
  295.     case CPluginValue::e_Document:
  296.         {{
  297.             const IDocument* doc = val.GetDocument();
  298.             const CObject*   obj = val.GetObject();
  299.             if ( !doc  ||  !obj ) {
  300.                 return false;
  301.             }
  302.             doc = dynamic_cast<const IDocument*>(obj);
  303.             if ( !doc ) {
  304.                 return false;
  305.             }
  306.             return true;
  307.         }}
  308.         break;
  309.     case CPluginValue::e_Object:
  310.         {{
  311.             const IDocument* doc = val.GetDocument();
  312.             const CObject*   obj = val.GetObject();
  313.             if ( !doc  ||  !obj ) {
  314.                 return false;
  315.             }
  316.             if (val.GetObjectSubtype() == "Document") {
  317.                 doc = dynamic_cast<const IDocument*>(obj);
  318.                 if ( !doc ) {
  319.                     return false;
  320.                 }
  321.                 return true;
  322.             } else if (val.GetObjectSubtype() == "Object") {
  323.                 return true;
  324.             } else {
  325.                 const CSerialObject* o =
  326.                     dynamic_cast<const CSerialObject*>(obj);
  327.                 if (o) {
  328.                     return (val.GetObjectSubtype() ==
  329.                             o->GetThisTypeInfo()->GetName());
  330.                 } else {
  331.                     return false;
  332.                 }
  333.             }
  334.         }}
  335.         break;
  336.     }
  337.     return true;
  338. }
  339. //
  340. // check to see that a plugin argument's values match a plugin
  341. // argument's constraints
  342. //
  343. bool CPluginUtils::CheckConstraints(const CPluginArg& arg,
  344.                                     CConvertCache* cache)
  345. {
  346.     // we always succeed if the constraint is not set
  347.     if ( !arg.IsSetConstraint()  ||  arg.GetConstraint().size() == 0) {
  348.         return true;
  349.     }
  350.     switch (arg.GetType()) {
  351.     case CPluginArg::eInteger:
  352.         if (arg.GetConstraint().size() > 1) {
  353.             // we support only a single constraint for built-in types
  354.             LOG_POST(Error <<
  355.                      "CPluginArg::CheckConstraint(): "
  356.                      "built-in types support only one concurrent constraint");
  357.             return false;
  358.         } else {
  359.             const CPluginValueConstraint& cons = *arg.GetConstraint().front();
  360.             //
  361.             // integral types may be constrained by lower, upper, range,
  362.             // or set constraints
  363.             //
  364.             switch (cons.Which()) {
  365.             case CPluginValueConstraint::e_Lower:
  366.                 // greater than or equal to the lower range
  367.                 return (arg.AsInteger() >=
  368.                         NStr::StringToInt(cons.GetLower()));
  369.             case CPluginValueConstraint::e_Upper:
  370.                 // less than or equal to the lower range
  371.                 return (arg.AsInteger() <=
  372.                         NStr::StringToInt(cons.GetUpper()));
  373.             case CPluginValueConstraint::e_Range:
  374.                 // bounded by the range of values specified
  375.                 {{
  376.                      int val = arg.AsInteger();
  377.                      int lower =
  378.                          NStr::StringToInt(cons.GetRange().GetLower());
  379.                      if (val < lower) {
  380.                          return false;
  381.                      }
  382.                      int upper =
  383.                          NStr::StringToInt(cons.GetRange().GetUpper());
  384.                      return (val <= upper);
  385.                  }}
  386.             case CPluginValueConstraint::e_Set:
  387.                 // must match an item in the set
  388.                 // FIXME: we use a linear scan here
  389.                 {{
  390.                      int val = arg.AsInteger();
  391.                      string val_str = NStr::IntToString(val);
  392.                      CPluginValueConstraint::TSet::const_iterator iter =
  393.                          std::find(cons.GetSet().begin(),
  394.                                    cons.GetSet().end(),
  395.                                    val_str);
  396.                      return (iter != cons.GetSet().end());
  397.                  }}
  398.             default:
  399.                 LOG_POST(Error <<
  400.                          "CPluginArg::CheckConstraint(): "
  401.                          "invalid constraint type for " <<
  402.                          arg.GetName() << ": " << (int)cons.Which());
  403.                 return false;
  404.             }
  405.         }
  406.         break;
  407.     case CPluginArg::eDouble:
  408.         if (arg.GetConstraint().size() > 1) {
  409.             // we support only a single constraint for built-in types
  410.             LOG_POST(Error <<
  411.                      "CPluginArg::CheckConstraint(): "
  412.                      "built-in types support only one concurrent constraint");
  413.             return false;
  414.         } else {
  415.             const CPluginValueConstraint& cons = *arg.GetConstraint().front();
  416.             //
  417.             // real types may be constrained by lower, upper, range, or set
  418.             // constraints
  419.             //
  420.             switch (cons.Which()) {
  421.             case CPluginValueConstraint::e_Lower:
  422.                 // greater than or equal to the lower range
  423.                 return (arg.AsDouble() >=
  424.                         NStr::StringToDouble(cons.GetLower()));
  425.             case CPluginValueConstraint::e_Upper:
  426.                 // less than or equal to the lower range
  427.                 return (arg.AsDouble() <=
  428.                         NStr::StringToDouble(cons.GetUpper()));
  429.             case CPluginValueConstraint::e_Range:
  430.                 // bounded by the range of values specified
  431.                 {{
  432.                      double val = arg.AsDouble();
  433.                      double lower =
  434.                          NStr::StringToDouble(cons.GetRange().GetLower());
  435.                      if (val < lower) {
  436.                          return false;
  437.                      }
  438.                      double upper =
  439.                          NStr::StringToDouble(cons.GetRange().GetUpper());
  440.                      return (val <= upper);
  441.                  }}
  442.             case CPluginValueConstraint::e_Set:
  443.                 // must match an item in the set
  444.                 // FIXME: we use a linear scan here
  445.                 {{
  446.                      double val = arg.AsDouble();
  447.                      string val_str = NStr::DoubleToString(val);
  448.                      CPluginValueConstraint::TSet::const_iterator iter =
  449.                          std::find(cons.GetSet().begin(),
  450.                                    cons.GetSet().end(),
  451.                                    val_str);
  452.                      return (iter != cons.GetSet().end());
  453.                  }}
  454.             default:
  455.                 LOG_POST(Error <<
  456.                          "CPluginArg::CheckConstraint(): "
  457.                          "invalid constraint type for " <<
  458.                          arg.GetName() << ": " << (int)cons.Which());
  459.                 return false;
  460.             }
  461.         }
  462.         break;
  463.     case CPluginArg::eString:
  464.         if (arg.GetConstraint().size() > 1) {
  465.             // we support only a single constraint for built-in types
  466.             LOG_POST(Error <<
  467.                      "CPluginArg::CheckConstraint(): "
  468.                      "built-in types support only one concurrent constraint");
  469.             return false;
  470.         } else {
  471.             const CPluginValueConstraint& cons = *arg.GetConstraint().front();
  472.             //
  473.             // integral types may be constrained by lower, upper, range, or set
  474.             // constraints
  475.             //
  476.             switch (cons.Which()) {
  477.             case CPluginValueConstraint::e_Lower:
  478.                 // greater than or equal to the lower range
  479.                 return (arg.AsString() >= cons.GetLower());
  480.             case CPluginValueConstraint::e_Upper:
  481.                 // less than or equal to the lower range
  482.                 return (arg.AsString() <= cons.GetUpper());
  483.             case CPluginValueConstraint::e_Range:
  484.                 // bounded by the range of values specified
  485.                 {{
  486.                      string val = arg.AsString();
  487.                      string lower = cons.GetRange().GetLower();
  488.                      if (val < lower) {
  489.                          return false;
  490.                      }
  491.                      string upper = cons.GetRange().GetUpper();
  492.                      return (val <= upper);
  493.                  }}
  494.             case CPluginValueConstraint::e_Set:
  495.                 // must match an item in the set
  496.                 // FIXME: we use a linear scan here
  497.                 {{
  498.                      string val = arg.AsString();
  499.                      CPluginValueConstraint::TSet::const_iterator iter =
  500.                          std::find(cons.GetSet().begin(),
  501.                                    cons.GetSet().end(),
  502.                                    val);
  503.                      return (iter != cons.GetSet().end());
  504.                  }}
  505.             default:
  506.                 LOG_POST(Error <<
  507.                          "CPluginArg::CheckConstraint(): "
  508.                          "invalid constraint type for " <<
  509.                          arg.GetName() << ": " << (int)cons.Which());
  510.                 return false;
  511.             }
  512.         }
  513.         break;
  514.     case CPluginArg::eBoolean:
  515.         // no constraints make sense for boolean arguments
  516.         LOG_POST(Error << "CPluginArg::CheckConstraint(): "
  517.                  "constraints are invalid for Boolean arguments");
  518.         return false;
  519.     case CPluginArg::eObject:
  520.     case CPluginArg::eDocument:
  521.         {{
  522.              CTypeConstIterator<CPluginValue> iter(arg);
  523.              for ( ;  iter;  ++iter) {
  524.                  const CObject* obj = iter->GetObject();
  525.                  const IDocument* doc = iter->GetDocument();
  526.                  if ( !obj  ||  !doc ) {
  527.                      return false;
  528.                  }
  529.                  CScope& scope = doc->GetScope();
  530.                  if ( !CheckConstraints(arg, scope, *obj, cache) ) {
  531.                      return false;
  532.                  }
  533.              }
  534.              return true;
  535.          }}
  536.     default:
  537.         LOG_POST(Error << "CPluginUtils::CheckConstraint(): "
  538.                  "unhandled argument type");
  539.         break;
  540.     }
  541.     return false;
  542. }
  543. bool CPluginUtils::CheckConstraints(const CPluginArg& arg,
  544.                                     CScope& scope,
  545.                                     const CObject& obj,
  546.                                     CConvertCache* cache)
  547. {
  548.     //
  549.     // we may have multiple constraints, to answer questions such as "Give
  550.     // me all sequences that are proteins of at least 100 bases" and "Give
  551.     // me a set of sequences, all of the same molecule type, that are of
  552.     // sequence type raw"
  553.     //
  554.     ITERATE (CPluginArg::TConstraint, c_iter, arg.GetConstraint()) {
  555.         const CPluginValueConstraint& cons = **c_iter;
  556.         switch (cons.Which()) {
  557.             //
  558.             // constraints for bioseq types
  559.             //
  560.         case CPluginValueConstraint::e_Seq_repr:
  561.             // constrain the sequence representation to be of a certain type
  562.             {{
  563.                  CObjConverter::TObjList bioseqs;
  564.                  CObjectConverter::Convert(scope, obj, CBioseq::GetTypeInfo(),
  565.                                            bioseqs);
  566.                  ITERATE(CObjConverter::TObjList, iter, bioseqs) {
  567.                      const CBioseq* bioseq =
  568.                          dynamic_cast<const CBioseq*>(iter->GetPointer());
  569.                      if ( !bioseq ) {
  570.                          return false;
  571.                      }
  572.                      if (std::find(cons.GetSeq_repr().begin(),
  573.                                    cons.GetSeq_repr().end(),
  574.                                    bioseq->GetInst().GetRepr()) ==
  575.                          cons.GetSeq_repr().end() ) {
  576.                          return false;
  577.                      }
  578.                  }
  579.              }}
  580.             break;
  581.         case CPluginValueConstraint::e_Seq_mol:
  582.             // constrain the molecule type to be of a certain type
  583.             {{
  584.                  CObjConverter::TObjList bioseqs;
  585.                  CObjectConverter::Convert(scope, obj, CBioseq::GetTypeInfo(),
  586.                                            bioseqs);
  587.                  ITERATE(CObjConverter::TObjList, iter, bioseqs) {
  588.                      const CBioseq* bioseq =
  589.                          dynamic_cast<const CBioseq*>(iter->GetPointer());
  590.                      if ( !bioseq ) {
  591.                          return false;
  592.                      }
  593.                      if (std::find(cons.GetSeq_mol().begin(),
  594.                                    cons.GetSeq_mol().end(),
  595.                                    bioseq->GetInst().GetMol()) ==
  596.                          cons.GetSeq_mol().end() ) {
  597.                          return false;
  598.                      }
  599.                  }
  600.              }}
  601.             break;
  602.         case CPluginValueConstraint::e_Seq_mol_same_type:
  603.             // constrain a set of values such that their molecule types are all
  604.             // the same
  605.             {{
  606.                  const CBioseq* prev = NULL;
  607.                  CObjConverter::TObjList bioseqs;
  608.                  CObjectConverter::Convert(scope, obj, CBioseq::GetTypeInfo(),
  609.                                            bioseqs);
  610.                  ITERATE(CObjConverter::TObjList, iter, bioseqs) {
  611.                      const CBioseq* bioseq =
  612.                          dynamic_cast<const CBioseq*>(iter->GetPointer());
  613.                      if ( !bioseq ) {
  614.                          return false;
  615.                      }
  616.                      if ( !prev ) {
  617.                          prev = bioseq;
  618.                      } else {
  619.                          if (prev->GetInst().GetMol() !=
  620.                              bioseq->GetInst().GetMol()) {
  621.                              return false;
  622.                          }
  623.                      }
  624.                  }
  625.              }}
  626.             break;
  627.         case CPluginValueConstraint::e_Seq_length_lower:
  628.             // constrain a set of sequences such that their lengths are at
  629.             // least some bound
  630.             {{
  631.                  TSeqPos min_len = cons.GetSeq_length_lower();
  632.                  CObjConverter::TObjList bioseqs;
  633.                  CObjectConverter::Convert(scope, obj, CBioseq::GetTypeInfo(),
  634.                                            bioseqs);
  635.                  ITERATE(CObjConverter::TObjList, iter, bioseqs) {
  636.                      const CBioseq* bioseq =
  637.                          dynamic_cast<const CBioseq*>(iter->GetPointer());
  638.                      if ( !bioseq ) {
  639.                          return false;
  640.                      }
  641.                      if (bioseq->GetInst().GetLength() < min_len) {
  642.                          return false;
  643.                      }
  644.                  }
  645.              }}
  646.             break;
  647.         case CPluginValueConstraint::e_Seq_length_upper:
  648.             // constrain a set of sequences such that their lengths are no
  649.             // greater than some bound
  650.             {{
  651.                  TSeqPos max_len = cons.GetSeq_length_upper();
  652.                  CObjConverter::TObjList bioseqs;
  653.                  CObjectConverter::Convert(scope, obj, CBioseq::GetTypeInfo(),
  654.                                            bioseqs);
  655.                  ITERATE(CObjConverter::TObjList, iter, bioseqs) {
  656.                      const CBioseq* bioseq =
  657.                          dynamic_cast<const CBioseq*>(iter->GetPointer());
  658.                      if ( !bioseq ) {
  659.                          return false;
  660.                      }
  661.                      if (bioseq->GetInst().GetLength() > max_len) {
  662.                          return false;
  663.                      }
  664.                  }
  665.              }}
  666.             break;
  667.         case CPluginValueConstraint::e_Seq_length_range:
  668.             // constrain a set of sequences such that their lengths are at
  669.             // least some bound
  670.             {{
  671.                  TSeqPos min_len =
  672.                      NStr::StringToInt(cons.GetSeq_length_range().GetLower());
  673.                  TSeqPos max_len =
  674.                      NStr::StringToInt(cons.GetSeq_length_range().GetUpper());
  675.                  CObjConverter::TObjList bioseqs;
  676.                  CObjectConverter::Convert(scope, obj, CBioseq::GetTypeInfo(),
  677.                                            bioseqs);
  678.                  ITERATE(CObjConverter::TObjList, iter, bioseqs) {
  679.                      const CBioseq* bioseq =
  680.                          dynamic_cast<const CBioseq*>(iter->GetPointer());
  681.                      if ( !bioseq ) {
  682.                          return false;
  683.                      }
  684.                      if (bioseq->GetInst().GetLength() < min_len  ||
  685.                          bioseq->GetInst().GetLength() > max_len) {
  686.                          return false;
  687.                      }
  688.                  }
  689.              }}
  690.             break;
  691.         case CPluginValueConstraint::e_Seq_length_same:
  692.             _TRACE("x_CheckObjectConstraint(): failed: "
  693.                    "seq-inst.length: same length constraint not implemented");
  694.             break;
  695.             //
  696.             // constraints for seq-entry types
  697.             //
  698.         case CPluginValueConstraint::e_Entry_type:
  699.             // constrain a set of values such that their molecule types are all
  700.             // the same
  701.             {{
  702.                  CObjConverter::TObjList entries;
  703.                  CObjectConverter::Convert(scope, obj,
  704.                                            CSeq_entry::GetTypeInfo(), entries);
  705.                  ITERATE(CObjConverter::TObjList, iter, entries) {
  706.                      const CSeq_entry* entry=
  707.                          dynamic_cast<const CSeq_entry*>(iter->GetPointer());
  708.                      if ( !entry ) {
  709.                          return false;
  710.                      }
  711.                      if ( !entry->IsSet()  ||
  712.                           !entry->GetSet().IsSetClass()  ||
  713.                           !entry->GetSet().GetClass() == cons.GetEntry_type()) {
  714.                          return false;
  715.                      }
  716.                  }
  717.              }}
  718.             break;
  719.             //
  720.             // constraints for seq-annot types
  721.             //
  722.         case CPluginValueConstraint::e_Annot_type:
  723.             // constrain the sequence representation to be of a certain type
  724.             {{
  725.                  CObjConverter::TObjList annots;
  726.                  CObjectConverter::Convert(scope, obj,
  727.                                            CSeq_annot::GetTypeInfo(), annots);
  728.                  ITERATE(CObjConverter::TObjList, iter, annots) {
  729.                      const CSeq_annot* annot=
  730.                          dynamic_cast<const CSeq_annot*>(iter->GetPointer());
  731.                      if ( !annot ) {
  732.                          return false;
  733.                      }
  734.                      if (annot->GetData().Which() != cons.GetAnnot_type()) {
  735.                          return false;
  736.                      }
  737.                  }
  738.              }}
  739.             break;
  740.             //
  741.             // constraints for seq-feat types
  742.             //
  743.         case CPluginValueConstraint::e_Feat_type:
  744.             // constrain the sequence representation to be of a certain type
  745.             {{
  746.                  CObjConverter::TObjList feats;
  747.                  CObjectConverter::Convert(scope, obj,
  748.                                            CSeq_feat::GetTypeInfo(), feats);
  749.                  ITERATE(CObjConverter::TObjList, iter, feats) {
  750.                      const CSeq_feat* feat=
  751.                          dynamic_cast<const CSeq_feat*>(iter->GetPointer());
  752.                      if ( !feat ) {
  753.                          return false;
  754.                      }
  755.                      if (std::find(cons.GetFeat_type().begin(),
  756.                                    cons.GetFeat_type().end(), 
  757.                                    feat->GetData().Which()) ==
  758.                          cons.GetFeat_type().end()) {
  759.                          return false;
  760.                      }
  761.                  }
  762.              }}
  763.             break;
  764.             //
  765.             // constraints for seq-feat subtypes
  766.             //
  767.         case CPluginValueConstraint::e_Feat_subtype:
  768.             // constrain the sequence representation to be of a certain type
  769.             {{
  770.                  CObjConverter::TObjList feats;
  771.                  CObjectConverter::Convert(scope, obj,
  772.                                            CSeq_feat::GetTypeInfo(), feats);
  773.                  ITERATE(CObjConverter::TObjList, iter, feats) {
  774.                      const CSeq_feat* feat=
  775.                          dynamic_cast<const CSeq_feat*>(iter->GetPointer());
  776.                      if ( !feat ) {
  777.                          return false;
  778.                      }
  779.                      string label;
  780.                      feature::GetLabel(*feat, &label, feature::eBoth, &scope);
  781.                      if (std::find(cons.GetFeat_subtype().begin(),
  782.                                    cons.GetFeat_subtype().end(),
  783.                                    feat->GetData().GetSubtype()) ==
  784.                          cons.GetFeat_subtype().end()) {
  785.                          return false;
  786.                      }
  787.                  }
  788.              }}
  789.             break;
  790.             //
  791.             // constraints for seq-feats that have products set
  792.             //
  793.         case CPluginValueConstraint::e_Feat_has_product:
  794.             // constrain the sequence representation to be of a certain type
  795.             {{
  796.                  CObjConverter::TObjList feats;
  797.                  CObjectConverter::Convert(scope, obj,
  798.                                            CSeq_feat::GetTypeInfo(), feats);
  799.                  ITERATE(CObjConverter::TObjList, iter, feats) {
  800.                      const CSeq_feat* feat=
  801.                          dynamic_cast<const CSeq_feat*>(iter->GetPointer());
  802.                      if ( !feat ) {
  803.                          return false;
  804.                      }
  805.                      if ( !feat->IsSetProduct() ) {
  806.                          return false;
  807.                      }
  808.                  }
  809.              }}
  810.             break;
  811.         default:
  812.             LOG_POST(Error <<
  813.                      "CPluginArg::CheckConstraint():"
  814.                      " unhandled constraint type: " << (int)cons.Which());
  815.             return false;
  816.             break;
  817.         }
  818.     }
  819.     return true;
  820. }
  821. //
  822. // utility function to convert a set of selections into a set of arguments
  823. //
  824. int CPluginUtils::FillArgs(CPluginArgSet& args, const IDocument& doc)
  825. {
  826.     TConstScopedObjects sels;
  827.     sels.push_back(SConstScopedObject(doc, doc.GetScope()));
  828.     return FillArgs(args, sels);
  829. }
  830. int CPluginUtils::FillArgs(CPluginArgSet& args,
  831.                            const CPluginArg::TData::TArray& objs)
  832. {
  833.     // step 1: clear any object-based arguments
  834.     NON_CONST_ITERATE (CPluginArgSet::Tdata, iter, args.Set()) {
  835.         CPluginArg& arg = **iter;
  836.         arg.ClearObjects();
  837.     }
  838.     CSelectionBuffer buffer;
  839.     ITERATE (CPluginArg::TData::TArray, iter, objs) {
  840.         const CPluginValue& val = **iter;
  841.         if ( !val.GetObject() ) {
  842.             continue;
  843.         }
  844.         if ( val.IsObject() ) {
  845.             const CSerialObject* obj =
  846.                 dynamic_cast<const CSerialObject*>(val.GetObject());
  847.             IDocument* doc =
  848.                 const_cast<IDocument*>(
  849.                 dynamic_cast<const IDocument*>(val.GetDocument()));
  850.             if (obj  &&  doc) {
  851.                 buffer.AddSelection(doc, *obj);
  852.             }
  853.         } else if ( val.IsDocument() ) {
  854.             IDocument* doc =
  855.                 const_cast<IDocument*>(
  856.                 dynamic_cast<const IDocument*>(val.GetObject()));
  857.             if (doc) {
  858.                 buffer.AddSelection(doc);
  859.             }
  860.         }
  861.     }
  862.     return FillArgs(args, buffer.DecomposeToPairs());
  863. }
  864. int CPluginUtils::FillArgs(CPluginArgSet& args,
  865.                            const TConstScopedObjects& sels)
  866. {
  867.     // easy out: no arguments to fill
  868.     if (args.Get().size() == 0) {
  869.         return 0;
  870.     }
  871.     // we plan to handle one case automatically: the set of arguments has
  872.     // one argument that takes a data model object.  Other cases are left
  873.     // to the user to clarify because these are too complex to guess
  874.     int visible_args = 0;
  875.     int obj_args = 0;
  876.     CRef<CPluginArg> arg_to_fill;
  877.     NON_CONST_ITERATE (CPluginArgSet::Tdata, iter, args.Set()) {
  878.         CPluginArg& arg = **iter;
  879.         if (arg.IsSetHidden()  && arg.GetHidden()) {
  880.             continue;
  881.         }
  882.         ++visible_args;
  883.         CPluginArg::EType type = arg.GetType();
  884.         if (type == CPluginArg::eObject  ||
  885.             type == CPluginArg::eDocument) {
  886.             ++obj_args;
  887.             // clear object argument
  888.             arg.ClearObjects();
  889.             arg_to_fill.Reset(&arg);
  890.         }
  891.     }
  892.     // make sure we actually can address this argument
  893.     if ( obj_args > 1  ||  !arg_to_fill ) {
  894.         return visible_args;
  895.     }
  896.     // now, convert as many objects as possible into the requested format
  897.     // here we plan to support automatic assignments to data model objects
  898.     // only; CObject assignments can be made for these, but this must be
  899.     // done under user direction
  900.     switch (arg_to_fill->GetData().Which()) {
  901.     case CPluginArg::TData::e_Single:
  902.         //
  903.         // make sure we have exactly one selection
  904.         //
  905.         if (sels.size() == 1) {
  906.             const string& target_type = arg_to_fill->GetObjectSubtype();
  907.             SConstScopedObject cso = sels.front();
  908.             CScope& scope = *cso.scope;
  909.             IDocument* doc = CDocManager::GetDocumentFromScope(scope);
  910.             if ( !doc ) {
  911.                 break;
  912.             }
  913.             CObjConverter::TObjList obj_list;
  914.             CObjectConverter::Convert(scope, *cso.object,
  915.                                       target_type, obj_list);
  916.             if (obj_list.size() != 1) {
  917.                 break;
  918.             }
  919.             arg_to_fill->SetObject(*doc, *obj_list.front());
  920.             if (CPluginUtils::CheckConstraints(*arg_to_fill)) {
  921.                 return visible_args - 1;
  922.             }
  923.         }
  924.         break;
  925.     case CPluginArg::TData::e_Array:
  926.         {{
  927.              // make sure we preserve existing values
  928.              CPluginArg::TValues value_list;
  929.              arg_to_fill->AsList(value_list);
  930.              // we can assign many objects
  931.              // first, we do a one-to-many conversion, based on the target type
  932.              const string& target_type = arg_to_fill->GetObjectSubtype();
  933.              // now, iterate our selections and convert as necessary
  934.              ITERATE (TConstScopedObjects, iter, sels) {
  935.                  SConstScopedObject cso = sels.front();
  936.                  CScope& scope = *cso.scope;
  937.                  IDocument* doc = CDocManager::GetDocumentFromScope(scope);
  938.                  if ( !doc ) {
  939.                      continue;
  940.                  }
  941.                  CObjectConverter::TObjList obj_list;
  942.                  CObjectConverter::Convert(scope, *iter->object,
  943.                                            target_type, obj_list);
  944.                  ITERATE(CObjectConverter::TObjList, obj_iter, obj_list) {
  945.                      CRef<CPluginValue> value(new CPluginValue());
  946.                      value->SetObject(*doc, **obj_iter);
  947.                      value_list.push_back(value);
  948.                  }
  949.              }
  950.              // make sure all of our arguments are valid
  951.              // we do this such that any unfilled argument will be passed on
  952.              // if we added nothing to this argument, then our size is 1
  953.              if (value_list.size() > 1) {
  954.                  CPluginArg::TValues::iterator iter     = value_list.begin();
  955.                  CPluginArg::TValues::iterator end_iter = value_list.end();
  956.                  for ( ;  iter != end_iter;  ) {
  957.                      const CPluginValue& value = **iter;
  958.                      if ( !IsValid(value) ) {
  959.                          iter = value_list.erase(iter);
  960.                      } else {
  961.                          ++iter;
  962.                      }
  963.                  }
  964.              }
  965.              arg_to_fill->SetList(value_list);
  966.              if (CPluginUtils::CheckConstraints(*arg_to_fill)) {
  967.                  return visible_args - 1;
  968.              }
  969.          }}
  970.         break;
  971.     default:
  972.         break;
  973.     }
  974.     return visible_args;
  975. }
  976. // this function performs a similar task to FillArgs(); however, instead of
  977. // actually filling the set of arguments automatically, it returns true if any
  978. // of the selections indicated *can* fit.  The primary use of this is to
  979. // determine if a set of plugins could accept some of the selections
  980. bool CPluginUtils::CanFitArgs(const CPluginArgSet& args,
  981.                               const IDocument& doc,
  982.                               CConvertCache* cache)
  983. {
  984.     TConstScopedObjects sels;
  985.     sels.push_back(SConstScopedObject(doc, doc.GetScope()));
  986.     return CanFitArgs(args, sels, cache);
  987. }
  988. bool CPluginUtils::CanFitArgs(const CPluginArgSet& args,
  989.                               const CSelectionBuffer& sels,
  990.                               CConvertCache* cache)
  991. {
  992.     return CanFitArgs(args, sels.DecomposeToPairs(), cache);
  993. }
  994. bool CPluginUtils::CanFitArgs(const CPluginArgSet& args,
  995.                               const TConstScopedObjects& sels,
  996.                               CConvertCache* cache)
  997. {
  998.     // easy out: no arguments to fill
  999.     // we're always valid here
  1000.     if (args.Get().size() == 0) {
  1001.         return true;
  1002.     }
  1003.     // we plan to handle one case automatically: the set of arguments has
  1004.     // one argument that takes a data model object.  Other cases are left
  1005.     // to the user to clarify because these are too complex to guess
  1006.     int obj_args = 0;
  1007.     ITERATE (CPluginArgSet::Tdata, iter, args.Get()) {
  1008.         const CPluginArg& arg = **iter;
  1009.         switch (arg.GetType()) {
  1010.         case CPluginArg::eObject:
  1011.         case CPluginArg::eDocument:
  1012.             {{
  1013.                  ++obj_args;
  1014.                  const string& target_type = arg.GetObjectSubtype();
  1015.                  // are there any selections that might support this object
  1016.                  // type?  if so, we can return true
  1017.                  ITERATE (TConstScopedObjects, iter, sels) {
  1018.                      SConstScopedObject cso = *iter;
  1019.                      CScope& scope = *cso.scope;
  1020.                      CObjConverter::TObjList obj_list;
  1021.                      /**
  1022.                      if (cache) {
  1023.                          obj_list =
  1024.                              cache->Convert(scope,
  1025.                                             *iter->m_Object.GetPointer(),
  1026.                                             target_type);
  1027.                      } else **/{
  1028.                          CObjectConverter::Convert(scope,
  1029.                                                    *cso.object,
  1030.                                                    target_type, obj_list);
  1031.                      }
  1032.                      if (obj_list.size() == 0) {
  1033.                          continue;
  1034.                      }
  1035.                      ITERATE (CObjConverter::TObjList, obj_iter, obj_list) {
  1036.                          if ( CheckConstraints(arg, scope, **obj_iter) ) {
  1037.                              return true;
  1038.                          }
  1039.                      }
  1040.                  }
  1041.              }}
  1042.             break;
  1043.         default:
  1044.             break;
  1045.         }
  1046.     }
  1047.     // we failed to match any selection to an argument type
  1048.     // the only case we let pass is that there are no object argument types
  1049.     return (obj_args == 0);
  1050. }
  1051. vector<string> CPluginUtils::ArgToStringVec(const CPluginArg& arg)
  1052. {
  1053.     if (arg.GetType() != CPluginArg::eString) {
  1054.         NCBI_THROW(CPluginException, eInvalidArg,
  1055.                    "CPluginUtil::ArgToStringVec(): "
  1056.                    "Argument is not of type String");
  1057.     }
  1058.     vector<string> vals;
  1059.     CTypeConstIterator<CPluginValue> iter(arg);
  1060.     for ( ;  iter;  ++iter) {
  1061.         vals.push_back(iter->AsString());
  1062.     }
  1063.     return vals;
  1064. }
  1065. //
  1066. // return the label of an object based on its type (arg.m_Subtype)
  1067. //
  1068. string CPluginUtils::GetLabel(const CObject& obj, CScope* scope)
  1069. {
  1070.     {{
  1071.         // generic document handling
  1072.         const IDocument* doc = dynamic_cast<const IDocument*> (&obj);
  1073.         if (doc) {
  1074.             return doc->GetTitle();
  1075.         }
  1076.     }}
  1077.     string label;
  1078.     CLabel::GetLabel(obj, &label, CLabel::eDefault, scope);
  1079.     return label;
  1080. }
  1081. //
  1082. // retrieve the CPluginInfo object associated with a named plugin
  1083. //
  1084. const CPluginInfo& CPluginUtils::GetInfo(const string& plugin_name)
  1085. {
  1086.     CPluginHandle handle = CPluginRegistry::GetPlugin(plugin_name);
  1087.     if ( !handle ) {
  1088.         NCBI_THROW(CPluginException, eInvalidArg,
  1089.                    "Invalid plugin name " + plugin_name);
  1090.     }
  1091.     return handle.GetInfo();
  1092. }
  1093. END_NCBI_SCOPE
  1094. /*
  1095.  * ===========================================================================
  1096.  * $Log: plugin_utils.cpp,v $
  1097.  * Revision 1000.5  2004/06/01 20:44:35  gouriano
  1098.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.69
  1099.  *
  1100.  * Revision 1.69  2004/06/01 18:03:45  dicuccio
  1101.  * Allocate temporary CSelectionBuffer objects on the heap, not on the stack
  1102.  *
  1103.  * Revision 1.68  2004/05/21 22:27:40  gorelenk
  1104.  * Added PCH ncbi_pch.hpp
  1105.  *
  1106.  * Revision 1.67  2004/05/07 15:41:27  dicuccio
  1107.  * Use CLabel instead of CSeqUtils::GetLabel()
  1108.  *
  1109.  * Revision 1.66  2004/05/03 12:49:28  dicuccio
  1110.  * gui/utils --> gui/objutils where needed
  1111.  *
  1112.  * Revision 1.65  2004/04/07 12:47:31  dicuccio
  1113.  * Use TConstScopedObjects instead of CSelectionBuffer::TSelList.  Changed
  1114.  * CallPlugin API to include an IReporter interface.
  1115.  *
  1116.  * Revision 1.64  2004/03/08 20:21:05  jcherry
  1117.  * Fixed object argument clearing
  1118.  *
  1119.  * Revision 1.63  2004/02/04 14:09:04  dicuccio
  1120.  * Enable clearing of objects
  1121.  *
  1122.  * Revision 1.62  2004/02/03 23:08:13  ucko
  1123.  * Temporarily remove call to ClearObjects, which doesn't seem to be
  1124.  * implemented yet.
  1125.  *
  1126.  * Revision 1.61  2004/02/03 21:24:31  dicuccio
  1127.  * Clear objects from plugin argument sets prior to filling with new objects
  1128.  *
  1129.  * Revision 1.60  2004/01/30 17:18:11  dicuccio
  1130.  * Moved most of GetLabel() to CSeqUtils - CPluginUtils::GetLabel() only handles
  1131.  * IDocument directly
  1132.  *
  1133.  * Revision 1.59  2004/01/21 12:38:18  dicuccio
  1134.  * redesigned CObjectCOnverter API to eliminate temporary object creation
  1135.  *
  1136.  * Revision 1.58  2004/01/20 18:13:28  dicuccio
  1137.  * Make sure to check for bioseq handle validity before requesting information
  1138.  * from it
  1139.  *
  1140.  * Revision 1.57  2004/01/15 22:50:17  jcherry
  1141.  * Added FinalizeArgs() for plugins
  1142.  *
  1143.  * Revision 1.56  2004/01/07 15:48:10  dicuccio
  1144.  * Renamed GetObjectLabel() to GetLabel().  Dropped use of CSeq_loc::GetLabel() in
  1145.  * favor of internal location processing
  1146.  *
  1147.  * Revision 1.55  2004/01/05 19:10:31  dicuccio
  1148.  * Move comment marker
  1149.  *
  1150.  * Revision 1.54  2003/12/22 19:21:16  dicuccio
  1151.  * GetObjectLabel(): format a nicer string for seq-ids when possible
  1152.  *
  1153.  * Revision 1.53  2003/11/26 17:08:22  dicuccio
  1154.  * Fixed two thinkos:
  1155.  * - in s_CallPlugin(), check to make sure the plugin handle is valid before
  1156.  *   calling FillDefaults()
  1157.  * - make sure that FillArgs() doesn't dereference a NULL pointer
  1158.  *
  1159.  * Revision 1.52  2003/11/18 17:44:31  dicuccio
  1160.  * Added new API for FitArgs() to take a set of CPluginValue objects
  1161.  *
  1162.  * Revision 1.51  2003/11/06 20:04:56  dicuccio
  1163.  * Added context parameter to PluginMessage.  Added APIs to CallPlugin() to permit
  1164.  * passing the context parameter
  1165.  *
  1166.  * Revision 1.50  2003/11/04 17:19:41  dicuccio
  1167.  * Made templateed calls to registry private.  Changed to match API change in
  1168.  * CPluginMessage.
  1169.  *
  1170.  * Revision 1.49  2003/10/27 17:39:54  dicuccio
  1171.  * Changed to match new API for CPluginValue variant
  1172.  *
  1173.  * Revision 1.48  2003/10/23 16:18:09  dicuccio
  1174.  * Fixed to match API change for CPluginArgDialog
  1175.  *
  1176.  * Revision 1.47  2003/10/15 18:28:45  dicuccio
  1177.  * Added handling for new constraint types
  1178.  *
  1179.  * Revision 1.46  2003/10/10 17:15:58  dicuccio
  1180.  * Changed protoypes for CanFitArgs() - take optional conversion cache
  1181.  *
  1182.  * Revision 1.45  2003/10/10 15:57:28  friedman
  1183.  * Changed all CPluginUtils::Convert to use CObjectConverter::Convert.
  1184.  * Label for SeqFeat changed to include the document id and document short title.
  1185.  *
  1186.  * Revision 1.44  2003/10/07 13:36:09  dicuccio
  1187.  * Renamed CPluginURL* to CPluginValue*.  Moved validation code into CPluginUtils
  1188.  *
  1189.  * Revision 1.43  2003/10/01 12:07:35  ucko
  1190.  * +<algorithm> for find()
  1191.  *
  1192.  * Revision 1.42  2003/09/16 14:02:07  dicuccio
  1193.  * Replaced conversion code with calls to new class (CObjectConverter)
  1194.  *
  1195.  * Revision 1.41  2003/09/04 14:01:51  dicuccio
  1196.  * Introduce IDocument and IView as abstract base classes for CDocument and CView
  1197.  *
  1198.  * Revision 1.40  2003/09/02 20:36:26  dicuccio
  1199.  * Corrected x_DocToSeqAnnot to handle the case of a seq-annot-as-document
  1200.  *
  1201.  * Revision 1.39  2003/08/28 15:55:51  ucko
  1202.  * GetObjectLabel: return CNcbiOstrstreamToString(label) rather than
  1203.  * label.str() to ensure proper cleanup and termination.
  1204.  *
  1205.  * Revision 1.38  2003/08/28 00:09:08  ucko
  1206.  * x_SeqLocToSeqAnnot: adjust for latest objmgr API.
  1207.  *
  1208.  * Revision 1.37  2003/08/22 17:28:10  dicuccio
  1209.  * FIxed seq-annot conversions - all now pass through x_SeqLocToSeqAnnot
  1210.  *
  1211.  * Revision 1.36  2003/08/22 17:05:05  dicuccio
  1212.  * Temporary compilation fix: disable annotation conversion
  1213.  *
  1214.  * Revision 1.35  2003/08/22 15:45:12  dicuccio
  1215.  * Removed a number of unnecessary _TRACE() statemens
  1216.  *
  1217.  * Revision 1.34  2003/08/19 18:52:16  friedman
  1218.  * Added the follwing conversion functionclality to Convert:
  1219.  *     doc -> seq-annot, bioseq -> seq-annot, seq-id -> seq-annot,
  1220.  *     seq-loc -> seq-annot, seq-entry -> seq-annot, doc -> seq-align
  1221.  *
  1222.  * Added seq-annot and seq-align label formatting to GetObjectLabel
  1223.  *
  1224.  * Revision 1.33  2003/08/18 19:16:47  dicuccio
  1225.  * Fixed another (hopefully last!) thinko in CanFitArgs() - must pass the logic
  1226.  * "return true if any of our selections matches an object argument or if there
  1227.  * are no object arguments"
  1228.  *
  1229.  * Revision 1.32  2003/08/15 19:34:33  dicuccio
  1230.  * Added early break to loop on failure
  1231.  *
  1232.  * Revision 1.31  2003/08/13 13:33:23  dicuccio
  1233.  * Fixed another thinko - always pass objects regardless of whether the argument is of type single or of type array
  1234.  *
  1235.  * Revision 1.30  2003/08/12 21:41:24  ucko
  1236.  * Fix typo
  1237.  *
  1238.  * Revision 1.29  2003/08/12 19:51:23  dicuccio
  1239.  * Fixed thinko in CanFitArgs() - rather than return false for any failure, return
  1240.  * true for any success
  1241.  *
  1242.  * Revision 1.28  2003/08/11 19:26:21  dicuccio
  1243.  * Favor member insert to std::copy()
  1244.  *
  1245.  * Revision 1.27  2003/08/06 14:38:55  friedman
  1246.  * Add Seq-entry label formatting to GetObjectLabel
  1247.  *
  1248.  * Revision 1.26  2003/08/05 17:07:15  dicuccio
  1249.  * Changed calling semantics for the message queue - pass by reference, not
  1250.  * CConstRef<>
  1251.  *
  1252.  * Revision 1.25  2003/07/31 16:56:06  dicuccio
  1253.  * Changed name of plugin message queue.  Correctly account for hidden arguments
  1254.  * to plugins.
  1255.  *
  1256.  * Revision 1.24  2003/07/24 13:12:29  dicuccio
  1257.  * Added basic bioseq conversion routines
  1258.  *
  1259.  * Revision 1.23  2003/07/23 19:14:08  dicuccio
  1260.  * Moved logic for validating plugin arguments into CPluginUtils.
  1261.  *
  1262.  * Revision 1.22  2003/07/22 17:01:14  dicuccio
  1263.  * Fixed compilation error - return TObjList instead of NULL
  1264.  *
  1265.  * Revision 1.21  2003/07/22 15:29:54  dicuccio
  1266.  * Dropped CSeqVector as an explicitly managed type.  Changed Convert() to perform
  1267.  * a one-to-many conversion
  1268.  *
  1269.  * Revision 1.20  2003/07/21 19:29:17  dicuccio
  1270.  * Changed to match API changes in CSelectionBuffer.  Added CanFitArgs() version
  1271.  * to work with selection buffers
  1272.  *
  1273.  * Revision 1.19  2003/07/17 03:20:19  friedman
  1274.  * Added passing in a TConstScopedObjects to CPluginArgDialog
  1275.  *
  1276.  * Revision 1.18  2003/07/14 11:01:20  shomrat
  1277.  * Plugin messageing system related changes
  1278.  *
  1279.  * Revision 1.17  2003/06/30 13:33:41  dicuccio
  1280.  * Added API to call a plugin with a raw CPluginRequest object
  1281.  *
  1282.  * Revision 1.16  2003/06/25 17:02:54  dicuccio
  1283.  * Split CPluginHandle into a handle (pointer-to-implementation) and
  1284.  * implementation file.  Lots of #include file clean-ups.
  1285.  *
  1286.  * Revision 1.15  2003/06/02 16:06:17  dicuccio
  1287.  * Rearranged src/objects/ subtree.  This includes the following shifts:
  1288.  *     - src/objects/asn2asn --> arc/app/asn2asn
  1289.  *     - src/objects/testmedline --> src/objects/ncbimime/test
  1290.  *     - src/objects/objmgr --> src/objmgr
  1291.  *     - src/objects/util --> src/objmgr/util
  1292.  *     - src/objects/alnmgr --> src/objtools/alnmgr
  1293.  *     - src/objects/flat --> src/objtools/flat
  1294.  *     - src/objects/validator --> src/objtools/validator
  1295.  *     - src/objects/cddalignview --> src/objtools/cddalignview
  1296.  * In addition, libseq now includes six of the objects/seq... libs, and libmmdb
  1297.  * replaces the three libmmdb? libs.
  1298.  *
  1299.  * Revision 1.14  2003/05/19 13:35:59  dicuccio
  1300.  * Moved gui/core/plugin/ -> gui/plugin/.  Merged gui/core/algo, gui/core/doc/,
  1301.  * and gui/core/view/ into one library (gui/core/)
  1302.  *
  1303.  * Revision 1.13  2003/05/06 15:55:16  dicuccio
  1304.  * Dropped identity object conversion in favor of a generic approach
  1305.  *
  1306.  * Revision 1.12  2003/05/05 12:42:48  dicuccio
  1307.  * Added new interface function (CanFitArgs()) to determine if a given set of
  1308.  * objects could possibly apply to a set of arguments
  1309.  *
  1310.  * Revision 1.11  2003/05/01 12:53:36  dicuccio
  1311.  * Added conversion routines for {doc,seq-id,seq-loc,seq-feat} --> seq-entry
  1312.  *
  1313.  * Revision 1.10  2003/04/29 14:44:16  dicuccio
  1314.  * Fixed bungled commit - deleted dead, poorly formatted code that affected
  1315.  * indentation
  1316.  *
  1317.  * Revision 1.9  2003/04/29 14:42:43  dicuccio
  1318.  * Changed SelectionsToArgs() -> FillArgs().  Added API for filling arguments
  1319.  * based solely on the contents of a document.  Made main type conversion
  1320.  * routine public.  Added API for converting objects based on CTypeInfo.  Added
  1321.  * prototype function for conversion of an argument to a vector of strings.
  1322.  *
  1323.  * Revision 1.8  2003/04/24 16:31:07  dicuccio
  1324.  * Large changes.  Added many new interface functions for objects
  1325.  * cast/conversion.  Changed SelBufferToArgs() -> more generic FillArgs().
  1326.  * Changed internals of filling out plugin arguments automatically to avoid
  1327.  * faulty assumptions about argument contents.
  1328.  *
  1329.  * Revision 1.7  2003/04/16 18:21:27  dicuccio
  1330.  * Added generic plugin launch mechanism (CallPlugin()).  Modified
  1331.  * document-to-argument resolution to permit empty documents to be passed as
  1332.  * documents
  1333.  *
  1334.  * Revision 1.6  2003/03/25 13:11:32  dicuccio
  1335.  * Changed FillArgs() to return the number of unset arguments
  1336.  *
  1337.  * Revision 1.5  2003/03/10 22:58:51  kuznets
  1338.  * iterate -> ITERATE
  1339.  *
  1340.  * Revision 1.4  2003/02/26 14:24:36  dicuccio
  1341.  * Major rewrite of selection-to-argument handling code - most cases should be
  1342.  * handled automatically now, but there is still no manual fall-back.
  1343.  *
  1344.  * Revision 1.3  2003/02/25 14:46:52  dicuccio
  1345.  * Intermediate fix.  Still not working, but at least it compiles.
  1346.  *
  1347.  * Revision 1.2  2003/02/24 13:03:15  dicuccio
  1348.  * Renamed classes in plugin spec:
  1349.  *     CArgSeg --> CPluginArgSet
  1350.  *     CArgument --> CPluginArg
  1351.  *     CPluginArgs --> CPluginCommand
  1352.  *     CPluginCommands --> CPluginCommandSet
  1353.  *
  1354.  * Revision 1.1  2003/02/20 19:49:56  dicuccio
  1355.  * Created new plugin architecture, based on ASN.1 spec.  Moved GBENCH frameowrk
  1356.  * over to use new plugin architecture.
  1357.  *
  1358.  * ===========================================================================
  1359.  */
  1360.