Split option code away from SelectionCollection.
authorTeemu Murtola <teemu.murtola@gmail.com>
Fri, 18 May 2012 08:32:56 +0000 (11:32 +0300)
committerTeemu Murtola <teemu.murtola@gmail.com>
Fri, 18 May 2012 09:46:34 +0000 (12:46 +0300)
Move code required for selection option implementation from
SelectionCollection to a separate SelectionOptionManager class.
Simplified the selection request handling code in the process, but
otherwise this commit mainly moves code around without changing any
functionality (except for small changes required to use the new class
in code using the selections).

This makes the responsibilities in the code clearer, since
SelectionCollection is now completely independent of any options
implementation.  It also simplifies the involved classes, since
the options handling (which will become even more involved with #656)
no longer complicates the core of the selection module.

Related to #656.

Change-Id: Iac24a2f9392c8cc2421edef3f212ddb462e864b3

16 files changed:
src/gromacs/commandline/tests/cmdlinehelpwriter.cpp
src/gromacs/selection.h
src/gromacs/selection/CMakeLists.txt
src/gromacs/selection/selectioncollection-impl.h
src/gromacs/selection/selectioncollection.cpp
src/gromacs/selection/selectioncollection.h
src/gromacs/selection/selectionfileoption.h
src/gromacs/selection/selectionfileoptioninfo.h
src/gromacs/selection/selectionfileoptionstorage.h
src/gromacs/selection/selectionoption.cpp
src/gromacs/selection/selectionoptioninfo.h
src/gromacs/selection/selectionoptionmanager.cpp [new file with mode: 0644]
src/gromacs/selection/selectionoptionmanager.h [new file with mode: 0644]
src/gromacs/selection/selectionoptionstorage.h
src/gromacs/selection/tests/selectionoption.cpp
src/gromacs/trajectoryanalysis/cmdlinerunner.cpp

index a7bccea301275d2e257a33424bebd2114cb4bce3..36ab4a53206c3994eb564bab104829f3f630513e 100644 (file)
 #include "gromacs/options/basicoptions.h"
 #include "gromacs/options/filenameoption.h"
 #include "gromacs/options/options.h"
+#include "gromacs/selection/selectioncollection.h"
 #include "gromacs/selection/selectionfileoption.h"
 #include "gromacs/selection/selectionoption.h"
 #include "gromacs/selection/selectionoptioninfo.h"
-#include "gromacs/selection/selectioncollection.h"
+#include "gromacs/selection/selectionoptionmanager.h"
 #include "gromacs/utility/file.h"
 
 #include "testutils/datapath.h"
@@ -219,9 +220,10 @@ TEST_F(CommandLineHelpWriterTest, HandlesSelectionOptions)
     options.addOption(SelectionOption("sel").required().valueCount(2)
                         .description("Selection option"));
     gmx::SelectionCollection selections;
-    setSelectionCollectionForOptions(&options, &selections);
+    gmx::SelectionOptionManager manager(&selections);
+    setManagerForSelectionOptions(&options, &manager);
     options.finish();
-    selections.parseRequestedFromString(
+    manager.parseRequestedFromString(
             "resname SOL;"
             "surface = within 0.5 of resname SOL;"
             "group \"Protein\" and surface;"
index 039158b6038398bc9048d23e3d20f688ff1c26b1..2ca93137eafd37bf9fb53a8253ad4b584ff89768 100644 (file)
  * module_options for general explanation of the options mechanism).  These
  * classes provide the main interface to obtain gmx::Selection objects in
  * trajectory analysis using gmx::TrajectoryAnalysisModule.
- *
+ * To use these classes outside the trajectory analysis framework,
+ * a gmx::SelectionOptionManager needs to be created to serve as a bridge
+ * between the selection option classes and the gmx::SelectionCollection
+ * object.
  * \if libapi
+ * gmx::SelectionFileOption can be used to implement generic file input for
+ * selection options (done internally in the trajectory analysis framework).
+ *
  * The selection module contains some lower-level functionality that is
  * currently internal to it (centerofmass.h, indexutil.h, poscalc.h,
  * position.h), but could possibly be useful also outside the module.
@@ -84,5 +90,6 @@
 #include "selection/selectioncollection.h"
 #include "selection/selectionoption.h"
 #include "selection/selectionoptioninfo.h"
+#include "selection/selectionoptionmanager.h"
 
 #endif
index 6381fe505b52ede9cf440de18a93c3b5d89eb093..40437385f3b4fdd75984b7c96e6fb2643a1c5dc8 100644 (file)
@@ -9,7 +9,8 @@ set(SELECTION_PUBLIC_HEADERS
     selectioncollection.h
     selectionenums.h
     selectionoption.h
-    selectionoptioninfo.h)
+    selectionoptioninfo.h
+    selectionoptionmanager.h)
 install(FILES ${SELECTION_PUBLIC_HEADERS}
         DESTINATION ${INCL_INSTALL_DIR}/gromacs/selection
         COMPONENT development)
index fecbdbb5a6328d1be8dea742db0c47ab2d821819..ddf51f7ec17cdda4e7f5f02177252eaacdb6d224 100644 (file)
@@ -99,7 +99,6 @@ namespace gmx
 {
 
 class MessageStringCollector;
-class SelectionOptionStorage;
 
 /*! \internal \brief
  * Private implemention class for SelectionCollection.
@@ -109,62 +108,6 @@ class SelectionOptionStorage;
 class SelectionCollection::Impl
 {
     public:
-        /*! \brief
-         * Request for postponed parsing of selections.
-         *
-         * Used to communicate what needs to be parsed with
-         * parseRequestedFromStdin() or parseRequstedFromString().
-         */
-        struct SelectionRequest
-        {
-            //! Initializes a request for the given option.
-            SelectionRequest(const std::string &name, const std::string &descr,
-                             SelectionOptionStorage *storage)
-                : name(name), descr(descr), storage(storage)
-            {
-            }
-
-            /*! \brief
-             * Returns the number of selections requested in this request.
-             *
-             * -1 indicates no upper limit.
-             */
-            int count() const;
-
-            //! Name of the option to which this request relates to.
-            std::string                 name;
-            //! Description of the option to which this request relates to.
-            std::string                 descr;
-            //! Storage object to which the selections will be added.
-            SelectionOptionStorage     *storage;
-        };
-
-        //! Collection for a list of selection requests.
-        typedef std::vector<SelectionRequest> RequestList;
-
-        /*! \brief
-         * Helper class that clears a request list on scope exit.
-         *
-         * Methods in this class do not throw.
-         */
-        class RequestsClearer
-        {
-            public:
-                //! Constructs an object that clears given list on scope exit.
-                explicit RequestsClearer(RequestList *requests)
-                    : requests_(requests)
-                {
-                }
-                //! Clears the request list given to the constructor.
-                ~RequestsClearer()
-                {
-                    requests_->clear();
-                }
-
-            private:
-                RequestList    *requests_;
-        };
-
         /*! \brief
          * Creates a new selection collection.
          *
@@ -199,37 +142,6 @@ class SelectionCollection::Impl
          */
         void runParser(void *scanner, int maxnr,
                        SelectionList *output);
-        /*! \brief
-         * Adds a selection request for delayed user input.
-         *
-         * \param[in] name    Name for the requested selections.
-         * \param[in] descr   Description of the requested selections.
-         * \param     storage Storage object to receive the selections.
-         * \throws    std::bad_alloc if out of memory.
-         *
-         * Strong exception safety.
-         *
-         * \see parseRequestedFromStdin()
-         */
-        void requestSelections(const std::string &name,
-                               const std::string &descr,
-                               SelectionOptionStorage *storage);
-        /*! \brief
-         * Assign selections from a list to pending requests.
-         *
-         * \param[in] selections  List of selections to assign.
-         * \throws    std::bad_alloc if out of memory.
-         * \throws    InvalidInputError if the assignment cannot be done
-         *      (see parseRequestedFromFile() for documented conditions).
-         *
-         * Loops through \p selections and the pending requests lists in order,
-         * and for each requests, assigns the first yet unassigned selections
-         * from the list.
-         *
-         * Used to implement parseRequestedFromFile() and
-         * parseRequestedFromStdin().
-         */
-        void placeSelectionsInRequests(const SelectionList &selections);
         /*! \brief
          * Replace group references by group contents.
          *
@@ -271,8 +183,6 @@ class SelectionCollection::Impl
         bool                    _bExternalGroupsSet;
         //! External index groups (can be NULL).
         gmx_ana_indexgrps_t    *_grps;
-        //! List of selections requested for later parsing.
-        RequestList             _requests;
 };
 
 /*! \internal \brief
index ad80d3499b8510749fd37f35b56698ec7e063e34..8be14ae1045d7d565b44f9f07587c2e48558570e 100644 (file)
 
 #include <cstdio>
 
-#include "futil.h"
-#include "oenv.h"
-#include "smalloc.h"
-#include "xvgr.h"
+#include "gromacs/legacyheaders/oenv.h"
+#include "gromacs/legacyheaders/smalloc.h"
+#include "gromacs/legacyheaders/xvgr.h"
 
 #include "gromacs/options/basicoptions.h"
 #include "gromacs/options/options.h"
@@ -52,7 +51,6 @@
 #include "gromacs/selection/selectioncollection.h"
 #include "gromacs/utility/exceptions.h"
 #include "gromacs/utility/file.h"
-#include "gromacs/utility/format.h"
 #include "gromacs/utility/gmxassert.h"
 #include "gromacs/utility/messagestringcollector.h"
 
@@ -61,7 +59,6 @@
 #include "poscalc.h"
 #include "scanner.h"
 #include "selectioncollection-impl.h"
-#include "selectionoptionstorage.h"
 #include "selelem.h"
 #include "selmethod.h"
 #include "symrec.h"
@@ -80,11 +77,6 @@ namespace gmx
  * SelectionCollection::Impl
  */
 
-int SelectionCollection::Impl::SelectionRequest::count() const
-{
-    return storage->maxValueCount();
-}
-
 SelectionCollection::Impl::Impl()
     : _options("selection", "Common selection control"),
       _debugLevel(0), _bExternalGroupsSet(false), _grps(NULL)
@@ -171,56 +163,6 @@ SelectionCollection::Impl::runParser(yyscan_t scanner, int maxnr,
 }
 
 
-void SelectionCollection::Impl::requestSelections(
-        const std::string &name, const std::string &descr,
-        SelectionOptionStorage *storage)
-{
-    _requests.push_back(SelectionRequest(name, descr, storage));
-}
-
-
-void SelectionCollection::Impl::placeSelectionsInRequests(
-        const SelectionList &selections)
-{
-    RequestsClearer clearRequestsOnExit(&_requests);
-
-    SelectionList::const_iterator first = selections.begin();
-    SelectionList::const_iterator last = first;
-    RequestList::const_iterator i;
-    // TODO: Improve error messages.
-    for (i = _requests.begin(); i != _requests.end(); ++i)
-    {
-        const SelectionRequest &request = *i;
-        if (request.count() > 0)
-        {
-            if (selections.end() - first < request.count())
-            {
-                GMX_THROW(InvalidInputError("Too few selections provided"));
-            }
-            last = first + request.count();
-        }
-        else
-        {
-            if (i != _requests.end() - 1)
-            {
-                GMX_THROW(InvalidInputError(
-                            formatString("Request for selection '%s' must "
-                                         "not be followed by others",
-                                         request.name.c_str())));
-            }
-            last = selections.end();
-        }
-        SelectionList curr(first, last);
-        request.storage->addSelections(curr, true);
-        first = last;
-    }
-    if (last != selections.end())
-    {
-        GMX_THROW(InvalidInputError("Too many selections provided"));
-    }
-}
-
-
 void SelectionCollection::Impl::resolveExternalGroups(
         t_selelem *root, MessageStringCollector *errors)
 {
@@ -438,60 +380,6 @@ SelectionCollection::requiresTopology() const
 }
 
 
-void
-SelectionCollection::parseRequestedFromStdin(bool bInteractive)
-{
-    Impl::RequestsClearer clearRequestsOnExit(&_impl->_requests);
-
-    Impl::RequestList::const_iterator i;
-    for (i = _impl->_requests.begin(); i != _impl->_requests.end(); ++i)
-    {
-        const Impl::SelectionRequest &request = *i;
-        if (bInteractive)
-        {
-            std::fprintf(stderr, "\nSpecify ");
-            if (request.count() < 0)
-            {
-                std::fprintf(stderr, "any number of selections");
-            }
-            else if (request.count() == 1)
-            {
-                std::fprintf(stderr, "a selection");
-            }
-            else
-            {
-                std::fprintf(stderr, "%d selections", request.count());
-            }
-            std::fprintf(stderr, " for option '%s' (%s):\n",
-                         request.name.c_str(), request.descr.c_str());
-            std::fprintf(stderr, "(one selection per line, 'help' for help%s)\n",
-                         request.count() < 0 ? ", Ctrl-D to end" : "");
-        }
-        SelectionList selections;
-        parseFromStdin(request.count(), bInteractive, &selections);
-        request.storage->addSelections(selections, true);
-    }
-}
-
-
-void
-SelectionCollection::parseRequestedFromFile(const std::string &filename)
-{
-    SelectionList selections;
-    parseFromFile(filename, &selections);
-    _impl->placeSelectionsInRequests(selections);
-}
-
-
-void
-SelectionCollection::parseRequestedFromString(const std::string &str)
-{
-    SelectionList selections;
-    parseFromString(str, &selections);
-    _impl->placeSelectionsInRequests(selections);
-}
-
-
 void
 SelectionCollection::parseFromStdin(int nr, bool bInteractive,
                                     SelectionList *output)
index 6e6ad0dbca8e580e8afe4b9f73be26521760b3e8..6b74eeea00bca4a3a79e843a8d4b1e906811be82 100644 (file)
@@ -55,7 +55,6 @@ namespace gmx
 class Options;
 class SelectionCompiler;
 class SelectionEvaluator;
-class SelectionOptionStorage;
 
 /*! \brief
  * Collection of selections.
@@ -73,10 +72,9 @@ class SelectionOptionStorage;
  *
  * After setting the default values, one or more selections can be parsed with
  * one or more calls to parseFromStdin(), parseFromFile(), and/or
- * parseFromString().  parseRequestedFromStdin() and parseRequestedFromString()
- * are provided for integration with SelectionOption.  After all selections are
- * parsed, the topology must be set with setTopology() unless
- * requiresTopology() returns false (the topology can also be set earlier).
+ * parseFromString().  After all selections are parsed, the topology must be
+ * set with setTopology() unless requiresTopology() returns false (the topology
+ * can also be set earlier).
  * setIndexGroups() must also be called if external index group references are
  * used in the selections; it can be called at any point before compile().
  * Once all selections are parsed, they must be compiled all at once using
@@ -227,65 +225,6 @@ class SelectionCollection
          * called as setIndexGroups(NULL).
          */
         void setIndexGroups(gmx_ana_indexgrps_t *grps);
-        /*! \brief
-         * Parses selection(s) from standard input for options not yet
-         * provided.
-         *
-         * \param[in]  bInteractive Whether the parser should behave
-         *      interactively.
-         * \throws     unspecified  Can throw any exception thrown by
-         *      parseFromStdin().
-         * \throws     std::bad_alloc if out of memory.
-         *
-         * This method cooperates with SelectionOption to allow interactive
-         * input of missing selections after all options have been processed.
-         * It should be called after the Options::finish() method has been
-         * called on all options that add selections to this collection.
-         * For each required selection option that has not been given, as well
-         * as for optional selection options that have been specified without
-         * values, it will prompt the user to input the necessary selections.
-         */
-        void parseRequestedFromStdin(bool bInteractive);
-        /*! \brief
-         * Parses selection(s) from a file for options not yet provided.
-         *
-         * \param[in]  filename Name of the file to parse selections from.
-         * \throws     unspecified  Can throw any exception thrown by
-         *      parseFromFile().
-         * \throws     std::bad_alloc if out of memory.
-         * \throws     InvalidInputError if
-         *      - the number of selections in \p filename doesn't match the
-         *        number requested.
-         *      - any selection uses a feature that is not allowed for the
-         *        corresponding option.
-         *      - if there is a request for any number of selections that is
-         *        not the last (in which case it is not possible to determine
-         *        which selections belong to which request).
-         *
-         * This method behaves as parseRequestedFromStdin(), but reads the
-         * selections from a file instead of standard input.
-         * This is used to implement SelectionFileOption.
-         *
-         * \see parseRequestedFromStdin()
-         */
-        void parseRequestedFromFile(const std::string &filename);
-        /*! \brief
-         * Parses selection(s) from a string for options not yet provided.
-         *
-         * \param[in]  str     String to parse.
-         * \throws     unspecified  Can throw any exception thrown by
-         *      parseFromString().
-         * \throws     std::bad_alloc if out of memory.
-         * \throws     InvalidInputError in same conditions as
-         *      parseRequestedFromFile().
-         *
-         * This method behaves as parseRequestedFromFile(), but reads the
-         * selections from a string instead of a file.
-         * This method is mainly used for testing.
-         *
-         * \see parseRequestedFromFile()
-         */
-        void parseRequestedFromString(const std::string &str);
         /*! \brief
          * Parses selection(s) from standard input.
          *
@@ -427,10 +366,6 @@ class SelectionCollection
          * Needed for the evaluator to freely modify the collection.
          */
         friend class SelectionEvaluator;
-        /*! \brief
-         * Needed for handling delayed selection parsing requests.
-         */
-        friend class SelectionOptionStorage;
 };
 
 } // namespace gmx
