OpenWalnut  1.4.0
WPropertyGroupBase.h
00001 //---------------------------------------------------------------------------
00002 //
00003 // Project: OpenWalnut ( http://www.openwalnut.org )
00004 //
00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
00006 // For more information see http://www.openwalnut.org/copying
00007 //
00008 // This file is part of OpenWalnut.
00009 //
00010 // OpenWalnut is free software: you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as published by
00012 // the Free Software Foundation, either version 3 of the License, or
00013 // (at your option) any later version.
00014 //
00015 // OpenWalnut is distributed in the hope that it will be useful,
00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 // GNU Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public License
00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
00022 //
00023 //---------------------------------------------------------------------------
00024 
00025 #ifndef WPROPERTYGROUPBASE_H
00026 #define WPROPERTYGROUPBASE_H
00027 
00028 #include <map>
00029 #include <string>
00030 #include <vector>
00031 
00032 #include <boost/thread/thread.hpp>
00033 #include <boost/thread/mutex.hpp>
00034 #include <boost/thread/locks.hpp>
00035 #include <boost/thread.hpp>
00036 
00037 #include "WConditionSet.h"
00038 #include "WPropertyBase.h"
00039 #include "WPropertyTypes.h"
00040 #include "WPropertyVariable.h"
00041 #include "WSharedSequenceContainer.h"
00042 
00043 /**
00044  * This is the base class and interface for property groups. This class itself is abstract and derived from WPropertyBase. So if you create a
00045  * 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
00046  * itself. This allows the deriving class to prohibit modifications and to provide a custom interface, or even model-controller like
00047  * implementations.
00048  *
00049  * Another advantage is, that the GUI implementations which support WPropertyGroupBase can display your custom properties directly.
00050  */
00051 class WPropertyGroupBase: public WPropertyBase
00052 {
00053 public:
00054     /**
00055      * For shortening: a type defining a shared vector of WSubject pointers.
00056      */
00057     typedef std::vector< boost::shared_ptr< WPropertyBase > > PropertyContainerType;
00058 
00059     /**
00060      * The alias for a shared container.
00061      */
00062     typedef WSharedSequenceContainer< PropertyContainerType > PropertySharedContainerType;
00063 
00064     /**
00065      * The const iterator type of the container.
00066      */
00067     typedef PropertyContainerType::const_iterator PropertyConstIterator;
00068 
00069     /**
00070      * The iterator type of the container.
00071      */
00072     typedef PropertyContainerType::iterator PropertyIterator;
00073 
00074     /**
00075      * Convenience typedef for a boost::shared_ptr< WPropertyGroupBase >.
00076      */
00077     typedef boost::shared_ptr< WPropertyGroupBase > SPtr;
00078 
00079     /**
00080      * Convenience typedef for a boost::shared_ptr< const WPropertyGroupBase >.
00081      */
00082     typedef boost::shared_ptr< const WPropertyGroupBase > ConstSPtr;
00083 
00084     /**
00085      * The separator used to separate groups and subgroups
00086      */
00087     static const std::string separator;
00088 
00089     ///////////////////////////////////////////////////////////////////////////////////////////////////
00090     // Construction
00091     ///////////////////////////////////////////////////////////////////////////////////////////////////
00092 
00093     /**
00094      * Constructor. Creates an empty list of properties.
00095      *
00096      * \param name the name of the property group. The GUI is using this name for naming the tabs/group boxes
00097      * \param description the description of the group.
00098      */
00099     WPropertyGroupBase( std::string name, std::string description );
00100 
00101     /**
00102      * Copy constructor. Creates a deep copy of this property. As boost::signals2 and condition variables are non-copyable, new instances get
00103      * created. The subscriptions to a signal are LOST as well as all listeners to a condition.
00104      * The conditions you can grab using getValueChangeConditon and getCondition are not the same as in the original! This is because
00105      * the class corresponds to the observer/observable pattern. You won't expect a clone to fire a condition if a original flag is changed
00106      * (which after cloning is completely decoupled from the clone).
00107      *
00108      * \note the properties inside this list are also copied deep
00109      *
00110      * \param from the instance to copy.
00111      */
00112     explicit WPropertyGroupBase( const WPropertyGroupBase& from );
00113 
00114     /**
00115      * Destructor.
00116      */
00117     virtual ~WPropertyGroupBase();
00118 
00119     ///////////////////////////////////////////////////////////////////////////////////////////////////
00120     // The WPropertyGroupBase interface
00121     ///////////////////////////////////////////////////////////////////////////////////////////////////
00122 
00123     /**
00124      * Helper function that finds a property by its name. Use this method to find out whether the property exists or not, since
00125      * findProperty throws an exception.
00126      *
00127      * \param name name of searched property.
00128      *
00129      * \return Answer to the question whether the property exists.
00130      */
00131     virtual bool existsProperty( std::string name );
00132 
00133     /**
00134      * Function searches the property. If it does not exists, it throws an exception.
00135      *
00136      * \param name the name of the property
00137      *
00138      * \return a WProperty object
00139      */
00140     virtual boost::shared_ptr< WPropertyBase > getProperty( std::string name );
00141 
00142     /**
00143      * Returns a read ticket for read-access to the list of properties.
00144      *
00145      * \return the read ticket.
00146      */
00147     virtual PropertySharedContainerType::ReadTicket getProperties() const;
00148 
00149     /**
00150      * Returns an read ticket for the properties. This, and only this, has to be used for external iteration of properties.
00151      *
00152      * \see WSharedObjectTicketRead
00153      * \return the read ticket.
00154      */
00155     virtual PropertySharedContainerType::ReadTicket getReadTicket() const;
00156 
00157     /**
00158      * 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
00159      * in nested groups too. The naming rules for finding a property in subgroups of this group is like specifying a path, using the \ref
00160      * separator char: "somegroup" + separator + "anothergroup" + separator + "propnametosearch".
00161      *
00162      * \param name the name of the property to search
00163      *
00164      * \return the property or NULL if not found.
00165      */
00166     virtual boost::shared_ptr< WPropertyBase > findProperty( std::string name ) const;
00167 
00168     /**
00169      * The visitor type used to visit properties as strings. The first parameter is the name, including the path of the property, relative to
00170      * this group. The second parameter is the value as string.
00171      */
00172     typedef boost::function< void ( std::string, std::string )> PropertyStringVisitor;
00173 
00174     /**
00175      * Visit all leafs in the property three that aren't empty groups. This is especially interesting when using it with lambda functionality.
00176      * The visitor function gets two parameters: 1st: the name of the property, including the path beginning at this group; 2nd: the value as
00177      * string.
00178      *
00179      * \param visitor the function to use for each property.
00180      * \param pathPrefix add this prefix to the property name in the visitor. It might be interesting if manually implementing group visitors
00181      * that always require a complete path, so you can add an upper-level path here.
00182      */
00183     virtual void visitAsString( PropertyStringVisitor visitor, std::string pathPrefix = "" ) const;
00184 
00185 protected:
00186    /**
00187     * Helping function to find a property inside a specific group. It does not recursively find properties nested inside other property groups.
00188     *
00189     * \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
00190     * findProperty as it is contained in this or a nested properties instance.
00191     * \param name the name of the property inside THIS group.
00192     *
00193     * \return the property if found, else NULL.
00194     */
00195     virtual boost::shared_ptr< WPropertyBase > findProperty( const WPropertyGroupBase* const props, std::string name ) const;
00196 
00197     /**
00198      * The set of proerties. This uses the operators ==,<,> WProperty to determine equalness.
00199      */
00200     PropertySharedContainerType m_properties;
00201 
00202     /**
00203      * Compares the names of two properties and returns true if they are equal.
00204      *
00205      * \param prop1 the first prop.
00206      * \param prop2 the second prop.
00207      *
00208      * \return Are the names of the two properties equal?
00209      */
00210     bool propNamePredicate( boost::shared_ptr< WPropertyBase > prop1, boost::shared_ptr< WPropertyBase > prop2 ) const;
00211 
00212     /**
00213      * Insert the specified property into the list. This method is protected. It is a convenience method for deriving classes to add properties
00214      * without the need to update several conditions and similar.
00215      *
00216      * \param prop the property to add
00217      */
00218     void addArbitraryProperty( WPropertyBase::SPtr prop );
00219 
00220     /**
00221      * Comfortable template to create a property instance and add it to the group. This is a utility for deriving classes which need to handle
00222      * certain property types and other types during compile time.
00223      *
00224      * At the first glance, this might not look very useful. But this
00225      * is practical to change the add-behaviour for certain property types by specializing this class. For example, the template \ref
00226      * WPropertyStruct uses this to modify the behaviour for the non-property type \ref WPropertyStructHelper::NOTYPE, which is used as
00227      * template list default (to emulate variadic template parameters lists).
00228      *
00229      * \tparam PropertyType the property type to create. It is assumed that this is a shared_ptr< WPropertyXYZ >.
00230      */
00231     template< typename PropertyType >
00232     struct PropertyCreatorAndGroupAdder
00233     {
00234         /**
00235          * The type of the initial value.
00236          */
00237         typedef typename PropertyType::element_type::ValueType ValueType;
00238 
00239         /**
00240          * Actually does the work and adds a new property with the given name, description and other parameters to the specified group.
00241          *
00242          * \param group the group to add the new property to
00243          * \param name the name of the new property
00244          * \param description the description of the new property
00245          * \param initial initial value
00246          */
00247         static void createAndAdd( WPropertyGroupBase* group, std::string name, std::string description, const ValueType& initial = ValueType() )
00248         {
00249             group->addArbitraryProperty(
00250                 PropertyType(
00251                     new typename PropertyType::element_type( name, description, initial )
00252                 )
00253             );
00254        }
00255     };
00256 
00257 private:
00258 };
00259 
00260 #endif  // WPROPERTYGROUPBASE_H
00261