Skip to content
Snippets Groups Projects
CompositeValidator.cpp 3.37 KiB
Newer Older
#include "MantidKernel/CompositeValidator.h"

using namespace Mantid::Kernel;

namespace Mantid
{
  namespace Kernel
  {
    /// Default constructor
    CompositeValidator::CompositeValidator()
     : IValidator(), m_children()
    {
    }

    /// Destructor
    CompositeValidator::~CompositeValidator()
    {
      m_children.clear();
    }

    /**
     * The allowed values for the composite vaidator. This returns
     * the intersection of the allowedValues for the child validators
     * @return
     */
    std::vector<std::string> CompositeValidator::allowedValues() const
    {
      std::set<std::string>      elem_unique;
      std::multiset<std::string> elem_all;
      // how many validators return non-empty list of allowed values
      int n_combinations(0);
      std::list<IValidator_sptr>::const_iterator itrEnd = m_children.end();
      for( std::list<IValidator_sptr>::const_iterator itr = m_children.begin(); itr != itrEnd; ++itr)
        std::vector<std::string> subs = (*itr)->allowedValues();
        if ( subs.empty())continue;
        elem_unique.insert(subs.begin(),subs.end());
        elem_all.insert(subs.begin(),subs.end());
        n_combinations++;
      }
      // empty or single set of allowed values
      if(n_combinations<2)return std::vector<std::string>( elem_unique.begin(), elem_unique.end() );
      // there is more then one combination and we have to identify its union;
      for(std::set<std::string>::const_iterator its=elem_unique.begin();its!=elem_unique.end();++its)
      {
        std::multiset<std::string>::iterator im = elem_all.find(*its);
        elem_all.erase(im);
      }
      std::set<std::string> rez;
      for(std::multiset<std::string>::const_iterator im=elem_all.begin();im!=elem_all.end();++im)
      {
      return std::vector<std::string>( rez.begin(), rez.end() );
    }

    /**
     * Clone the validator
     * @return A newly constructed validator object. Each child is also cloned
     */
    Kernel::IValidator_sptr CompositeValidator::clone() const
    {
      boost::shared_ptr<CompositeValidator> copy = boost::make_shared<CompositeValidator>();
      std::list<IValidator_sptr>::const_iterator itrEnd = m_children.end();
      for(   std::list<IValidator_sptr>::const_iterator itr = m_children.begin(); itr != itrEnd; ++itr)
      {
        copy->add( (*itr)->clone() );
      }
      return copy;
    }

    /** Adds a validator to the group of validators to check
     *  @param child :: A pointer to the validator to add
     */
    void CompositeValidator::add(Kernel::IValidator_sptr child)
    {
      m_children.push_back(child);
    }

    /** Checks the value of all child validators. Fails if any child fails.
     *  @param value :: The workspace to test
     *  @return A user level description of the first problem it finds otherwise ""
     */
    std::string CompositeValidator::check( const boost::any& value ) const
    {
      std::list<IValidator_sptr>::const_iterator itrEnd = m_children.end();
      for(std::list<IValidator_sptr>::const_iterator itr = m_children.begin(); itr != itrEnd; ++itr)
        std::string error = (*itr)->check(value);
        //exit on the first error, to avoid passing doing more tests on invalid objects that could fail
        if (error != "") return error;
      }
      //there were no errors
      return "";
    }