Sort all includes in src/gromacs
[alexxy/gromacs.git] / src / gromacs / selection / selectionoption.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2010,2011,2012,2013,2014, by the GROMACS development team, led by
5  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6  * and including many others, as listed in the AUTHORS file in the
7  * top-level source directory and at http://www.gromacs.org.
8  *
9  * GROMACS is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1
12  * of the License, or (at your option) any later version.
13  *
14  * GROMACS is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with GROMACS; if not, see
21  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
23  *
24  * If you want to redistribute modifications to GROMACS, please
25  * consider that scientific software is very special. Version
26  * control is crucial - bugs must be traceable. We will be happy to
27  * consider code for inclusion in the official distribution, but
28  * derived work must not be called official GROMACS. Details are found
29  * in the README & COPYING files - if they are missing, get the
30  * official version at http://www.gromacs.org.
31  *
32  * To help us fund GROMACS development, we humbly ask that you cite
33  * the research papers on the package. Check out http://www.gromacs.org.
34  */
35 /*! \internal \file
36  * \brief
37  * Implements classes in selectionoption.h and selectionoptionstorage.h.
38  *
39  * \author Teemu Murtola <teemu.murtola@gmail.com>
40  * \ingroup module_selection
41  */
42 #include "gmxpre.h"
43
44 #include "selectionoption.h"
45
46 #include <string>
47
48 #include "gromacs/options/optionmanagercontainer.h"
49 #include "gromacs/selection/selection.h"
50 #include "gromacs/selection/selectionfileoption.h"
51 #include "gromacs/selection/selectionoptionmanager.h"
52 #include "gromacs/utility/exceptions.h"
53 #include "gromacs/utility/gmxassert.h"
54 #include "gromacs/utility/messagestringcollector.h"
55
56 #include "selectionfileoptionstorage.h"
57 #include "selectionoptionstorage.h"
58
59 namespace gmx
60 {
61
62 /********************************************************************
63  * SelectionOptionStorage
64  */
65
66 SelectionOptionStorage::SelectionOptionStorage(const SelectionOption  &settings,
67                                                SelectionOptionManager *manager)
68     : MyBase(settings, OptionFlags() | efOption_NoDefaultValue
69              | efOption_DontCheckMinimumCount),
70       info_(this), manager_(*manager), defaultText_(settings.defaultText_),
71       selectionFlags_(settings.selectionFlags_)
72 {
73     GMX_RELEASE_ASSERT(manager != NULL,
74                        "SelectionOptionManager must be added before SelectionOption");
75     GMX_RELEASE_ASSERT(!hasFlag(efOption_MultipleTimes),
76                        "allowMultiple() is not supported for selection options");
77     manager_.registerOption(this);
78 }
79
80
81 std::string SelectionOptionStorage::formatSingleValue(const Selection &value) const
82 {
83     return value.selectionText();
84 }
85
86
87 void SelectionOptionStorage::addSelections(
88         const SelectionList &selections,
89         bool                 bFullValue)
90 {
91     if (bFullValue && selections.size() < static_cast<size_t>(minValueCount()))
92     {
93         GMX_THROW(InvalidInputError("Too few selections provided"));
94     }
95     if (bFullValue)
96     {
97         clearSet();
98     }
99     SelectionList::const_iterator i;
100     for (i = selections.begin(); i != selections.end(); ++i)
101     {
102         // TODO: Having this check in the parser would make interactive input
103         // behave better.
104         if (selectionFlags_.test(efSelection_OnlyStatic) && i->isDynamic())
105         {
106             GMX_THROW(InvalidInputError("Dynamic selections not supported"));
107         }
108         // Create a copy to allow modifications.
109         Selection sel(*i);
110         sel.data().setFlags(selectionFlags_);
111         addValue(sel);
112     }
113     if (bFullValue)
114     {
115         commitValues();
116         markAsSet();
117     }
118 }
119
120
121 void SelectionOptionStorage::convertValue(const std::string &value)
122 {
123     manager_.convertOptionValue(this, value, false);
124 }
125
126 void SelectionOptionStorage::processSetValues(ValueList *values)
127 {
128     if (values->size() == 0)
129     {
130         manager_.requestOptionDelayedParsing(this);
131     }
132     else if (values->size() < static_cast<size_t>(minValueCount()))
133     {
134         GMX_THROW(InvalidInputError("Too few (valid) values provided"));
135     }
136 }
137
138 void SelectionOptionStorage::processAll()
139 {
140     if (!isSet() && !defaultText_.empty())
141     {
142         manager_.convertOptionValue(this, defaultText_, true);
143     }
144     if (isRequired() && !isSet())
145     {
146         manager_.requestOptionDelayedParsing(this);
147         markAsSet();
148     }
149 }
150
151 void SelectionOptionStorage::setAllowedValueCount(int count)
152 {
153     // TODO: It should be possible to have strong exception safety here.
154     MessageStringCollector errors;
155     errors.startContext("In option '" + name() + "'");
156     if (count >= 0)
157     {
158         // Should not throw because efOption_DontCheckMinimumCount is set.
159         setMinValueCount(count);
160         if (valueCount() > 0 && valueCount() < count)
161         {
162             errors.append("Too few (valid) values provided");
163         }
164     }
165     try
166     {
167         setMaxValueCount(count);
168     }
169     catch (const UserInputError &ex)
170     {
171         errors.append(ex.what());
172     }
173     errors.finishContext();
174     if (!errors.isEmpty())
175     {
176         GMX_THROW(InvalidInputError(errors.toString()));
177     }
178 }
179
180 void SelectionOptionStorage::setSelectionFlag(SelectionFlag flag, bool bSet)
181 {
182     ValueList::iterator i;
183     for (i = values().begin(); i != values().end(); ++i)
184     {
185         if (flag == efSelection_OnlyStatic && bSet && i->isDynamic())
186         {
187             MessageStringCollector errors;
188             errors.startContext("In option '" + name() + "'");
189             errors.append("Dynamic selections not supported");
190             errors.finishContext();
191             GMX_THROW(InvalidInputError(errors.toString()));
192         }
193     }
194     selectionFlags_.set(flag, bSet);
195     for (i = values().begin(); i != values().end(); ++i)
196     {
197         i->data().setFlags(selectionFlags_);
198     }
199 }
200
201
202 /********************************************************************
203  * SelectionOptionInfo
204  */
205
206 SelectionOptionInfo::SelectionOptionInfo(SelectionOptionStorage *option)
207     : OptionInfo(option)
208 {
209 }
210
211 SelectionOptionStorage &SelectionOptionInfo::option()
212 {
213     return static_cast<SelectionOptionStorage &>(OptionInfo::option());
214 }
215
216 const SelectionOptionStorage &SelectionOptionInfo::option() const
217 {
218     return static_cast<const SelectionOptionStorage &>(OptionInfo::option());
219 }
220
221 void SelectionOptionInfo::setValueCount(int count)
222 {
223     option().setAllowedValueCount(count);
224 }
225
226 void SelectionOptionInfo::setEvaluateVelocities(bool bEnabled)
227 {
228     option().setSelectionFlag(efSelection_EvaluateVelocities, bEnabled);
229 }
230
231 void SelectionOptionInfo::setEvaluateForces(bool bEnabled)
232 {
233     option().setSelectionFlag(efSelection_EvaluateForces, bEnabled);
234 }
235
236 void SelectionOptionInfo::setOnlyAtoms(bool bEnabled)
237 {
238     option().setSelectionFlag(efSelection_OnlyAtoms, bEnabled);
239 }
240
241 void SelectionOptionInfo::setOnlyStatic(bool bEnabled)
242 {
243     option().setSelectionFlag(efSelection_OnlyStatic, bEnabled);
244 }
245
246 void SelectionOptionInfo::setDynamicMask(bool bEnabled)
247 {
248     option().setSelectionFlag(efSelection_DynamicMask, bEnabled);
249 }
250
251
252 /********************************************************************
253  * SelectionOption
254  */
255
256 AbstractOptionStorage *
257 SelectionOption::createStorage(const OptionManagerContainer &managers) const
258 {
259     return new SelectionOptionStorage(
260             *this, managers.get<SelectionOptionManager>());
261 }
262
263
264 /********************************************************************
265  * SelectionFileOptionStorage
266  */
267
268 SelectionFileOptionStorage::SelectionFileOptionStorage(
269         const SelectionFileOption &settings, SelectionOptionManager *manager)
270     : AbstractOptionStorage(settings, OptionFlags() | efOption_MultipleTimes
271                             | efOption_DontCheckMinimumCount),
272       info_(this), manager_(*manager), bValueParsed_(false)
273 {
274     GMX_RELEASE_ASSERT(manager != NULL,
275                        "SelectionOptionManager must be added before SelectionFileOption");
276 }
277
278 void SelectionFileOptionStorage::clearSet()
279 {
280     bValueParsed_ = false;
281 }
282
283 void SelectionFileOptionStorage::convertValue(const std::string &value)
284 {
285     if (bValueParsed_)
286     {
287         GMX_THROW(InvalidInputError("More than one file name provided"));
288     }
289     bValueParsed_ = true;
290     // TODO: Should we throw an InvalidInputError if the file does not exist?
291     manager_.parseRequestedFromFile(value);
292 }
293
294 void SelectionFileOptionStorage::processSet()
295 {
296     if (!bValueParsed_)
297     {
298         GMX_THROW(InvalidInputError("No file name provided"));
299     }
300 }
301
302
303 /********************************************************************
304  * SelectionFileOptionInfo
305  */
306
307 SelectionFileOptionInfo::SelectionFileOptionInfo(SelectionFileOptionStorage *option)
308     : OptionInfo(option)
309 {
310 }
311
312
313 /********************************************************************
314  * SelectionFileOption
315  */
316
317 SelectionFileOption::SelectionFileOption(const char *name)
318     : AbstractOption(name)
319 {
320     setDescription("Provide selections from files");
321 }
322
323 AbstractOptionStorage *
324 SelectionFileOption::createStorage(const OptionManagerContainer &managers) const
325 {
326     return new SelectionFileOptionStorage(
327             *this, managers.get<SelectionOptionManager>());
328 }
329
330 } // namespace gmx