index f1587092a021815fc5e8503eeee2dec5589940e5..10a63a5bd7edb9151068dc6a105891919ec84370 100644 (file)
@@ -49,7 +49,7 @@ namespace gmx
  *
  * This option is used internally by the command-line framework to implement
  * file input for selections.  The option takes a file name, and reads it in
- * using SelectionCollection::parseRequestedFromFile().  This means that
+ * using SelectionOptionManager::parseRequestedFromFile().  This means that
  * selections from the file are assigned to selection options that have been
  * explicitly provided without values earlier on the command line.
  *
index bff3a5bac222e718c81b6a6dbe41d4c4b3064897..f18989973961240220d1c7050006e60edebc0d58 100644 (file)
@@ -44,8 +44,8 @@
 namespace gmx
 {
 
-class SelectionCollection;
 class SelectionFileOptionStorage;
+class SelectionOptionManager;
 
 /*! \libinternal \brief
  * Wrapper class for accessing and modifying selection file option information.
@@ -63,20 +63,8 @@ class SelectionFileOptionInfo : public OptionInfo
          */
         explicit SelectionFileOptionInfo(SelectionFileOptionStorage *option);
 
-        /*! \brief
-         * Set selection collection into which this option adds selections.
-         *
-         * \param   selections  Selection collection to set.
-         *
-         * This must be called before values are added.
-         *
-         * Typically it is called through setSelectionCollectionForOptions(),
-         * which recursively sets the collection for all selection options in
-         * an Options object.
-         *
-         * Does not throw.
-         */
-        void setSelectionCollection(SelectionCollection *selections);
+        //! \copydoc SelectionOptionInfo::setManager()
+        void setManager(SelectionOptionManager *manager);
 
     private:
         SelectionFileOptionStorage &option();
index de1555e39d7c5ac8f7d2bc2bb46069abc01c6e00..12a29cc7bd248b8088c3a88948a490733bc3b78e 100644 (file)
@@ -44,8 +44,8 @@
 namespace gmx
 {
 
-class SelectionCollection;
 class SelectionFileOption;
+class SelectionOptionManager;
 
 /*! \internal \brief
  * Implementation for a special option for reading selections from files.
@@ -67,10 +67,10 @@ class SelectionFileOptionStorage : public AbstractOptionStorage
         virtual int valueCount() const { return 0; }
         virtual std::string formatValue(int /*i*/) const { return ""; }
 
-        //! \copydoc SelectionFileOptionInfo::setSelectionCollection()
-        void setSelectionCollection(SelectionCollection *selections)
+        //! \copydoc SelectionFileOptionInfo::setManager()
+        void setManager(SelectionOptionManager *manager)
         {
-            sc_ = selections;
+            manager_ = manager;
         }
 
     private:
@@ -80,7 +80,7 @@ class SelectionFileOptionStorage : public AbstractOptionStorage
         virtual void processAll() {}
 
         SelectionFileOptionInfo info_;
-        SelectionCollection    *sc_;
+        SelectionOptionManager *manager_;
         bool                    bValueParsed_;
 };
 
