plugin_utils.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:53k
- /*
- * ===========================================================================
- * PRODUCTION $Log: plugin_utils.cpp,v $
- * PRODUCTION Revision 1000.5 2004/06/01 20:44:35 gouriano
- * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.69
- * PRODUCTION
- * ===========================================================================
- */
- /* $Id: plugin_utils.cpp,v 1000.5 2004/06/01 20:44:35 gouriano Exp $
- * ===========================================================================
- *
- * PUBLIC DOMAIN NOTICE
- * National Center for Biotechnology Information
- *
- * This software/database is a "United States Government Work" under the
- * terms of the United States Copyright Act. It was written as part of
- * the author's official duties as a United States Government employee and
- * thus cannot be copyrighted. This software/database is freely available
- * to the public for use. The National Library of Medicine and the U.S.
- * Government have not placed any restriction on its use or reproduction.
- *
- * Although all reasonable efforts have been taken to ensure the accuracy
- * and reliability of the software and data, the NLM and the U.S.
- * Government do not and cannot warrant the performance or results that
- * may be obtained by using this software or data. The NLM and the U.S.
- * Government disclaim all warranties, express or implied, including
- * warranties of performance, merchantability or fitness for any particular
- * purpose.
- *
- * Please cite the author in any work or product based on this material.
- *
- * ===========================================================================
- *
- * Authors: Mike DiCuccio
- *
- * File Description:
- * CPluginUtils -- utilities for managing the interface between the plugin
- * architecture and the GBENCH framework
- */
- #include <ncbi_pch.hpp>
- #include <gui/core/idocument.hpp>
- #include <gui/core/obj_convert.hpp>
- #include <gui/plugin/PluginValue.hpp>
- #include <gui/plugin/PluginValueConstraint.hpp>
- #include <gui/plugin/PluginValueRangeConstraint.hpp>
- #include <gui/plugin/PluginReply.hpp>
- #include <gui/plugin/PluginMessage.hpp>
- #include <gui/core/plugin_registry.hpp>
- #include <gui/core/plugin_utils.hpp>
- #include <gui/core/message_queue.hpp>
- #include <gui/core/doc_manager.hpp>
- #include <gui/objutils/label.hpp>
- #include <gui/utils/message_box.hpp>
- #include <gui/core/plugin_arg_dialog.hpp>
- #include <serial/iterator.hpp>
- #include <objects/seq/Bioseq.hpp>
- #include <objects/seq/Seq_annot.hpp>
- #include <objects/seqloc/Seq_loc.hpp>
- #include <objects/seqloc/Seq_point.hpp>
- #include <objects/seqset/Seq_entry.hpp>
- #include <objects/seqset/Seq_entry.hpp>
- #include <objects/seqalign/Seq_align.hpp>
- #include <objmgr/seq_vector.hpp>
- #include <objmgr/util/sequence.hpp>
- #include <objmgr/util/feature.hpp>
- #include <objmgr/annot_selector.hpp>
- #include <objmgr/annot_ci.hpp>
- #include <objmgr/align_ci.hpp>
- #include <algorithm>
- BEGIN_NCBI_SCOPE
- USING_SCOPE(objects);
- // simple functor to return the best argument in a list of arguments
- // 'best' is determined by a simple user-supplied rank
- struct SChoiceRank
- {
- const vector<int>& m_Ranks;
- SChoiceRank(const vector<int>& ranks)
- : m_Ranks(ranks) {}
- int operator() (CConstRef<CPluginArg> arg) const
- {
- if ( !arg ) {
- return m_Ranks.size();
- }
- return m_Ranks[ arg->GetType() ];
- }
- };
- //
- // call a plugin by name, passing in a selection buffer
- //
- template <class Command>
- void s_CallPlugin(const string& plugin_name, Command cmd,
- const CSelectionBuffer& selections,
- IReporter* reporter,
- const string& ctx_name,
- CPluginUtils::EDispatchWhen when)
- {
- // prepare a plugin message to handle our command
- CRef<objects::CPluginMessage> msg(new objects::CPluginMessage());
- msg->SetDestination(plugin_name);
- if ( !ctx_name.empty() ) {
- msg->SetContext(ctx_name);
- }
- msg->SetReporter(reporter);
- objects::CPluginRequest& request = msg->SetRequest();
- objects::CPluginCommand& args = request.SetCommand(cmd);
- // don't forget to fill in our default arguments
- CPluginHandle handle =
- CPluginRegistry::GetPlugin(plugin_name);
- if ( !handle ) {
- LOG_POST(Error << "CallPlugin(): failed to find plugin named "
- << plugin_name);
- return;
- }
- handle.FillDefaults(cmd, args);
- // now, pass off to internal processing
- CPluginUtils::CallPlugin(*msg, selections.DecomposeToPairs(), when);
- }
- //
- // call a plugin by name, passing in a document
- //
- template <class Command>
- void s_CallPlugin(const string& plugin_name, Command cmd,
- const IDocument* doc,
- IReporter* reporter,
- const string& ctx_name,
- CPluginUtils::EDispatchWhen when)
- {
- CRef<CSelectionBuffer> buffer(new CSelectionBuffer());
- if (doc) {
- buffer->AddSelection(const_cast<IDocument*>(doc));
- }
- // pass off to a more intelligent CallPlugin() command
- CPluginUtils::CallPlugin(plugin_name, cmd, *buffer,
- reporter, ctx_name, when);
- }
- void CPluginUtils::CallPlugin(const string& name, EAlgoCommand cmd,
- const CSelectionBuffer& buffer,
- IReporter* reporter,
- const string& ctx_name,
- EDispatchWhen when)
- {
- s_CallPlugin(name, cmd, buffer, reporter, ctx_name, when);
- }
- void CPluginUtils::CallPlugin(const string& name, EDataCommand cmd,
- const CSelectionBuffer& buffer,
- IReporter* reporter,
- const string& ctx_name,
- EDispatchWhen when)
- {
- s_CallPlugin(name, cmd, buffer, reporter, ctx_name, when);
- }
- void CPluginUtils::CallPlugin(const string& name, EViewCommand cmd,
- const CSelectionBuffer& buffer,
- IReporter* reporter,
- const string& ctx_name,
- EDispatchWhen when)
- {
- s_CallPlugin(name, cmd, buffer, reporter, ctx_name, when);
- }
- void CPluginUtils::CallPlugin(const string& name, EAlgoCommand cmd,
- const IDocument* doc,
- IReporter* reporter,
- const string& ctx_name,
- EDispatchWhen when)
- {
- s_CallPlugin(name, cmd, doc, reporter, ctx_name, when);
- }
- void CPluginUtils::CallPlugin(const string& name, EDataCommand cmd,
- const IDocument* doc,
- IReporter* reporter,
- const string& ctx_name,
- EDispatchWhen when)
- {
- s_CallPlugin(name, cmd, doc, reporter, ctx_name, when);
- }
- void CPluginUtils::CallPlugin(const string& name, EViewCommand cmd,
- const IDocument* doc,
- IReporter* reporter,
- const string& ctx_name,
- EDispatchWhen when)
- {
- s_CallPlugin(name, cmd, doc, reporter, ctx_name, when);
- }
- //
- // internal handler for plugin requests that use the CPluginMessage interface
- //
- void CPluginUtils::CallPlugin(CPluginMessage& msg,
- EDispatchWhen when)
- {
- switch (when) {
- case eDispatch_Deferred:
- // now, place the request message in the message queue.
- CPluginMessageQueue::Add(msg);
- break;
- case eDispatch_Now:
- CPluginMessageQueue::ProcessMessage(msg);
- break;
- }
- }
- //
- // internal handler for all plugin requests
- //
- void CPluginUtils::CallPlugin(CPluginMessage& msg,
- const TConstScopedObjects& selections,
- EDispatchWhen when)
- {
- try {
- // first, fill our default values
- string plugin_name = msg.GetDestination();
- CPluginHandle handle = CPluginRegistry::GetPlugin(plugin_name);
- CPluginRequest& request = msg.SetRequest();
- CPluginCommand& cmd = request.SetCommand();
- CPluginArgSet& args = cmd.SetArgs();
- // give the plugin the opportunity to modify it aguments
- handle.FinalizeArgs(msg);
- // now, try and add any object arguments to our list
- if ( FillArgs(args, selections) || !CPluginUtils::IsValid(args) ) {
- // we have remaining arguments that need to be addressed
- // pop up a form dialog to handle these
- CPluginArgDialog dlg(handle, args, selections);
- if (dlg.ShowModal() == eCancel) {
- msg.SetReply().SetStatus(eMessageStatus_ignored);
- return;
- }
- }
- // now, place the request message in the message queue.
- CallPlugin(msg, when);
- }
- catch (CException& e) {
- NcbiMessageBox("Failed to execute plugin:n" + e.GetMsg());
- }
- catch (exception& e) {
- NcbiMessageBox(string("Failed to execute plugin:n") + e.what());
- }
- #ifndef _DEBUG
- catch (...) {
- NcbiMessageBox("Failed to execute plugin:nUnknown error");
- }
- #endif
- }
- //
- // verify that a set of arguments is valid
- //
- bool CPluginUtils::IsValid(const CPluginArgSet& arg)
- {
- ITERATE(CPluginArgSet::Tdata, iter, arg.Get()) {
- if ( !IsValid(**iter) ) {
- return false;
- }
- }
- return true;
- }
- //
- // verify that a given argument's values are consistent with the argument's
- // specifications
- //
- bool CPluginUtils::IsValid(const CPluginArg& arg)
- {
- if (arg.IsSetHidden() && arg.GetHidden()) {
- // hidden arguments are ignored for the sake of validity
- return true;
- }
- CTypeConstIterator<CPluginValue> iter(arg);
- if ( !iter ) {
- return false;
- }
- CPluginValue::E_Choice type = iter->Which();
- string subtype = iter->GetObjectSubtype();
- for ( ; iter; ++iter) {
- if (iter->Which() != type ||
- iter->GetObjectSubtype() != subtype) {
- return false;
- }
- if ( !IsValid(*iter) ) {
- return false;
- }
- }
- return CheckConstraints(arg);
- }
- //
- // verify that a single plugin value is valid
- //
- bool CPluginUtils::IsValid(const CPluginValue& val)
- {
- switch (val.Which()) {
- default:
- case CPluginValue::e_not_set:
- return false;
- case CPluginValue::e_Integer:
- case CPluginValue::e_String:
- case CPluginValue::e_Double:
- case CPluginValue::e_Boolean:
- case CPluginValue::e_File:
- return !val.IsEmpty();
- case CPluginValue::e_Document:
- {{
- const IDocument* doc = val.GetDocument();
- const CObject* obj = val.GetObject();
- if ( !doc || !obj ) {
- return false;
- }
- doc = dynamic_cast<const IDocument*>(obj);
- if ( !doc ) {
- return false;
- }
- return true;
- }}
- break;
- case CPluginValue::e_Object:
- {{
- const IDocument* doc = val.GetDocument();
- const CObject* obj = val.GetObject();
- if ( !doc || !obj ) {
- return false;
- }
- if (val.GetObjectSubtype() == "Document") {
- doc = dynamic_cast<const IDocument*>(obj);
- if ( !doc ) {
- return false;
- }
- return true;
- } else if (val.GetObjectSubtype() == "Object") {
- return true;
- } else {
- const CSerialObject* o =
- dynamic_cast<const CSerialObject*>(obj);
- if (o) {
- return (val.GetObjectSubtype() ==
- o->GetThisTypeInfo()->GetName());
- } else {
- return false;
- }
- }
- }}
- break;
- }
- return true;
- }
- //
- // check to see that a plugin argument's values match a plugin
- // argument's constraints
- //
- bool CPluginUtils::CheckConstraints(const CPluginArg& arg,
- CConvertCache* cache)
- {
- // we always succeed if the constraint is not set
- if ( !arg.IsSetConstraint() || arg.GetConstraint().size() == 0) {
- return true;
- }
- switch (arg.GetType()) {
- case CPluginArg::eInteger:
- if (arg.GetConstraint().size() > 1) {
- // we support only a single constraint for built-in types
- LOG_POST(Error <<
- "CPluginArg::CheckConstraint(): "
- "built-in types support only one concurrent constraint");
- return false;
- } else {
- const CPluginValueConstraint& cons = *arg.GetConstraint().front();
- //
- // integral types may be constrained by lower, upper, range,
- // or set constraints
- //
- switch (cons.Which()) {
- case CPluginValueConstraint::e_Lower:
- // greater than or equal to the lower range
- return (arg.AsInteger() >=
- NStr::StringToInt(cons.GetLower()));
- case CPluginValueConstraint::e_Upper:
- // less than or equal to the lower range
- return (arg.AsInteger() <=
- NStr::StringToInt(cons.GetUpper()));
- case CPluginValueConstraint::e_Range:
- // bounded by the range of values specified
- {{
- int val = arg.AsInteger();
- int lower =
- NStr::StringToInt(cons.GetRange().GetLower());
- if (val < lower) {
- return false;
- }
- int upper =
- NStr::StringToInt(cons.GetRange().GetUpper());
- return (val <= upper);
- }}
- case CPluginValueConstraint::e_Set:
- // must match an item in the set
- // FIXME: we use a linear scan here
- {{
- int val = arg.AsInteger();
- string val_str = NStr::IntToString(val);
- CPluginValueConstraint::TSet::const_iterator iter =
- std::find(cons.GetSet().begin(),
- cons.GetSet().end(),
- val_str);
- return (iter != cons.GetSet().end());
- }}
- default:
- LOG_POST(Error <<
- "CPluginArg::CheckConstraint(): "
- "invalid constraint type for " <<
- arg.GetName() << ": " << (int)cons.Which());
- return false;
- }
- }
- break;
- case CPluginArg::eDouble:
- if (arg.GetConstraint().size() > 1) {
- // we support only a single constraint for built-in types
- LOG_POST(Error <<
- "CPluginArg::CheckConstraint(): "
- "built-in types support only one concurrent constraint");
- return false;
- } else {
- const CPluginValueConstraint& cons = *arg.GetConstraint().front();
- //
- // real types may be constrained by lower, upper, range, or set
- // constraints
- //
- switch (cons.Which()) {
- case CPluginValueConstraint::e_Lower:
- // greater than or equal to the lower range
- return (arg.AsDouble() >=
- NStr::StringToDouble(cons.GetLower()));
- case CPluginValueConstraint::e_Upper:
- // less than or equal to the lower range
- return (arg.AsDouble() <=
- NStr::StringToDouble(cons.GetUpper()));
- case CPluginValueConstraint::e_Range:
- // bounded by the range of values specified
- {{
- double val = arg.AsDouble();
- double lower =
- NStr::StringToDouble(cons.GetRange().GetLower());
- if (val < lower) {
- return false;
- }
- double upper =
- NStr::StringToDouble(cons.GetRange().GetUpper());
- return (val <= upper);
- }}
- case CPluginValueConstraint::e_Set:
- // must match an item in the set
- // FIXME: we use a linear scan here
- {{
- double val = arg.AsDouble();
- string val_str = NStr::DoubleToString(val);
- CPluginValueConstraint::TSet::const_iterator iter =
- std::find(cons.GetSet().begin(),
- cons.GetSet().end(),
- val_str);
- return (iter != cons.GetSet().end());
- }}
- default:
- LOG_POST(Error <<
- "CPluginArg::CheckConstraint(): "
- "invalid constraint type for " <<
- arg.GetName() << ": " << (int)cons.Which());
- return false;
- }
- }
- break;
- case CPluginArg::eString:
- if (arg.GetConstraint().size() > 1) {
- // we support only a single constraint for built-in types
- LOG_POST(Error <<
- "CPluginArg::CheckConstraint(): "
- "built-in types support only one concurrent constraint");
- return false;
- } else {
- const CPluginValueConstraint& cons = *arg.GetConstraint().front();
- //
- // integral types may be constrained by lower, upper, range, or set
- // constraints
- //
- switch (cons.Which()) {
- case CPluginValueConstraint::e_Lower:
- // greater than or equal to the lower range
- return (arg.AsString() >= cons.GetLower());
- case CPluginValueConstraint::e_Upper:
- // less than or equal to the lower range
- return (arg.AsString() <= cons.GetUpper());
- case CPluginValueConstraint::e_Range:
- // bounded by the range of values specified
- {{
- string val = arg.AsString();
- string lower = cons.GetRange().GetLower();
- if (val < lower) {
- return false;
- }
- string upper = cons.GetRange().GetUpper();
- return (val <= upper);
- }}
- case CPluginValueConstraint::e_Set:
- // must match an item in the set
- // FIXME: we use a linear scan here
- {{
- string val = arg.AsString();
- CPluginValueConstraint::TSet::const_iterator iter =
- std::find(cons.GetSet().begin(),
- cons.GetSet().end(),
- val);
- return (iter != cons.GetSet().end());
- }}
- default:
- LOG_POST(Error <<
- "CPluginArg::CheckConstraint(): "
- "invalid constraint type for " <<
- arg.GetName() << ": " << (int)cons.Which());
- return false;
- }
- }
- break;
- case CPluginArg::eBoolean:
- // no constraints make sense for boolean arguments
- LOG_POST(Error << "CPluginArg::CheckConstraint(): "
- "constraints are invalid for Boolean arguments");
- return false;
- case CPluginArg::eObject:
- case CPluginArg::eDocument:
- {{
- CTypeConstIterator<CPluginValue> iter(arg);
- for ( ; iter; ++iter) {
- const CObject* obj = iter->GetObject();
- const IDocument* doc = iter->GetDocument();
- if ( !obj || !doc ) {
- return false;
- }
- CScope& scope = doc->GetScope();
- if ( !CheckConstraints(arg, scope, *obj, cache) ) {
- return false;
- }
- }
- return true;
- }}
- default:
- LOG_POST(Error << "CPluginUtils::CheckConstraint(): "
- "unhandled argument type");
- break;
- }
- return false;
- }
- bool CPluginUtils::CheckConstraints(const CPluginArg& arg,
- CScope& scope,
- const CObject& obj,
- CConvertCache* cache)
- {
- //
- // we may have multiple constraints, to answer questions such as "Give
- // me all sequences that are proteins of at least 100 bases" and "Give
- // me a set of sequences, all of the same molecule type, that are of
- // sequence type raw"
- //
- ITERATE (CPluginArg::TConstraint, c_iter, arg.GetConstraint()) {
- const CPluginValueConstraint& cons = **c_iter;
- switch (cons.Which()) {
- //
- // constraints for bioseq types
- //
- case CPluginValueConstraint::e_Seq_repr:
- // constrain the sequence representation to be of a certain type
- {{
- CObjConverter::TObjList bioseqs;
- CObjectConverter::Convert(scope, obj, CBioseq::GetTypeInfo(),
- bioseqs);
- ITERATE(CObjConverter::TObjList, iter, bioseqs) {
- const CBioseq* bioseq =
- dynamic_cast<const CBioseq*>(iter->GetPointer());
- if ( !bioseq ) {
- return false;
- }
- if (std::find(cons.GetSeq_repr().begin(),
- cons.GetSeq_repr().end(),
- bioseq->GetInst().GetRepr()) ==
- cons.GetSeq_repr().end() ) {
- return false;
- }
- }
- }}
- break;
- case CPluginValueConstraint::e_Seq_mol:
- // constrain the molecule type to be of a certain type
- {{
- CObjConverter::TObjList bioseqs;
- CObjectConverter::Convert(scope, obj, CBioseq::GetTypeInfo(),
- bioseqs);
- ITERATE(CObjConverter::TObjList, iter, bioseqs) {
- const CBioseq* bioseq =
- dynamic_cast<const CBioseq*>(iter->GetPointer());
- if ( !bioseq ) {
- return false;
- }
- if (std::find(cons.GetSeq_mol().begin(),
- cons.GetSeq_mol().end(),
- bioseq->GetInst().GetMol()) ==
- cons.GetSeq_mol().end() ) {
- return false;
- }
- }
- }}
- break;
- case CPluginValueConstraint::e_Seq_mol_same_type:
- // constrain a set of values such that their molecule types are all
- // the same
- {{
- const CBioseq* prev = NULL;
- CObjConverter::TObjList bioseqs;
- CObjectConverter::Convert(scope, obj, CBioseq::GetTypeInfo(),
- bioseqs);
- ITERATE(CObjConverter::TObjList, iter, bioseqs) {
- const CBioseq* bioseq =
- dynamic_cast<const CBioseq*>(iter->GetPointer());
- if ( !bioseq ) {
- return false;
- }
- if ( !prev ) {
- prev = bioseq;
- } else {
- if (prev->GetInst().GetMol() !=
- bioseq->GetInst().GetMol()) {
- return false;
- }
- }
- }
- }}
- break;
- case CPluginValueConstraint::e_Seq_length_lower:
- // constrain a set of sequences such that their lengths are at
- // least some bound
- {{
- TSeqPos min_len = cons.GetSeq_length_lower();
- CObjConverter::TObjList bioseqs;
- CObjectConverter::Convert(scope, obj, CBioseq::GetTypeInfo(),
- bioseqs);
- ITERATE(CObjConverter::TObjList, iter, bioseqs) {
- const CBioseq* bioseq =
- dynamic_cast<const CBioseq*>(iter->GetPointer());
- if ( !bioseq ) {
- return false;
- }
- if (bioseq->GetInst().GetLength() < min_len) {
- return false;
- }
- }
- }}
- break;
- case CPluginValueConstraint::e_Seq_length_upper:
- // constrain a set of sequences such that their lengths are no
- // greater than some bound
- {{
- TSeqPos max_len = cons.GetSeq_length_upper();
- CObjConverter::TObjList bioseqs;
- CObjectConverter::Convert(scope, obj, CBioseq::GetTypeInfo(),
- bioseqs);
- ITERATE(CObjConverter::TObjList, iter, bioseqs) {
- const CBioseq* bioseq =
- dynamic_cast<const CBioseq*>(iter->GetPointer());
- if ( !bioseq ) {
- return false;
- }
- if (bioseq->GetInst().GetLength() > max_len) {
- return false;
- }
- }
- }}
- break;
- case CPluginValueConstraint::e_Seq_length_range:
- // constrain a set of sequences such that their lengths are at
- // least some bound
- {{
- TSeqPos min_len =
- NStr::StringToInt(cons.GetSeq_length_range().GetLower());
- TSeqPos max_len =
- NStr::StringToInt(cons.GetSeq_length_range().GetUpper());
- CObjConverter::TObjList bioseqs;
- CObjectConverter::Convert(scope, obj, CBioseq::GetTypeInfo(),
- bioseqs);
- ITERATE(CObjConverter::TObjList, iter, bioseqs) {
- const CBioseq* bioseq =
- dynamic_cast<const CBioseq*>(iter->GetPointer());
- if ( !bioseq ) {
- return false;
- }
- if (bioseq->GetInst().GetLength() < min_len ||
- bioseq->GetInst().GetLength() > max_len) {
- return false;
- }
- }
- }}
- break;
- case CPluginValueConstraint::e_Seq_length_same:
- _TRACE("x_CheckObjectConstraint(): failed: "
- "seq-inst.length: same length constraint not implemented");
- break;
- //
- // constraints for seq-entry types
- //
- case CPluginValueConstraint::e_Entry_type:
- // constrain a set of values such that their molecule types are all
- // the same
- {{
- CObjConverter::TObjList entries;
- CObjectConverter::Convert(scope, obj,
- CSeq_entry::GetTypeInfo(), entries);
- ITERATE(CObjConverter::TObjList, iter, entries) {
- const CSeq_entry* entry=
- dynamic_cast<const CSeq_entry*>(iter->GetPointer());
- if ( !entry ) {
- return false;
- }
- if ( !entry->IsSet() ||
- !entry->GetSet().IsSetClass() ||
- !entry->GetSet().GetClass() == cons.GetEntry_type()) {
- return false;
- }
- }
- }}
- break;
- //
- // constraints for seq-annot types
- //
- case CPluginValueConstraint::e_Annot_type:
- // constrain the sequence representation to be of a certain type
- {{
- CObjConverter::TObjList annots;
- CObjectConverter::Convert(scope, obj,
- CSeq_annot::GetTypeInfo(), annots);
- ITERATE(CObjConverter::TObjList, iter, annots) {
- const CSeq_annot* annot=
- dynamic_cast<const CSeq_annot*>(iter->GetPointer());
- if ( !annot ) {
- return false;
- }
- if (annot->GetData().Which() != cons.GetAnnot_type()) {
- return false;
- }
- }
- }}
- break;
- //
- // constraints for seq-feat types
- //
- case CPluginValueConstraint::e_Feat_type:
- // constrain the sequence representation to be of a certain type
- {{
- CObjConverter::TObjList feats;
- CObjectConverter::Convert(scope, obj,
- CSeq_feat::GetTypeInfo(), feats);
- ITERATE(CObjConverter::TObjList, iter, feats) {
- const CSeq_feat* feat=
- dynamic_cast<const CSeq_feat*>(iter->GetPointer());
- if ( !feat ) {
- return false;
- }
- if (std::find(cons.GetFeat_type().begin(),
- cons.GetFeat_type().end(),
- feat->GetData().Which()) ==
- cons.GetFeat_type().end()) {
- return false;
- }
- }
- }}
- break;
- //
- // constraints for seq-feat subtypes
- //
- case CPluginValueConstraint::e_Feat_subtype:
- // constrain the sequence representation to be of a certain type
- {{
- CObjConverter::TObjList feats;
- CObjectConverter::Convert(scope, obj,
- CSeq_feat::GetTypeInfo(), feats);
- ITERATE(CObjConverter::TObjList, iter, feats) {
- const CSeq_feat* feat=
- dynamic_cast<const CSeq_feat*>(iter->GetPointer());
- if ( !feat ) {
- return false;
- }
- string label;
- feature::GetLabel(*feat, &label, feature::eBoth, &scope);
- if (std::find(cons.GetFeat_subtype().begin(),
- cons.GetFeat_subtype().end(),
- feat->GetData().GetSubtype()) ==
- cons.GetFeat_subtype().end()) {
- return false;
- }
- }
- }}
- break;
- //
- // constraints for seq-feats that have products set
- //
- case CPluginValueConstraint::e_Feat_has_product:
- // constrain the sequence representation to be of a certain type
- {{
- CObjConverter::TObjList feats;
- CObjectConverter::Convert(scope, obj,
- CSeq_feat::GetTypeInfo(), feats);
- ITERATE(CObjConverter::TObjList, iter, feats) {
- const CSeq_feat* feat=
- dynamic_cast<const CSeq_feat*>(iter->GetPointer());
- if ( !feat ) {
- return false;
- }
- if ( !feat->IsSetProduct() ) {
- return false;
- }
- }
- }}
- break;
- default:
- LOG_POST(Error <<
- "CPluginArg::CheckConstraint():"
- " unhandled constraint type: " << (int)cons.Which());
- return false;
- break;
- }
- }
- return true;
- }
- //
- // utility function to convert a set of selections into a set of arguments
- //
- int CPluginUtils::FillArgs(CPluginArgSet& args, const IDocument& doc)
- {
- TConstScopedObjects sels;
- sels.push_back(SConstScopedObject(doc, doc.GetScope()));
- return FillArgs(args, sels);
- }
- int CPluginUtils::FillArgs(CPluginArgSet& args,
- const CPluginArg::TData::TArray& objs)
- {
- // step 1: clear any object-based arguments
- NON_CONST_ITERATE (CPluginArgSet::Tdata, iter, args.Set()) {
- CPluginArg& arg = **iter;
- arg.ClearObjects();
- }
- CSelectionBuffer buffer;
- ITERATE (CPluginArg::TData::TArray, iter, objs) {
- const CPluginValue& val = **iter;
- if ( !val.GetObject() ) {
- continue;
- }
- if ( val.IsObject() ) {
- const CSerialObject* obj =
- dynamic_cast<const CSerialObject*>(val.GetObject());
- IDocument* doc =
- const_cast<IDocument*>(
- dynamic_cast<const IDocument*>(val.GetDocument()));
- if (obj && doc) {
- buffer.AddSelection(doc, *obj);
- }
- } else if ( val.IsDocument() ) {
- IDocument* doc =
- const_cast<IDocument*>(
- dynamic_cast<const IDocument*>(val.GetObject()));
- if (doc) {
- buffer.AddSelection(doc);
- }
- }
- }
- return FillArgs(args, buffer.DecomposeToPairs());
- }
- int CPluginUtils::FillArgs(CPluginArgSet& args,
- const TConstScopedObjects& sels)
- {
- // easy out: no arguments to fill
- if (args.Get().size() == 0) {
- return 0;
- }
- // we plan to handle one case automatically: the set of arguments has
- // one argument that takes a data model object. Other cases are left
- // to the user to clarify because these are too complex to guess
- int visible_args = 0;
- int obj_args = 0;
- CRef<CPluginArg> arg_to_fill;
- NON_CONST_ITERATE (CPluginArgSet::Tdata, iter, args.Set()) {
- CPluginArg& arg = **iter;
- if (arg.IsSetHidden() && arg.GetHidden()) {
- continue;
- }
- ++visible_args;
- CPluginArg::EType type = arg.GetType();
- if (type == CPluginArg::eObject ||
- type == CPluginArg::eDocument) {
- ++obj_args;
- // clear object argument
- arg.ClearObjects();
- arg_to_fill.Reset(&arg);
- }
- }
- // make sure we actually can address this argument
- if ( obj_args > 1 || !arg_to_fill ) {
- return visible_args;
- }
- // now, convert as many objects as possible into the requested format
- // here we plan to support automatic assignments to data model objects
- // only; CObject assignments can be made for these, but this must be
- // done under user direction
- switch (arg_to_fill->GetData().Which()) {
- case CPluginArg::TData::e_Single:
- //
- // make sure we have exactly one selection
- //
- if (sels.size() == 1) {
- const string& target_type = arg_to_fill->GetObjectSubtype();
- SConstScopedObject cso = sels.front();
- CScope& scope = *cso.scope;
- IDocument* doc = CDocManager::GetDocumentFromScope(scope);
- if ( !doc ) {
- break;
- }
- CObjConverter::TObjList obj_list;
- CObjectConverter::Convert(scope, *cso.object,
- target_type, obj_list);
- if (obj_list.size() != 1) {
- break;
- }
- arg_to_fill->SetObject(*doc, *obj_list.front());
- if (CPluginUtils::CheckConstraints(*arg_to_fill)) {
- return visible_args - 1;
- }
- }
- break;
- case CPluginArg::TData::e_Array:
- {{
- // make sure we preserve existing values
- CPluginArg::TValues value_list;
- arg_to_fill->AsList(value_list);
- // we can assign many objects
- // first, we do a one-to-many conversion, based on the target type
- const string& target_type = arg_to_fill->GetObjectSubtype();
- // now, iterate our selections and convert as necessary
- ITERATE (TConstScopedObjects, iter, sels) {
- SConstScopedObject cso = sels.front();
- CScope& scope = *cso.scope;
- IDocument* doc = CDocManager::GetDocumentFromScope(scope);
- if ( !doc ) {
- continue;
- }
- CObjectConverter::TObjList obj_list;
- CObjectConverter::Convert(scope, *iter->object,
- target_type, obj_list);
- ITERATE(CObjectConverter::TObjList, obj_iter, obj_list) {
- CRef<CPluginValue> value(new CPluginValue());
- value->SetObject(*doc, **obj_iter);
- value_list.push_back(value);
- }
- }
- // make sure all of our arguments are valid
- // we do this such that any unfilled argument will be passed on
- // if we added nothing to this argument, then our size is 1
- if (value_list.size() > 1) {
- CPluginArg::TValues::iterator iter = value_list.begin();
- CPluginArg::TValues::iterator end_iter = value_list.end();
- for ( ; iter != end_iter; ) {
- const CPluginValue& value = **iter;
- if ( !IsValid(value) ) {
- iter = value_list.erase(iter);
- } else {
- ++iter;
- }
- }
- }
- arg_to_fill->SetList(value_list);
- if (CPluginUtils::CheckConstraints(*arg_to_fill)) {
- return visible_args - 1;
- }
- }}
- break;
- default:
- break;
- }
- return visible_args;
- }
- // this function performs a similar task to FillArgs(); however, instead of
- // actually filling the set of arguments automatically, it returns true if any
- // of the selections indicated *can* fit. The primary use of this is to
- // determine if a set of plugins could accept some of the selections
- bool CPluginUtils::CanFitArgs(const CPluginArgSet& args,
- const IDocument& doc,
- CConvertCache* cache)
- {
- TConstScopedObjects sels;
- sels.push_back(SConstScopedObject(doc, doc.GetScope()));
- return CanFitArgs(args, sels, cache);
- }
- bool CPluginUtils::CanFitArgs(const CPluginArgSet& args,
- const CSelectionBuffer& sels,
- CConvertCache* cache)
- {
- return CanFitArgs(args, sels.DecomposeToPairs(), cache);
- }
- bool CPluginUtils::CanFitArgs(const CPluginArgSet& args,
- const TConstScopedObjects& sels,
- CConvertCache* cache)
- {
- // easy out: no arguments to fill
- // we're always valid here
- if (args.Get().size() == 0) {
- return true;
- }
- // we plan to handle one case automatically: the set of arguments has
- // one argument that takes a data model object. Other cases are left
- // to the user to clarify because these are too complex to guess
- int obj_args = 0;
- ITERATE (CPluginArgSet::Tdata, iter, args.Get()) {
- const CPluginArg& arg = **iter;
- switch (arg.GetType()) {
- case CPluginArg::eObject:
- case CPluginArg::eDocument:
- {{
- ++obj_args;
- const string& target_type = arg.GetObjectSubtype();
- // are there any selections that might support this object
- // type? if so, we can return true
- ITERATE (TConstScopedObjects, iter, sels) {
- SConstScopedObject cso = *iter;
- CScope& scope = *cso.scope;
- CObjConverter::TObjList obj_list;
- /**
- if (cache) {
- obj_list =
- cache->Convert(scope,
- *iter->m_Object.GetPointer(),
- target_type);
- } else **/{
- CObjectConverter::Convert(scope,
- *cso.object,
- target_type, obj_list);
- }
- if (obj_list.size() == 0) {
- continue;
- }
- ITERATE (CObjConverter::TObjList, obj_iter, obj_list) {
- if ( CheckConstraints(arg, scope, **obj_iter) ) {
- return true;
- }
- }
- }
- }}
- break;
- default:
- break;
- }
- }
- // we failed to match any selection to an argument type
- // the only case we let pass is that there are no object argument types
- return (obj_args == 0);
- }
- vector<string> CPluginUtils::ArgToStringVec(const CPluginArg& arg)
- {
- if (arg.GetType() != CPluginArg::eString) {
- NCBI_THROW(CPluginException, eInvalidArg,
- "CPluginUtil::ArgToStringVec(): "
- "Argument is not of type String");
- }
- vector<string> vals;
- CTypeConstIterator<CPluginValue> iter(arg);
- for ( ; iter; ++iter) {
- vals.push_back(iter->AsString());
- }
- return vals;
- }
- //
- // return the label of an object based on its type (arg.m_Subtype)
- //
- string CPluginUtils::GetLabel(const CObject& obj, CScope* scope)
- {
- {{
- // generic document handling
- const IDocument* doc = dynamic_cast<const IDocument*> (&obj);
- if (doc) {
- return doc->GetTitle();
- }
- }}
- string label;
- CLabel::GetLabel(obj, &label, CLabel::eDefault, scope);
- return label;
- }
- //
- // retrieve the CPluginInfo object associated with a named plugin
- //
- const CPluginInfo& CPluginUtils::GetInfo(const string& plugin_name)
- {
- CPluginHandle handle = CPluginRegistry::GetPlugin(plugin_name);
- if ( !handle ) {
- NCBI_THROW(CPluginException, eInvalidArg,
- "Invalid plugin name " + plugin_name);
- }
- return handle.GetInfo();
- }
- END_NCBI_SCOPE
- /*
- * ===========================================================================
- * $Log: plugin_utils.cpp,v $
- * Revision 1000.5 2004/06/01 20:44:35 gouriano
- * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.69
- *
- * Revision 1.69 2004/06/01 18:03:45 dicuccio
- * Allocate temporary CSelectionBuffer objects on the heap, not on the stack
- *
- * Revision 1.68 2004/05/21 22:27:40 gorelenk
- * Added PCH ncbi_pch.hpp
- *
- * Revision 1.67 2004/05/07 15:41:27 dicuccio
- * Use CLabel instead of CSeqUtils::GetLabel()
- *
- * Revision 1.66 2004/05/03 12:49:28 dicuccio
- * gui/utils --> gui/objutils where needed
- *
- * Revision 1.65 2004/04/07 12:47:31 dicuccio
- * Use TConstScopedObjects instead of CSelectionBuffer::TSelList. Changed
- * CallPlugin API to include an IReporter interface.
- *
- * Revision 1.64 2004/03/08 20:21:05 jcherry
- * Fixed object argument clearing
- *
- * Revision 1.63 2004/02/04 14:09:04 dicuccio
- * Enable clearing of objects
- *
- * Revision 1.62 2004/02/03 23:08:13 ucko
- * Temporarily remove call to ClearObjects, which doesn't seem to be
- * implemented yet.
- *
- * Revision 1.61 2004/02/03 21:24:31 dicuccio
- * Clear objects from plugin argument sets prior to filling with new objects
- *
- * Revision 1.60 2004/01/30 17:18:11 dicuccio
- * Moved most of GetLabel() to CSeqUtils - CPluginUtils::GetLabel() only handles
- * IDocument directly
- *
- * Revision 1.59 2004/01/21 12:38:18 dicuccio
- * redesigned CObjectCOnverter API to eliminate temporary object creation
- *
- * Revision 1.58 2004/01/20 18:13:28 dicuccio
- * Make sure to check for bioseq handle validity before requesting information
- * from it
- *
- * Revision 1.57 2004/01/15 22:50:17 jcherry
- * Added FinalizeArgs() for plugins
- *
- * Revision 1.56 2004/01/07 15:48:10 dicuccio
- * Renamed GetObjectLabel() to GetLabel(). Dropped use of CSeq_loc::GetLabel() in
- * favor of internal location processing
- *
- * Revision 1.55 2004/01/05 19:10:31 dicuccio
- * Move comment marker
- *
- * Revision 1.54 2003/12/22 19:21:16 dicuccio
- * GetObjectLabel(): format a nicer string for seq-ids when possible
- *
- * Revision 1.53 2003/11/26 17:08:22 dicuccio
- * Fixed two thinkos:
- * - in s_CallPlugin(), check to make sure the plugin handle is valid before
- * calling FillDefaults()
- * - make sure that FillArgs() doesn't dereference a NULL pointer
- *
- * Revision 1.52 2003/11/18 17:44:31 dicuccio
- * Added new API for FitArgs() to take a set of CPluginValue objects
- *
- * Revision 1.51 2003/11/06 20:04:56 dicuccio
- * Added context parameter to PluginMessage. Added APIs to CallPlugin() to permit
- * passing the context parameter
- *
- * Revision 1.50 2003/11/04 17:19:41 dicuccio
- * Made templateed calls to registry private. Changed to match API change in
- * CPluginMessage.
- *
- * Revision 1.49 2003/10/27 17:39:54 dicuccio
- * Changed to match new API for CPluginValue variant
- *
- * Revision 1.48 2003/10/23 16:18:09 dicuccio
- * Fixed to match API change for CPluginArgDialog
- *
- * Revision 1.47 2003/10/15 18:28:45 dicuccio
- * Added handling for new constraint types
- *
- * Revision 1.46 2003/10/10 17:15:58 dicuccio
- * Changed protoypes for CanFitArgs() - take optional conversion cache
- *
- * Revision 1.45 2003/10/10 15:57:28 friedman
- * Changed all CPluginUtils::Convert to use CObjectConverter::Convert.
- * Label for SeqFeat changed to include the document id and document short title.
- *
- * Revision 1.44 2003/10/07 13:36:09 dicuccio
- * Renamed CPluginURL* to CPluginValue*. Moved validation code into CPluginUtils
- *
- * Revision 1.43 2003/10/01 12:07:35 ucko
- * +<algorithm> for find()
- *
- * Revision 1.42 2003/09/16 14:02:07 dicuccio
- * Replaced conversion code with calls to new class (CObjectConverter)
- *
- * Revision 1.41 2003/09/04 14:01:51 dicuccio
- * Introduce IDocument and IView as abstract base classes for CDocument and CView
- *
- * Revision 1.40 2003/09/02 20:36:26 dicuccio
- * Corrected x_DocToSeqAnnot to handle the case of a seq-annot-as-document
- *
- * Revision 1.39 2003/08/28 15:55:51 ucko
- * GetObjectLabel: return CNcbiOstrstreamToString(label) rather than
- * label.str() to ensure proper cleanup and termination.
- *
- * Revision 1.38 2003/08/28 00:09:08 ucko
- * x_SeqLocToSeqAnnot: adjust for latest objmgr API.
- *
- * Revision 1.37 2003/08/22 17:28:10 dicuccio
- * FIxed seq-annot conversions - all now pass through x_SeqLocToSeqAnnot
- *
- * Revision 1.36 2003/08/22 17:05:05 dicuccio
- * Temporary compilation fix: disable annotation conversion
- *
- * Revision 1.35 2003/08/22 15:45:12 dicuccio
- * Removed a number of unnecessary _TRACE() statemens
- *
- * Revision 1.34 2003/08/19 18:52:16 friedman
- * Added the follwing conversion functionclality to Convert:
- * doc -> seq-annot, bioseq -> seq-annot, seq-id -> seq-annot,
- * seq-loc -> seq-annot, seq-entry -> seq-annot, doc -> seq-align
- *
- * Added seq-annot and seq-align label formatting to GetObjectLabel
- *
- * Revision 1.33 2003/08/18 19:16:47 dicuccio
- * Fixed another (hopefully last!) thinko in CanFitArgs() - must pass the logic
- * "return true if any of our selections matches an object argument or if there
- * are no object arguments"
- *
- * Revision 1.32 2003/08/15 19:34:33 dicuccio
- * Added early break to loop on failure
- *
- * Revision 1.31 2003/08/13 13:33:23 dicuccio
- * Fixed another thinko - always pass objects regardless of whether the argument is of type single or of type array
- *
- * Revision 1.30 2003/08/12 21:41:24 ucko
- * Fix typo
- *
- * Revision 1.29 2003/08/12 19:51:23 dicuccio
- * Fixed thinko in CanFitArgs() - rather than return false for any failure, return
- * true for any success
- *
- * Revision 1.28 2003/08/11 19:26:21 dicuccio
- * Favor member insert to std::copy()
- *
- * Revision 1.27 2003/08/06 14:38:55 friedman
- * Add Seq-entry label formatting to GetObjectLabel
- *
- * Revision 1.26 2003/08/05 17:07:15 dicuccio
- * Changed calling semantics for the message queue - pass by reference, not
- * CConstRef<>
- *
- * Revision 1.25 2003/07/31 16:56:06 dicuccio
- * Changed name of plugin message queue. Correctly account for hidden arguments
- * to plugins.
- *
- * Revision 1.24 2003/07/24 13:12:29 dicuccio
- * Added basic bioseq conversion routines
- *
- * Revision 1.23 2003/07/23 19:14:08 dicuccio
- * Moved logic for validating plugin arguments into CPluginUtils.
- *
- * Revision 1.22 2003/07/22 17:01:14 dicuccio
- * Fixed compilation error - return TObjList instead of NULL
- *
- * Revision 1.21 2003/07/22 15:29:54 dicuccio
- * Dropped CSeqVector as an explicitly managed type. Changed Convert() to perform
- * a one-to-many conversion
- *
- * Revision 1.20 2003/07/21 19:29:17 dicuccio
- * Changed to match API changes in CSelectionBuffer. Added CanFitArgs() version
- * to work with selection buffers
- *
- * Revision 1.19 2003/07/17 03:20:19 friedman
- * Added passing in a TConstScopedObjects to CPluginArgDialog
- *
- * Revision 1.18 2003/07/14 11:01:20 shomrat
- * Plugin messageing system related changes
- *
- * Revision 1.17 2003/06/30 13:33:41 dicuccio
- * Added API to call a plugin with a raw CPluginRequest object
- *
- * Revision 1.16 2003/06/25 17:02:54 dicuccio
- * Split CPluginHandle into a handle (pointer-to-implementation) and
- * implementation file. Lots of #include file clean-ups.
- *
- * Revision 1.15 2003/06/02 16:06:17 dicuccio
- * Rearranged src/objects/ subtree. This includes the following shifts:
- * - src/objects/asn2asn --> arc/app/asn2asn
- * - src/objects/testmedline --> src/objects/ncbimime/test
- * - src/objects/objmgr --> src/objmgr
- * - src/objects/util --> src/objmgr/util
- * - src/objects/alnmgr --> src/objtools/alnmgr
- * - src/objects/flat --> src/objtools/flat
- * - src/objects/validator --> src/objtools/validator
- * - src/objects/cddalignview --> src/objtools/cddalignview
- * In addition, libseq now includes six of the objects/seq... libs, and libmmdb
- * replaces the three libmmdb? libs.
- *
- * Revision 1.14 2003/05/19 13:35:59 dicuccio
- * Moved gui/core/plugin/ -> gui/plugin/. Merged gui/core/algo, gui/core/doc/,
- * and gui/core/view/ into one library (gui/core/)
- *
- * Revision 1.13 2003/05/06 15:55:16 dicuccio
- * Dropped identity object conversion in favor of a generic approach
- *
- * Revision 1.12 2003/05/05 12:42:48 dicuccio
- * Added new interface function (CanFitArgs()) to determine if a given set of
- * objects could possibly apply to a set of arguments
- *
- * Revision 1.11 2003/05/01 12:53:36 dicuccio
- * Added conversion routines for {doc,seq-id,seq-loc,seq-feat} --> seq-entry
- *
- * Revision 1.10 2003/04/29 14:44:16 dicuccio
- * Fixed bungled commit - deleted dead, poorly formatted code that affected
- * indentation
- *
- * Revision 1.9 2003/04/29 14:42:43 dicuccio
- * Changed SelectionsToArgs() -> FillArgs(). Added API for filling arguments
- * based solely on the contents of a document. Made main type conversion
- * routine public. Added API for converting objects based on CTypeInfo. Added
- * prototype function for conversion of an argument to a vector of strings.
- *
- * Revision 1.8 2003/04/24 16:31:07 dicuccio
- * Large changes. Added many new interface functions for objects
- * cast/conversion. Changed SelBufferToArgs() -> more generic FillArgs().
- * Changed internals of filling out plugin arguments automatically to avoid
- * faulty assumptions about argument contents.
- *
- * Revision 1.7 2003/04/16 18:21:27 dicuccio
- * Added generic plugin launch mechanism (CallPlugin()). Modified
- * document-to-argument resolution to permit empty documents to be passed as
- * documents
- *
- * Revision 1.6 2003/03/25 13:11:32 dicuccio
- * Changed FillArgs() to return the number of unset arguments
- *
- * Revision 1.5 2003/03/10 22:58:51 kuznets
- * iterate -> ITERATE
- *
- * Revision 1.4 2003/02/26 14:24:36 dicuccio
- * Major rewrite of selection-to-argument handling code - most cases should be
- * handled automatically now, but there is still no manual fall-back.
- *
- * Revision 1.3 2003/02/25 14:46:52 dicuccio
- * Intermediate fix. Still not working, but at least it compiles.
- *
- * Revision 1.2 2003/02/24 13:03:15 dicuccio
- * Renamed classes in plugin spec:
- * CArgSeg --> CPluginArgSet
- * CArgument --> CPluginArg
- * CPluginArgs --> CPluginCommand
- * CPluginCommands --> CPluginCommandSet
- *
- * Revision 1.1 2003/02/20 19:49:56 dicuccio
- * Created new plugin architecture, based on ASN.1 spec. Moved GBENCH frameowrk
- * over to use new plugin architecture.
- *
- * ===========================================================================
- */
-