OpenWalnut  1.4.0
WPropertyGroupBase.h
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #ifndef WPROPERTYGROUPBASE_H
26 #define WPROPERTYGROUPBASE_H
27 
28 #include <map>
29 #include <string>
30 #include <vector>
31 
32 #include <boost/thread/thread.hpp>
33 #include <boost/thread/mutex.hpp>
34 #include <boost/thread/locks.hpp>
35 #include <boost/thread.hpp>
36 
37 #include "WConditionSet.h"
38 #include "WPropertyBase.h"
39 #include "WPropertyTypes.h"
40 #include "WPropertyVariable.h"
41 #include "WSharedSequenceContainer.h"
42 
43 /**
44  * This is the base class and interface for property groups. This class itself is abstract and derived from WPropertyBase. So if you create a
45  * group of properties, this ensures that your group is a property itself. This interface defines no way to add, remove or edit the property list
46  * itself. This allows the deriving class to prohibit modifications and to provide a custom interface, or even model-controller like
47  * implementations.
48  *
49  * Another advantage is, that the GUI implementations which support WPropertyGroupBase can display your custom properties directly.
50  */
52 {
53 public:
54  /**
55  * For shortening: a type defining a shared vector of WSubject pointers.
56  */
57  typedef std::vector< boost::shared_ptr< WPropertyBase > > PropertyContainerType;
58 
59  /**
60  * The alias for a shared container.
61  */
63 
64  /**
65  * The const iterator type of the container.
66  */
67  typedef PropertyContainerType::const_iterator PropertyConstIterator;
68 
69  /**
70  * The iterator type of the container.
71  */
72  typedef PropertyContainerType::iterator PropertyIterator;
73 
74  /**
75  * Convenience typedef for a boost::shared_ptr< WPropertyGroupBase >.
76  */
77  typedef boost::shared_ptr< WPropertyGroupBase > SPtr;
78 
79  /**
80  * Convenience typedef for a boost::shared_ptr< const WPropertyGroupBase >.
81  */
82  typedef boost::shared_ptr< const WPropertyGroupBase > ConstSPtr;
83 
84  /**
85  * The separator used to separate groups and subgroups
86  */
87  static const std::string separator;
88 
89  ///////////////////////////////////////////////////////////////////////////////////////////////////
90  // Construction
91  ///////////////////////////////////////////////////////////////////////////////////////////////////
92 
93  /**
94  * Constructor. Creates an empty list of properties.
95  *
96  * \param name the name of the property group. The GUI is using this name for naming the tabs/group boxes
97  * \param description the description of the group.
98  */
99  WPropertyGroupBase( std::string name, std::string description );
100 
101  /**
102  * Copy constructor. Creates a deep copy of this property. As boost::signals2 and condition variables are non-copyable, new instances get
103  * created. The subscriptions to a signal are LOST as well as all listeners to a condition.
104  * The conditions you can grab using getValueChangeConditon and getCondition are not the same as in the original! This is because
105  * the class corresponds to the observer/observable pattern. You won't expect a clone to fire a condition if a original flag is changed
106  * (which after cloning is completely decoupled from the clone).
107  *
108  * \note the properties inside this list are also copied deep
109  *
110  * \param from the instance to copy.
111  */
112  explicit WPropertyGroupBase( const WPropertyGroupBase& from );
113 
114  /**
115  * Destructor.
116  */
117  virtual ~WPropertyGroupBase();
118 
119  ///////////////////////////////////////////////////////////////////////////////////////////////////
120  // The WPropertyGroupBase interface
121  ///////////////////////////////////////////////////////////////////////////////////////////////////
122 
123  /**
124  * Helper function that finds a property by its name. Use this method to find out whether the property exists or not, since
125  * findProperty throws an exception.
126  *
127  * \param name name of searched property.
128  *
129  * \return Answer to the question whether the property exists.
130  */
131  virtual bool existsProperty( std::string name );
132 
133  /**
134  * Function searches the property. If it does not exists, it throws an exception.
135  *
136  * \param name the name of the property
137  *
138  * \return a WProperty object
139  */
140  virtual boost::shared_ptr< WPropertyBase > getProperty( std::string name );
141 
142  /**
143  * Returns a read ticket for read-access to the list of properties.
144  *
145  * \return the read ticket.
146  */
148 
149  /**
150  * Returns an read ticket for the properties. This, and only this, has to be used for external iteration of properties.
151  *
152  * \see WSharedObjectTicketRead
153  * \return the read ticket.
154  */
156 
157  /**
158  * Searches the property with a given name. It does not throw any exception. It simply returns NULL if it can't be found. It searches
159  * in nested groups too. The naming rules for finding a property in subgroups of this group is like specifying a path, using the \ref
160  * separator char: "somegroup" + separator + "anothergroup" + separator + "propnametosearch".
161  *
162  * \param name the name of the property to search
163  *
164  * \return the property or NULL if not found.
165  */
166  virtual boost::shared_ptr< WPropertyBase > findProperty( std::string name ) const;
167 
168  /**
169  * The visitor type used to visit properties as strings. The first parameter is the name, including the path of the property, relative to
170  * this group. The second parameter is the value as string.
171  */
172  typedef boost::function< void ( std::string, std::string )> PropertyStringVisitor;
173 
174  /**
175  * Visit all leafs in the property three that aren't empty groups. This is especially interesting when using it with lambda functionality.
176  * The visitor function gets two parameters: 1st: the name of the property, including the path beginning at this group; 2nd: the value as
177  * string.
178  *
179  * \param visitor the function to use for each property.
180  * \param pathPrefix add this prefix to the property name in the visitor. It might be interesting if manually implementing group visitors
181  * that always require a complete path, so you can add an upper-level path here.
182  */
183  virtual void visitAsString( PropertyStringVisitor visitor, std::string pathPrefix = "" ) const;
184 
185 protected:
186  /**
187  * Helping function to find a property inside a specific group. It does not recursively find properties nested inside other property groups.
188  *
189  * \param props the group to search in. This is not a shared pointer since it is not needed. It simply can't happen that it is freed during
190  * findProperty as it is contained in this or a nested properties instance.
191  * \param name the name of the property inside THIS group.
192  *
193  * \return the property if found, else NULL.
194  */
195  virtual boost::shared_ptr< WPropertyBase > findProperty( const WPropertyGroupBase* const props, std::string name ) const;
196 
197  /**
198  * The set of proerties. This uses the operators ==,<,> WProperty to determine equalness.
199  */
201 
202  /**
203  * Compares the names of two properties and returns true if they are equal.
204  *
205  * \param prop1 the first prop.
206  * \param prop2 the second prop.
207  *
208  * \return Are the names of the two properties equal?
209  */
210  bool propNamePredicate( boost::shared_ptr< WPropertyBase > prop1, boost::shared_ptr< WPropertyBase > prop2 ) const;
211 
212  /**
213  * Insert the specified property into the list. This method is protected. It is a convenience method for deriving classes to add properties
214  * without the need to update several conditions and similar.
215  *
216  * \param prop the property to add
217  */
219 
220  /**
221  * Comfortable template to create a property instance and add it to the group. This is a utility for deriving classes which need to handle
222  * certain property types and other types during compile time.
223  *
224  * At the first glance, this might not look very useful. But this
225  * is practical to change the add-behaviour for certain property types by specializing this class. For example, the template \ref
226  * WPropertyStruct uses this to modify the behaviour for the non-property type \ref WPropertyStructHelper::NOTYPE, which is used as
227  * template list default (to emulate variadic template parameters lists).
228  *
229  * \tparam PropertyType the property type to create. It is assumed that this is a shared_ptr< WPropertyXYZ >.
230  */
231  template< typename PropertyType >
233  {
234  /**
235  * The type of the initial value.
236  */
237  typedef typename PropertyType::element_type::ValueType ValueType;
238 
239  /**
240  * Actually does the work and adds a new property with the given name, description and other parameters to the specified group.
241  *
242  * \param group the group to add the new property to
243  * \param name the name of the new property
244  * \param description the description of the new property
245  * \param initial initial value
246  */
247  static void createAndAdd( WPropertyGroupBase* group, std::string name, std::string description, const ValueType& initial = ValueType() )
248  {
249  group->addArbitraryProperty(
250  PropertyType(
251  new typename PropertyType::element_type( name, description, initial )
252  )
253  );
254  }
255  };
256 
257 private:
258 };
259 
260 #endif // WPROPERTYGROUPBASE_H
261