index a93c364b2283a94b8a6c45da5ba9bf31df0fce15..92f0958a151084ddb0a558765f5b9b84ab7963d4 100644 (file)
 #include "gromacs/selection/selectioncollection.h"
 #include "gromacs/selection/selectionfileoption.h"
 #include "gromacs/selection/selectionoptioninfo.h"
+#include "gromacs/selection/selectionoptionmanager.h"
 #include "gromacs/utility/exceptions.h"
 #include "gromacs/utility/gmxassert.h"
 #include "gromacs/utility/messagestringcollector.h"
 
-#include "selectioncollection-impl.h"
 #include "selectionfileoptionstorage.h"
 #include "selectionoptionstorage.h"
 
@@ -63,13 +63,13 @@ namespace gmx
 
 SelectionOptionStorage::SelectionOptionStorage(const SelectionOption &settings)
     : MyBase(settings, OptionFlags() | efNoDefaultValue | efDontCheckMinimumCount),
-      _info(this), _sc(NULL), _selectionFlags(settings._selectionFlags)
+      info_(this), manager_(NULL), selectionFlags_(settings._selectionFlags)
 {
     GMX_RELEASE_ASSERT(!hasFlag(efMulti),
                        "allowMultiple() is not supported for selection options");
     if (settings._infoPtr != NULL)
     {
-        *settings._infoPtr = &_info;
+        *settings._infoPtr = &info_;
     }
 }
 
