Changeset 270 in pacpusframework for trunk/src/PacpusLib


Ignore:
Timestamp:
Mar 13, 2014, 10:41:30 AM (11 years ago)
Author:
Marek Kurdej
Message:

Major: DomElementParser (direct parsing of XML attributes).

Location:
trunk/src/PacpusLib
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/PacpusLib/ComponentBase.cpp

    r263 r270  
    244244}
    245245
    246 void ComponentBase::parseParameters(const XmlComponentConfig & cfg)
     246class DomElementParser
     247{
     248public:
     249    DomElementParser(QDomElement const& args);
     250   
     251    /** Sets options descriptions to use. */
     252    DomElementParser& options(const boost::program_options::options_description& desc);
     253   
     254    /** Parses the options and returns the result of parsing.
     255        Throws on error.
     256    */
     257    boost::program_options::basic_parsed_options<char> run();
     258
     259    /** Specifies that unregistered options are allowed and should
     260        be passed though. For each command like token that looks
     261        like an option but does not contain a recognized name, an
     262        instance of basic_option<charT> will be added to result,
     263        with 'unrecognized' field set to 'true'. It's possible to
     264        collect all unrecognized options with the 'collect_unrecognized'
     265        funciton.
     266    */
     267    DomElementParser& allow_unregistered();
     268   
     269private:
     270    boost::program_options::basic_parsed_options<char> parseDomElement(
     271        const QDomElement& dom_element,
     272        const boost::program_options::options_description& desc,
     273        bool allow_unregistered = false);
     274
     275private:
     276    const boost::program_options::options_description* m_desc;
     277    const QDomElement& m_dom_element;
     278    bool m_allow_unregistered;
     279};
     280
     281DomElementParser::DomElementParser(const QDomElement& dom_element)
     282    : m_dom_element(dom_element)
     283    , m_allow_unregistered(false)
     284{
     285}
     286
     287DomElementParser& DomElementParser::options(const boost::program_options::options_description& desc)
     288{
     289    m_desc = &desc;
     290    return *this;
     291}
     292
     293DomElementParser& DomElementParser::allow_unregistered()
     294{
     295    m_allow_unregistered = true;
     296    return *this;
     297}
     298
     299#include <boost/iterator/iterator_facade.hpp>
     300#include <boost/program_options/errors.hpp>
     301
     302namespace detail
     303{
     304template <typename charT>
     305class basic_dom_element_iterator
     306    : public boost::iterator_facade<
     307        basic_dom_element_iterator<charT>
     308        , const boost::program_options::option
     309        , boost::random_access_traversal_tag
     310    >
     311{
     312public:
     313    typedef boost::program_options::option ValueType;
     314
     315    basic_dom_element_iterator<charT>()
     316        : m_dom_element(NULL)
     317        , m_at_eof(true)
     318    {
     319    }
     320
     321    basic_dom_element_iterator<charT>(const QDomElement& dom_element,
     322            const std::set<std::string>& allowed_options,
     323            bool allow_unregistered = false)
     324        : m_dom_element(&dom_element)
     325        , m_allowed_options(allowed_options)
     326        , m_allow_unregistered(false)
     327        , m_i(0)
     328    {
     329        m_attrs = m_dom_element->attributes();
     330        m_at_eof = !(m_i < m_attrs.size());
     331        if (!m_at_eof) {
     332            get();
     333        }
     334    }
     335   
     336//private:
     337    friend class iterator_core_access;
     338
     339    bool equal(const basic_dom_element_iterator<charT>& other) const
     340    {
     341        if (m_at_eof && other.m_at_eof) {
     342            return true;
     343        }
     344        return false;
     345    }
     346   
     347    void increment()
     348    {
     349        ++m_i;
     350        m_at_eof = !(m_i < m_attrs.size());
     351        if (!m_at_eof) {
     352            get();
     353        }
     354    }
     355   
     356    const ValueType& dereference() const
     357    {
     358        return m_value;
     359    }
     360   
     361    difference_type distance_to(const basic_dom_element_iterator<charT>& other) const
     362    {
     363        return other.m_i - this->m_i;
     364    }
     365
     366private:
     367    ValueType& value()
     368    {
     369        return m_value;
     370    }
     371   
     372    void get()
     373    {
     374        using namespace boost::program_options;
     375
     376        QDomNode node = m_attrs.item(m_i);
     377        QDomAttr attr = node.toAttr();
     378
     379        string name = attr.name().toStdString();
     380        string value = attr.value().toStdString();
     381
     382        bool registered = allowed_option(name);
     383        if (!registered && !m_allow_unregistered) {
     384            boost::throw_exception(unknown_option(name));
     385        }
     386
     387        this->value().string_key = name;
     388        this->value().value.clear();
     389        this->value().value.push_back(value);
     390        this->value().unregistered = !registered;
     391        this->value().original_tokens.push_back(name);
     392        this->value().original_tokens.push_back(value);
     393    }
     394
     395    bool allowed_option(const std::string& s) const
     396    {
     397        set<string>::const_iterator i = m_allowed_options.find(s);
     398        if (i != m_allowed_options.end()) {
     399            return true;       
     400        }
     401        return false;
     402    }
     403
     404private:
     405    const QDomElement* m_dom_element;
     406    std::set<std::string> m_allowed_options;
     407    bool m_allow_unregistered;
     408
     409    QDomNamedNodeMap m_attrs;
     410    int m_i;
     411    bool m_at_eof;
     412    ValueType m_value;
     413};
     414
     415typedef basic_dom_element_iterator<char> dom_element_iterator;
     416typedef basic_dom_element_iterator<wchar_t> wdom_element_iterator;
     417
     418}
     419
     420boost::program_options::basic_parsed_options<char> DomElementParser::run()
     421{
     422    assert(m_desc);
     423    return parseDomElement(m_dom_element, *m_desc, m_allow_unregistered);
     424}
     425
     426boost::program_options::basic_parsed_options<char> DomElementParser::parseDomElement(
     427        const QDomElement& dom_element,
     428        const boost::program_options::options_description& desc,
     429        bool allow_unregistered)
     430{
     431    typedef char charT;
     432
     433    using boost::program_options::error;
     434    using boost::shared_ptr;
     435    using namespace boost::program_options;
     436    using ::detail::basic_dom_element_iterator;
     437   
     438    set<string> allowed_options;
     439
     440    const vector<shared_ptr<option_description> >& options = desc.options();
     441    for (unsigned i = 0; i < options.size(); ++i) {
     442        const option_description& d = *options[i];
     443
     444        if (d.long_name().empty()) {
     445            boost::throw_exception(
     446                error("abbreviated option names are not permitted when parsing DOM elements"));
     447        }
     448       
     449        allowed_options.insert(d.long_name());
     450    }
     451   
     452    // Parser returns char strings
     453    parsed_options result(&desc);       
     454    copy(basic_dom_element_iterator<charT>(dom_element, allowed_options, allow_unregistered),
     455            basic_dom_element_iterator<charT>(),
     456            back_inserter(result.options));
     457
     458    // Convert char strings into desired type.
     459    return basic_parsed_options<charT>(result);
     460}
     461
     462DomElementParser parseDomElement();
     463
     464/** Creates instance of 'command_line_parser', passes parameters to it,
     465    and returns the result of calling the 'run' method.       
     466    */
     467boost::program_options::basic_parsed_options<char>
     468parseDomElement(QDomElement const& domElement, const boost::program_options::options_description&);
     469
     470boost::program_options::basic_parsed_options<char>
     471parseDomElement(QDomElement const& domElement, const boost::program_options::options_description& desc)
     472{
     473    return DomElementParser(domElement)
     474        .options(desc)
     475        .run();
     476}
     477
     478void ComponentBase::parseParameters(XmlComponentConfig const& cfg)
    247479{
    248480    LOG_INFO("Parsing parameters...");
     
    254486    try {
    255487        po::store(
    256             po::command_line_parser(xargs)
     488            DomElementParser(cfg.getDomElement())
     489            //po::command_line_parser(xargs)
    257490                .options(mOptionsDescription)
    258491                .allow_unregistered()   // FIXME: temporary only, at term all the components specify all parameters
     
    260493        , vm);
    261494        po::notify(vm);
    262     } catch (po::error & e) {
     495    } catch (po::error& e) {
    263496        LOG_WARN(e.what());
    264497        throw PacpusException(e.what());
  • trunk/src/PacpusLib/ComponentManager.cpp

    r232 r270  
    340340        }
    341341
    342         component->param.localCopy(cfg.qDomElement());
     342        component->param.localCopy(cfg.getDomElement());
    343343        try {
    344344            component->parseParameters(cfg);
     
    373373
    374374            // copy locally the config parameters of the component
    375             component->param.localCopy(cfg.qDomElement());
     375            component->param.localCopy(cfg.getDomElement());
    376376            component->setConfigurationState(component->configureComponent(cfg));
    377377        }
  • trunk/src/PacpusLib/XmlComponentConfig.cpp

    r176 r270  
    126126}
    127127
    128 QDomElement XmlComponentConfig::qDomElement() const
     128QDomElement const& XmlComponentConfig::getDomElement() const
    129129{
    130130    return component_;
Note: See TracChangeset for help on using the changeset viewer.