@@ -97,7 +97,7 @@ void SelectionOptionStorage::addSelections(
     {
         // TODO: Having this check in the parser would make interactive input
         // behave better.
-        if (_selectionFlags.test(efOnlyStatic) && i->isDynamic())
+        if (selectionFlags_.test(efOnlyStatic) && i->isDynamic())
         {
             GMX_THROW(InvalidInputError("Dynamic selections not supported"));
         }
@@ -112,20 +112,20 @@ void SelectionOptionStorage::addSelections(
 
 void SelectionOptionStorage::convertValue(const std::string &value)
 {
-    GMX_RELEASE_ASSERT(_sc != NULL, "Selection collection is not set");
+    GMX_RELEASE_ASSERT(manager_ != NULL, "Manager is not set");
 
     SelectionList selections;
-    _sc->parseFromString(value, &selections);
+    manager_->selectionCollection().parseFromString(value, &selections);
     addSelections(selections, false);
 }
 
 void SelectionOptionStorage::processSetValues(ValueList *values)
 {
-    GMX_RELEASE_ASSERT(_sc != NULL, "Selection collection is not set");
+    GMX_RELEASE_ASSERT(manager_ != NULL, "Manager is not set");
 
     if (values->size() == 0)
     {
-        _sc->_impl->requestSelections(name(), description(), this);
+        manager_->requestDelayedParsing(this);
     }
     else if (values->size() < static_cast<size_t>(minValueCount()))
     {
@@ -134,7 +134,7 @@ void SelectionOptionStorage::processSetValues(ValueList *values)
     ValueList::iterator i;
     for (i = values->begin(); i != values->end(); ++i)
     {
-        i->data().setFlags(_selectionFlags);
+        i->data().setFlags(selectionFlags_);
     }
 }
 
@@ -142,9 +142,9 @@ void SelectionOptionStorage::processAll()
 {
     if (isRequired() && !isSet())
     {
-        GMX_RELEASE_ASSERT(_sc != NULL, "Selection collection is not set");
+        GMX_RELEASE_ASSERT(manager_ != NULL, "Manager is not set");
 
-        _sc->_impl->requestSelections(name(), description(), this);
+        manager_->requestDelayedParsing(this);
         setFlag(efSet);
     }
 }
@@ -192,10 +192,10 @@ void SelectionOptionStorage::setSelectionFlag(SelectionFlag flag, bool bSet)
             GMX_THROW(InvalidInputError(errors.toString()));
         }
     }
-    _selectionFlags.set(flag, bSet);
+    selectionFlags_.set(flag, bSet);
     for (i = values().begin(); i != values().end(); ++i)
     {
-        i->data().setFlags(_selectionFlags);
+        i->data().setFlags(selectionFlags_);
     }
 }
 
@@ -219,9 +219,9 @@ const SelectionOptionStorage &SelectionOptionInfo::option() const
     return static_cast<const SelectionOptionStorage &>(OptionInfo::option());
 }
 
-void SelectionOptionInfo::setSelectionCollection(SelectionCollection *selections)
+void SelectionOptionInfo::setManager(SelectionOptionManager *manager)
 {
-    option().setSelectionCollection(selections);
+    option().setManager(manager);
 }
 
 void SelectionOptionInfo::setValueCount(int count)
@@ -276,7 +276,7 @@ AbstractOptionStoragePointer SelectionOption::createStorage() const
 
 SelectionFileOptionStorage::SelectionFileOptionStorage(const SelectionFileOption &settings)
     : AbstractOptionStorage(settings, OptionFlags() | efMulti | efDontCheckMinimumCount),
-      info_(this), sc_(NULL), bValueParsed_(false)
+      info_(this), manager_(NULL), bValueParsed_(false)
 {
 }
 
@@ -287,7 +287,7 @@ void SelectionFileOptionStorage::clearSet()
 
 void SelectionFileOptionStorage::convertValue(const std::string &value)
 {
-    GMX_RELEASE_ASSERT(sc_ != NULL, "Selection collection is not set");
+    GMX_RELEASE_ASSERT(manager_ != NULL, "Manager is not set");
 
     if (bValueParsed_)
     {
@@ -295,7 +295,7 @@ void SelectionFileOptionStorage::convertValue(const std::string &value)
     }
     bValueParsed_ = true;
     // TODO: Should we throw an InvalidInputError if the file does not exist?
-    sc_->parseRequestedFromFile(value);
+    manager_->parseRequestedFromFile(value);
 }
 
 void SelectionFileOptionStorage::processSet()
@@ -326,9 +326,9 @@ const SelectionFileOptionStorage &SelectionFileOptionInfo::option() const
     return static_cast<const SelectionFileOptionStorage &>(OptionInfo::option());
 }
 
-void SelectionFileOptionInfo::setSelectionCollection(SelectionCollection *selections)
+void SelectionFileOptionInfo::setManager(SelectionOptionManager *manager)
 {
-    option().setSelectionCollection(selections);
+    option().setManager(manager);
 }
 
 
@@ -356,16 +356,16 @@ namespace
 {
 
 /*! \internal \brief
- * Visitor that sets the selection collection for each selection option.
+ * Visitor that sets the manager for each selection option.
  *
  * \ingroup module_selection
  */
-class SelectionCollectionSetter : public OptionsModifyingVisitor
+class SelectionOptionManagerSetter : public OptionsModifyingVisitor
 {
     public:
-        //! Construct a visitor that sets given selection collection.
-        explicit SelectionCollectionSetter(SelectionCollection *selections)
-            : selections_(selections)
+        //! Construct a visitor that sets given manager.
+        explicit SelectionOptionManagerSetter(SelectionOptionManager *manager)
+            : manager_(manager)
         {
         }
 
@@ -382,26 +382,26 @@ class SelectionCollectionSetter : public OptionsModifyingVisitor
                 = option->toType<SelectionOptionInfo>();
             if (selOption != NULL)
             {
-                selOption->setSelectionCollection(selections_);
+                selOption->setManager(manager_);
             }
             SelectionFileOptionInfo *selFileOption
                 = option->toType<SelectionFileOptionInfo>();
             if (selFileOption != NULL)
             {
-                selFileOption->setSelectionCollection(selections_);
+                selFileOption->setManager(manager_);
             }
         }
 
     private:
-        SelectionCollection    *selections_;
+        SelectionOptionManager *manager_;
 };
 
 } // namespace
 
-void setSelectionCollectionForOptions(Options *options,
-                                      SelectionCollection *selections)
+void setManagerForSelectionOptions(Options *options,
+                                   SelectionOptionManager *manager)
 {
-    SelectionCollectionSetter(selections).visitSubSection(options);
+    SelectionOptionManagerSetter(manager).visitSubSection(options);
 }
 
 } // namespace gmx
index 9e28e0943df17e5598040db86ee33eb882bb0c50..3a05b2c85115c95a44354e9a60ca906969d11c15 100644 (file)
@@ -45,7 +45,7 @@ namespace gmx
 {
 
 class Options;
-class SelectionCollection;
+class SelectionOptionManager;
 class SelectionOptionStorage;
 
 /*! \brief
@@ -103,19 +103,20 @@ class SelectionOptionInfo : public OptionInfo
         explicit SelectionOptionInfo(SelectionOptionStorage *option);
 
         /*! \brief
-         * Set selection collection into which this option adds selections.
+         * Set manager for handling interaction with other options and the
+         * selection collection.
          *
-         * \param   selections  Selection collection to set.
+         * \param   manager  Selection manager to set.
          *
          * This must be called before the values are added.
          *
-         * Typically it is called through setSelectionCollectionForOptions(),
-         * which recursively sets the collection for all selection options in
+         * Typically it is called through setManagerForSelectionOptions(),
+         * which recursively sets the manager for all selection options in
          * an Options object.
          *
          * Does not throw.
          */
-        void setSelectionCollection(SelectionCollection *selections);
+        void setManager(SelectionOptionManager *manager);
 
         /*! \brief
          * Sets the number of selections allowed for the option.
@@ -201,18 +202,18 @@ class SelectionOptionInfo : public OptionInfo
 };
 
 /*! \brief
- * Set selection collection for all selection options.
+ * Set manager for all selection options.
  *
- * Recursively sets the selection collection to \p selections for all selection
- * options in \p options.
+ * Recursively sets the manager to \p manager for all selection options in
+ * \p options.
  * Must be called before value assignment starts for \p options.
  *
  * Does not throw.
  *
  * \inpublicapi
  */
-void setSelectionCollectionForOptions(Options *options,
-                                      SelectionCollection *selections);
+void setManagerForSelectionOptions(Options *options,
+                                   SelectionOptionManager *manager);
 
 } // namespace gmx
 
diff --git a/src/gromacs/selection/selectionoptionmanager.cpp b/src/gromacs/selection/selectionoptionmanager.cpp
new file mode 100644 (file)
index 0000000..d18b721
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements gmx::SelectionOptionManager.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#include "selectionoptionmanager.h"
+
+#include <cstdio>
+
+#include "gromacs/selection/selection.h"
+#include "gromacs/selection/selectioncollection.h"
+#include "gromacs/utility/exceptions.h"
+#include "gromacs/utility/format.h"
+
+#include "selectionoptionstorage.h"
+
+namespace gmx
+{
+
+/********************************************************************
+ * SelectionOptionManager::Impl
+ */
+
+/*! \internal \brief
+ * Private implemention class for SelectionOptionManager.
+ *
+ * \ingroup module_selection
+ */
+class SelectionOptionManager::Impl
+{
+    public:
+        /*! \brief
+         * Request for postponed parsing of selections.
+         */
+        struct SelectionRequest
+        {
+            //! Initializes a request for the given option.
+            explicit SelectionRequest(SelectionOptionStorage *storage)
+                : storage_(storage)
+            {
+            }
+
+            //! Returns name of the requested selection optin.
+            const std::string &name() const
+            {
+                return storage_->name();
+            }
+            //! Returns description for the requested selection option.
+            const std::string &description() const
+            {
+                return storage_->description();
+            }
+            /*! \brief
+             * Returns the number of selections requested in this request.
+             *
+             * -1 indicates no upper limit.
+             */
+            int count() const
+            {
+                return storage_->maxValueCount();
+            }
+
+            //! Storage object to which the selections will be added.
+            SelectionOptionStorage     *storage_;
+        };
+
+        //! Collection for a list of selection requests.
+        typedef std::vector<SelectionRequest> RequestList;
+
+        /*! \brief
+         * Helper class that clears a request list on scope exit.
+         *
+         * Methods in this class do not throw.
+         */
+        class RequestsClearer
+        {
+            public:
+                //! Constructs an object that clears given list on scope exit.
+                explicit RequestsClearer(RequestList *requests)
+                    : requests_(requests)
+                {
+                }
+                //! Clears the request list given to the constructor.
+                ~RequestsClearer()
+                {
+                    requests_->clear();
+                }
+
+            private:
+                RequestList    *requests_;
+        };
+
+        /*! \brief
+         * Creates a new selection collection.
+         *
+         * \throws  std::bad_alloc if out of memory.
+         */
+        explicit Impl(SelectionCollection *collection);
+
+        /*! \brief
+         * Assign selections from a list to pending requests.
+         *
+         * \param[in] selections  List of selections to assign.
+         * \throws    std::bad_alloc if out of memory.
+         * \throws    InvalidInputError if the assignment cannot be done
+         *      (see parseRequestedFromFile() for documented conditions).
+         *
+         * Loops through \p selections and the pending requests lists in order,
+         * and for each requests, assigns the first yet unassigned selections
+         * from the list.
+         */
+        void placeSelectionsInRequests(const SelectionList &selections);
+
+        //! Selection collection to which selections are stored.
+        SelectionCollection    &collection_;
+        //! List of selections requested for later parsing.
+        RequestList             requests_;
+};
+
+SelectionOptionManager::Impl::Impl(SelectionCollection *collection)
+    : collection_(*collection)
+{
+}
+
+void SelectionOptionManager::Impl::placeSelectionsInRequests(
+        const SelectionList &selections)
+{
+    RequestsClearer clearRequestsOnExit(&requests_);
+
+    SelectionList::const_iterator first = selections.begin();
+    SelectionList::const_iterator last = first;
+    RequestList::const_iterator i;
+    // TODO: Improve error messages.
+    for (i = requests_.begin(); i != requests_.end(); ++i)
+    {
+        const SelectionRequest &request = *i;
+        if (request.count() > 0)
+        {
+            if (selections.end() - first < request.count())
+            {
+                GMX_THROW(InvalidInputError("Too few selections provided"));
+            }
+            last = first + request.count();
+        }
+        else
+        {
+            if (i != requests_.end() - 1)
+            {
+                GMX_THROW(InvalidInputError(
+                            formatString("Request for selection '%s' must "
+                                         "not be followed by others",
+                                         request.name().c_str())));
+            }
+            last = selections.end();
+        }
+        SelectionList curr(first, last);
+        request.storage_->addSelections(curr, true);
+        first = last;
+    }
+    if (last != selections.end())
+    {
+        GMX_THROW(InvalidInputError("Too many selections provided"));
+    }
+}
+
+
+/********************************************************************
+ * SelectionOptionManager
+ */
+
+SelectionOptionManager::SelectionOptionManager(SelectionCollection *collection)
+    : impl_(new Impl(collection))
+{
+}
+
+SelectionOptionManager::~SelectionOptionManager()
+{
+}
+
+SelectionCollection &
+SelectionOptionManager::selectionCollection()
+{
+    return impl_->collection_;
+}
+
+void
+SelectionOptionManager::requestDelayedParsing(SelectionOptionStorage *storage)
+{
+    impl_->requests_.push_back(Impl::SelectionRequest(storage));
+}
+
+void
+SelectionOptionManager::parseRequestedFromStdin(bool bInteractive)
+{
+    Impl::RequestsClearer clearRequestsOnExit(&impl_->requests_);
+
+    Impl::RequestList::const_iterator i;
+    for (i = impl_->requests_.begin(); i != impl_->requests_.end(); ++i)
+    {
+        const Impl::SelectionRequest &request = *i;
+        if (bInteractive)
+        {
+            std::fprintf(stderr, "\nSpecify ");
+            if (request.count() < 0)
+            {
+                std::fprintf(stderr, "any number of selections");
+            }
+            else if (request.count() == 1)
+            {
+                std::fprintf(stderr, "a selection");
+            }
+            else
+            {
+                std::fprintf(stderr, "%d selections", request.count());
+            }
+            std::fprintf(stderr, " for option '%s' (%s):\n",
+                         request.name().c_str(), request.description().c_str());
+            std::fprintf(stderr, "(one selection per line, 'help' for help%s)\n",
+                         request.count() < 0 ? ", Ctrl-D to end" : "");
+        }
+        SelectionList selections;
+        impl_->collection_.parseFromStdin(request.count(), bInteractive, &selections);
+        request.storage_->addSelections(selections, true);
+    }
+}
+
+void
+SelectionOptionManager::parseRequestedFromFile(const std::string &filename)
+{
+    SelectionList selections;
+    impl_->collection_.parseFromFile(filename, &selections);
+    impl_->placeSelectionsInRequests(selections);
+}
+
+void
+SelectionOptionManager::parseRequestedFromString(const std::string &str)
+{
+    SelectionList selections;
+    impl_->collection_.parseFromString(str, &selections);
+    impl_->placeSelectionsInRequests(selections);
+}
+
+} // namespace gmx
diff --git a/src/gromacs/selection/selectionoptionmanager.h b/src/gromacs/selection/selectionoptionmanager.h
new file mode 100644 (file)
index 0000000..7b02505
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \file
+ * \brief
+ * Declares gmx::SelectionOptionManager.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inpublicapi
+ * \ingroup module_selection
+ */
+#ifndef GMX_SELECTION_SELECTIONOPTIONMANAGER_H
+#define GMX_SELECTION_SELECTIONOPTIONMANAGER_H
+
+#include <string>
+
+#include "../utility/common.h"
+
+namespace gmx
+{
+
+class SelectionCollection;
+class SelectionOptionStorage;
+
+/*! \brief
+ * Handles interaction of selection options with other options and user input.
+ *
+ * This class implements features of SelectionOption that require actions
+ * outside options parsing.  It is also used to pass the selection collection
+ * to the selection options, and to implement the coupling between
+ * SelectionOption and SelectionFileOption.
+ *
+ * The main feature of this class (in addition to passing the
+ * selectionCollection() method) is that the internal implementation of
+ * selection options calls requestDelayedParsing() when an option is provided
+ * on the command line without a value.  Such calls are remembered, and
+ * the value for all requested options can be later provided by calling one of
+ * parseRequestedFromStdin(), parseRequestedFromFile() or
+ * parseRequstedFromString().
+ *
+ * \see setManagerForSelectionOptions()
+ *
+ * \inpublicapi
+ * \ingroup module_selection
+ */
+class SelectionOptionManager
+{
+    public:
+        /*! \brief
+         * Creates a manager for selection options.
+         *
+         * \throws  std::bad_alloc if out of memory.
+         */
+        explicit SelectionOptionManager(SelectionCollection *selections);
+        ~SelectionOptionManager();
+
+        /*! \brief
+         * Returns the selection collection for this manager.
+         *
+         * Does not throw.
+         */
+        SelectionCollection &selectionCollection();
+        /*! \brief
+         * Adds a selection option for delayed user input.
+         *
+         * \param     storage  Storage object for the option to request.
+         * \throws    std::bad_alloc if out of memory.
+         *
+         * This is only for internal use by the selection module.
+         * It is not possible to obtain a SelectionOptionStorage pointer
+         * through any public or library API.
+         *
+         * Strong exception safety.
+         */
+        void requestDelayedParsing(SelectionOptionStorage *storage);
+
+        /*! \brief
+         * Parses selection(s) from standard input for options not yet
+         * provided.
+         *
+         * \param[in]  bInteractive Whether the parser should behave
+         *      interactively.
+         * \throws     unspecified  Can throw any exception thrown by
+         *      SelectionCollection::parseFromStdin().
+         * \throws     std::bad_alloc if out of memory.
+         *
+         * This method cooperates with SelectionOption to allow interactive
+         * input of requested selections after all options have been processed.
+         * It should be called after the Options::finish() method has been
+         * called on all options that add selections to this collection.
+         * For each required selection option that has not been given, as well
+         * as for optional selection options that have been specified without
+         * values, it will prompt the user to input the necessary selections.
+         */
+        void parseRequestedFromStdin(bool bInteractive);
+        /*! \brief
+         * Parses selection(s) from a file for options not yet provided.
+         *
+         * \param[in]  filename Name of the file to parse selections from.
+         * \throws     unspecified  Can throw any exception thrown by
+         *      SelectionCollection::parseFromFile().
+         * \throws     std::bad_alloc if out of memory.
+         * \throws     InvalidInputError if
+         *      - the number of selections in \p filename doesn't match the
+         *        number requested.
+         *      - any selection uses a feature that is not allowed for the
+         *        corresponding option.
+         *      - if there is a request for any number of selections that is
+         *        not the last (in which case it is not possible to determine
+         *        which selections belong to which request).
+         *
+         * This method behaves as parseRequestedFromStdin(), but reads the
+         * selections from a file instead of standard input.
+         * This is used to implement SelectionFileOption.
+         *
+         * \see parseRequestedFromStdin()
+         */
+        void parseRequestedFromFile(const std::string &filename);
+        /*! \brief
+         * Parses selection(s) from a string for options not yet provided.
+         *
+         * \param[in]  str     String to parse.
+         * \throws     unspecified  Can throw any exception thrown by
+         *      SelectionCollection::parseFromString().
+         * \throws     std::bad_alloc if out of memory.
+         * \throws     InvalidInputError in same conditions as
+         *      parseRequestedFromFile().
+         *
+         * This method behaves as parseRequestedFromFile(), but reads the
+         * selections from a string instead of a file.
+         * This method is mainly used for testing.
+         *
+         * \see parseRequestedFromFile()
+         */
+        void parseRequestedFromString(const std::string &str);
+
+    private:
+        class Impl;
+
+        PrivateImplPointer<Impl> impl_;
+
+        /*! \brief
+         * Needed for handling delayed selection parsing requests.
+         */
+        friend class SelectionOptionStorage;
+};
+
+} // namespace gmx
+
+#endif
index 368461dd68953dbf9a61903dabf991ece25636c7..9de8e3b0212b091f052a347ee8d1824733d62c33 100644 (file)
@@ -46,8 +46,8 @@
 namespace gmx
 {
 
-class SelectionCollection;
 class SelectionOption;
+class SelectionOptionManager;
 
 /*! \internal \brief
  * Converts, validates, and stores selection values.
@@ -64,14 +64,14 @@ class SelectionOptionStorage : public OptionStorageTemplate<Selection>
          */
         SelectionOptionStorage(const SelectionOption &settings);
 
-        virtual OptionInfo &optionInfo() { return _info; }
+        virtual OptionInfo &optionInfo() { return info_; }
         virtual const char *typeString() const { return "sel"; }
         virtual std::string formatSingleValue(const Selection &value) const;
 
-        //! \copydoc SelectionOptionInfo::setSelectionCollection()
-        void setSelectionCollection(SelectionCollection *selections)
+        //! \copydoc SelectionOptionInfo::setManager()
+        void setManager(SelectionOptionManager *manager)
         {
-            _sc = selections;
+            manager_ = manager;
         }
 
         /*! \brief
@@ -86,11 +86,9 @@ class SelectionOptionStorage : public OptionStorageTemplate<Selection>
          *      - Any selection in \p selections is not allowed for this
          *        option.
          *
-         * This function is used to implement the methods
-         * SelectionCollection::parseRequestedFromStdin() and
-         * SelectionCollection::parseRequestedFromString() (called with
-         * \p bFullValue set to true), as well as internally by the storage
-         * class (called with \p bFullValue set to false).
+         * This function is used to add selections from SelectionOptionManager
+         * (called with \p bFullValue set to true), as well as internally by
+         * the storage class (called with \p bFullValue set to false).
          */
         void addSelections(const SelectionList &selections,
                            bool bFullValue);
@@ -122,9 +120,9 @@ class SelectionOptionStorage : public OptionStorageTemplate<Selection>
         virtual void processSetValues(ValueList *values);
         virtual void processAll();
 
-        SelectionOptionInfo     _info;
-        SelectionCollection    *_sc;
-        SelectionFlags          _selectionFlags;
+        SelectionOptionInfo     info_;
+        SelectionOptionManager *manager_;
+        SelectionFlags          selectionFlags_;
 };
 
 } // namespace gmx
index 4e3c2feae6859a9fda0aa0e42abfed205d6b4e64..710c74ca88b82667426462857c2feb540f7619cd 100644 (file)
 #include "gromacs/options/optionsassigner.h"
 #include "gromacs/selection/selection.h"
 #include "gromacs/selection/selectioncollection.h"
+#include "gromacs/selection/selectionfileoption.h"
 #include "gromacs/selection/selectionoption.h"
 #include "gromacs/selection/selectionoptioninfo.h"
-#include "gromacs/selection/selectionfileoption.h"
+#include "gromacs/selection/selectionoptionmanager.h"
 #include "gromacs/utility/exceptions.h"
 
 #include "testutils/datapath.h"
@@ -60,22 +61,23 @@ class SelectionOptionTestBase : public ::testing::Test
     public:
         SelectionOptionTestBase();
 
-        void setCollection();
+        void setManager();
 
-        gmx::SelectionCollection _sc;
-        gmx::Options             _options;
+        gmx::SelectionCollection    _sc;
+        gmx::SelectionOptionManager _manager;
+        gmx::Options                _options;
 };
 
 SelectionOptionTestBase::SelectionOptionTestBase()
-    : _options(NULL, NULL)
+    : _manager(&_sc), _options(NULL, NULL)
 {
     _sc.setReferencePosType("atom");
     _sc.setOutputPosType("atom");
 }
 
-void SelectionOptionTestBase::setCollection()
+void SelectionOptionTestBase::setManager()
 {
-    setSelectionCollectionForOptions(&_options, &_sc);
+    setManagerForSelectionOptions(&_options, &_manager);
 }
 
 
@@ -90,7 +92,7 @@ TEST_F(SelectionOptionTest, ParsesSimpleSelection)
     gmx::Selection sel;
     using gmx::SelectionOption;
     ASSERT_NO_THROW(_options.addOption(SelectionOption("sel").store(&sel)));
-    setCollection();
+    setManager();
 
     gmx::OptionsAssigner assigner(&_options);
     EXPECT_NO_THROW(assigner.start());
@@ -110,7 +112,7 @@ TEST_F(SelectionOptionTest, HandlesDynamicSelectionWhenStaticRequired)
     using gmx::SelectionOption;
     ASSERT_NO_THROW(_options.addOption(
                         SelectionOption("sel").store(&sel).onlyStatic()));
-    setCollection();
+    setManager();
 
     gmx::OptionsAssigner assigner(&_options);
     EXPECT_NO_THROW(assigner.start());
@@ -127,7 +129,7 @@ TEST_F(SelectionOptionTest, HandlesTooManySelections)
     gmx::Selection sel;
     using gmx::SelectionOption;
     ASSERT_NO_THROW(_options.addOption(SelectionOption("sel").store(&sel)));
-    setCollection();
+    setManager();
 
     gmx::OptionsAssigner assigner(&_options);
     EXPECT_NO_THROW(assigner.start());
@@ -147,7 +149,7 @@ TEST_F(SelectionOptionTest, HandlesTooFewSelections)
     using gmx::SelectionOption;
     ASSERT_NO_THROW(_options.addOption(
                         SelectionOption("sel").store(sel).valueCount(2)));
-    setCollection();
+    setManager();
 
     gmx::OptionsAssigner assigner(&_options);
     EXPECT_NO_THROW(assigner.start());
@@ -167,7 +169,7 @@ TEST_F(SelectionOptionTest, HandlesAdjuster)
     ASSERT_NO_THROW(_options.addOption(
                         SelectionOption("sel").storeVector(&sel).multiValue()
                             .getAdjuster(&info)));
-    setCollection();
+    setManager();
 
     gmx::OptionsAssigner assigner(&_options);
     EXPECT_NO_THROW(assigner.start());
@@ -189,7 +191,7 @@ TEST_F(SelectionOptionTest, HandlesDynamicWhenStaticRequiredWithAdjuster)
     ASSERT_NO_THROW(_options.addOption(
                         SelectionOption("sel").store(&sel)
                             .getAdjuster(&info)));
-    setCollection();
+    setManager();
 
     gmx::OptionsAssigner assigner(&_options);
     EXPECT_NO_THROW(assigner.start());
@@ -210,7 +212,7 @@ TEST_F(SelectionOptionTest, HandlesTooManySelectionsWithAdjuster)
     ASSERT_NO_THROW(_options.addOption(
                         SelectionOption("sel").storeVector(&sel).multiValue()
                             .getAdjuster(&info)));
-    setCollection();
+    setManager();
 
     gmx::OptionsAssigner assigner(&_options);
     EXPECT_NO_THROW(assigner.start());
@@ -232,7 +234,7 @@ TEST_F(SelectionOptionTest, HandlesTooFewSelectionsWithAdjuster)
     ASSERT_NO_THROW(_options.addOption(
                         SelectionOption("sel").storeVector(&sel).multiValue()
                             .getAdjuster(&info)));
-    setCollection();
+    setManager();
 
     gmx::OptionsAssigner assigner(&_options);
     EXPECT_NO_THROW(assigner.start());
@@ -251,13 +253,13 @@ TEST_F(SelectionOptionTest, HandlesDelayedRequiredSelection)
     using gmx::SelectionOption;
     ASSERT_NO_THROW(_options.addOption(
                         SelectionOption("sel").store(&sel).required()));
-    setCollection();
+    setManager();
 
     gmx::OptionsAssigner assigner(&_options);
     EXPECT_NO_THROW(assigner.start());
     EXPECT_NO_THROW(assigner.finish());
     EXPECT_NO_THROW(_options.finish());
-    EXPECT_NO_THROW(_sc.parseRequestedFromString("resname RA RB"));
+    EXPECT_NO_THROW(_manager.parseRequestedFromString("resname RA RB"));
     ASSERT_STREQ("resname RA RB", sel.selectionText());
 }
 
@@ -269,13 +271,13 @@ TEST_F(SelectionOptionTest, HandlesTooFewDelayedRequiredSelections)
     ASSERT_NO_THROW(_options.addOption(
                         SelectionOption("sel").store(sel).required()
                             .valueCount(2)));
-    setCollection();
+    setManager();
 
     gmx::OptionsAssigner assigner(&_options);
     EXPECT_NO_THROW(assigner.start());
     EXPECT_NO_THROW(assigner.finish());
     EXPECT_NO_THROW(_options.finish());
-    EXPECT_THROW(_sc.parseRequestedFromString("resname RA RB"), gmx::InvalidInputError);
+    EXPECT_THROW(_manager.parseRequestedFromString("resname RA RB"), gmx::InvalidInputError);
 }
 
 
@@ -284,7 +286,7 @@ TEST_F(SelectionOptionTest, HandlesDelayedOptionalSelection)
     gmx::Selection sel;
     using gmx::SelectionOption;
     ASSERT_NO_THROW(_options.addOption(SelectionOption("sel").store(&sel)));
-    setCollection();
+    setManager();
 
     gmx::OptionsAssigner assigner(&_options);
     EXPECT_NO_THROW(assigner.start());
@@ -292,7 +294,7 @@ TEST_F(SelectionOptionTest, HandlesDelayedOptionalSelection)
     EXPECT_NO_THROW(assigner.finishOption());
     EXPECT_NO_THROW(assigner.finish());
     EXPECT_NO_THROW(_options.finish());
-    EXPECT_NO_THROW(_sc.parseRequestedFromString("resname RA RB"));
+    EXPECT_NO_THROW(_manager.parseRequestedFromString("resname RA RB"));
     ASSERT_STREQ("resname RA RB", sel.selectionText());
 }
 
@@ -305,7 +307,7 @@ TEST_F(SelectionOptionTest, HandlesDelayedSelectionWithAdjuster)
     ASSERT_NO_THROW(_options.addOption(
                         SelectionOption("sel").storeVector(&sel).valueCount(3)
                             .getAdjuster(&info)));
-    setCollection();
+    setManager();
 
     gmx::OptionsAssigner assigner(&_options);
     EXPECT_NO_THROW(assigner.start());
@@ -314,7 +316,7 @@ TEST_F(SelectionOptionTest, HandlesDelayedSelectionWithAdjuster)
     EXPECT_NO_THROW(assigner.finish());
     EXPECT_NO_THROW(_options.finish());
     EXPECT_NO_THROW(info->setValueCount(2));
-    EXPECT_NO_THROW(_sc.parseRequestedFromString("resname RA RB; resname RB RC"));
+    EXPECT_NO_THROW(_manager.parseRequestedFromString("resname RA RB; resname RB RC"));
 }
 
 
@@ -340,7 +342,7 @@ TEST_F(SelectionFileOptionTest, HandlesSingleSelectionOptionFromFile)
     using gmx::SelectionOption;
     ASSERT_NO_THROW(_options.addOption(
                         SelectionOption("sel").storeVector(&sel).multiValue()));
-    setCollection();
+    setManager();
 
     gmx::OptionsAssigner assigner(&_options);
     EXPECT_NO_THROW(assigner.start());
@@ -368,7 +370,7 @@ TEST_F(SelectionFileOptionTest, HandlesTwoSeparateSelectionOptions)
                         SelectionOption("sel1").storeVector(&sel1).multiValue()));
     ASSERT_NO_THROW(_options.addOption(
                         SelectionOption("sel2").storeVector(&sel2).multiValue()));
-    setCollection();
+    setManager();
 
     gmx::OptionsAssigner assigner(&_options);
     std::string value(gmx::test::getTestFilePath("selfile.dat"));
@@ -405,7 +407,7 @@ TEST_F(SelectionFileOptionTest, HandlesTwoSelectionOptionsFromSingleFile)
                         SelectionOption("sel1").storeVector(&sel1)));
     ASSERT_NO_THROW(_options.addOption(
                         SelectionOption("sel2").storeVector(&sel2)));
-    setCollection();
+    setManager();
 
     gmx::OptionsAssigner assigner(&_options);
     std::string value(gmx::test::getTestFilePath("selfile.dat"));
@@ -434,7 +436,7 @@ TEST_F(SelectionFileOptionTest, GivesErrorWithNoFile)
     using gmx::SelectionOption;
     ASSERT_NO_THROW(_options.addOption(
                         SelectionOption("sel").storeVector(&sel).multiValue()));
-    setCollection();
+    setManager();
 
     gmx::OptionsAssigner assigner(&_options);
     EXPECT_NO_THROW(assigner.start());
@@ -453,7 +455,7 @@ TEST_F(SelectionFileOptionTest, GivesErrorWithNonExistentFile)
     using gmx::SelectionOption;
     ASSERT_NO_THROW(_options.addOption(
                         SelectionOption("sel").storeVector(&sel).multiValue()));
-    setCollection();
+    setManager();
 
     gmx::OptionsAssigner assigner(&_options);
     EXPECT_NO_THROW(assigner.start());
@@ -476,7 +478,7 @@ TEST_F(SelectionFileOptionTest, GivesErrorWithMultipleFiles)
     using gmx::SelectionOption;
     ASSERT_NO_THROW(_options.addOption(
                         SelectionOption("sel").storeVector(&sel).multiValue()));
-    setCollection();
+    setManager();
 
     gmx::OptionsAssigner assigner(&_options);
     EXPECT_NO_THROW(assigner.start());
index 144da8e7b6fe128d3ffb6c1e82cf3097b75c1f19..143ed1e70d5c4d0af85fd6b8b64ff77a20610be4 100644 (file)
@@ -50,6 +50,7 @@
 #include "gromacs/options/options.h"
 #include "gromacs/selection/selectioncollection.h"
 #include "gromacs/selection/selectionoptioninfo.h"
+#include "gromacs/selection/selectionoptionmanager.h"
 #include "gromacs/trajectoryanalysis/analysismodule.h"
 #include "gromacs/trajectoryanalysis/analysissettings.h"
 #include "gromacs/trajectoryanalysis/cmdlinerunner.h"
@@ -77,6 +78,7 @@ class TrajectoryAnalysisCommandLineRunner::Impl
         bool parseOptions(TrajectoryAnalysisSettings *settings,
                           TrajectoryAnalysisRunnerCommon *common,
                           SelectionCollection *selections,
+                          SelectionOptionManager *seloptManager,
                           Options *options,
                           int *argc, char *argv[]);
 
@@ -121,6 +123,7 @@ TrajectoryAnalysisCommandLineRunner::Impl::parseOptions(
         TrajectoryAnalysisSettings *settings,
         TrajectoryAnalysisRunnerCommon *common,
         SelectionCollection *selections,
+        SelectionOptionManager *seloptManager,
         Options *options,
         int *argc, char *argv[])
 {
@@ -132,7 +135,7 @@ TrajectoryAnalysisCommandLineRunner::Impl::parseOptions(
     options->addSubSection(&selectionOptions);
     options->addSubSection(&moduleOptions);
 
-    setSelectionCollectionForOptions(options, selections);
+    setManagerForSelectionOptions(options, seloptManager);
 
     {
         CommandLineParser  parser(options);
@@ -160,7 +163,7 @@ TrajectoryAnalysisCommandLineRunner::Impl::parseOptions(
 
     // TODO: Check whether the input is a pipe.
     bool bInteractive = true;
-    selections->parseRequestedFromStdin(bInteractive);
+    seloptManager->parseRequestedFromStdin(bInteractive);
     common->doneIndexGroups(selections);
 
     return true;
@@ -209,13 +212,14 @@ TrajectoryAnalysisCommandLineRunner::run(int argc, char *argv[])
 
     SelectionCollection  selections;
     selections.setDebugLevel(_impl->_debugLevel);
+    SelectionOptionManager seloptManager(&selections);
 
     TrajectoryAnalysisSettings  settings;
     TrajectoryAnalysisRunnerCommon  common(&settings);
 
     Options  options(NULL, NULL);
-    if (!_impl->parseOptions(&settings, &common, &selections, &options,
-                             &argc, argv))
+    if (!_impl->parseOptions(&settings, &common, &selections, &seloptManager,
+                             &options, &argc, argv))
     {
         return 0;
     }