OpenWalnut 1.3.1
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 
00045 /**
00046  * This is the base class and interface for property groups. This class itself is abstract and derived from WPropertyBase. So if you create a
00047  * 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
00048  * itself. This allows the deriving class to prohibit modifications and to provide a custom interface, or even model-controller like
00049  * implementations.
00050  *
00051  * Another advantage is, that the GUI implementations which support WPropertyGroupBase can display your custom properties directly.
00052  */
00053 class WPropertyGroupBase: public WPropertyBase
00054 {
00055 public:
00056     /**
00057      * For shortening: a type defining a shared vector of WSubject pointers.
00058      */
00059     typedef std::vector< boost::shared_ptr< WPropertyBase > > PropertyContainerType;
00060 
00061     /**
00062      * The alias for a shared container.
00063      */
00064     typedef WSharedSequenceContainer< PropertyContainerType > PropertySharedContainerType;
00065 
00066     /**
00067      * The const iterator type of the container.
00068      */
00069     typedef PropertyContainerType::const_iterator PropertyConstIterator;
00070 
00071     /**
00072      * The iterator type of the container.
00073      */
00074     typedef PropertyContainerType::iterator PropertyIterator;
00075 
00076     /**
00077      * Convenience typedef for a boost::shared_ptr< WPropertyGroupBase >.
00078      */
00079     typedef boost::shared_ptr< WPropertyGroupBase > SPtr;
00080 
00081     /**
00082      * Convenience typedef for a boost::shared_ptr< const WPropertyGroupBase >.
00083      */
00084     typedef boost::shared_ptr< const WPropertyGroupBase > ConstSPtr;
00085 
00086     ///////////////////////////////////////////////////////////////////////////////////////////////////
00087     // Construction
00088     ///////////////////////////////////////////////////////////////////////////////////////////////////
00089 
00090     /**
00091      * Constructor. Creates an empty list of properties.
00092      *
00093      * \param name the name of the property group. The GUI is using this name for naming the tabs/group boxes
00094      * \param description the description of the group.
00095      */
00096     WPropertyGroupBase( std::string name, std::string description );
00097 
00098     /**
00099      * Copy constructor. Creates a deep copy of this property. As boost::signals2 and condition variables are non-copyable, new instances get
00100      * created. The subscriptions to a signal are LOST as well as all listeners to a condition.
00101      * The conditions you can grab using getValueChangeConditon and getCondition are not the same as in the original! This is because
00102      * the class corresponds to the observer/observable pattern. You won't expect a clone to fire a condition if a original flag is changed
00103      * (which after cloning is completely decoupled from the clone).
00104      *
00105      * \note the properties inside this list are also copied deep
00106      *
00107      * \param from the instance to copy.
00108      */
00109     explicit WPropertyGroupBase( const WPropertyGroupBase& from );
00110 
00111     /**
00112      * Destructor.
00113      */
00114     virtual ~WPropertyGroupBase();
00115 
00116     ///////////////////////////////////////////////////////////////////////////////////////////////////
00117     // The WPropertyGroupBase interface
00118     ///////////////////////////////////////////////////////////////////////////////////////////////////
00119 
00120     /**
00121      * Helper function that finds a property by its name. Use this method to find out whether the property exists or not, since
00122      * findProperty throws an exception.
00123      *
00124      * \param name name of searched property.
00125      *
00126      * \return Answer to the question whether the property exists.
00127      */
00128     virtual bool existsProperty( std::string name );
00129 
00130     /**
00131      * Function searches the property. If it does not exists, it throws an exception.
00132      *
00133      * \param name the name of the property
00134      *
00135      * \return a WProperty object
00136      */
00137     virtual boost::shared_ptr< WPropertyBase > getProperty( std::string name );
00138 
00139     /**
00140      * Returns a read ticket for read-access to the list of properties.
00141      *
00142      * \return the read ticket.
00143      */
00144     virtual PropertySharedContainerType::ReadTicket getProperties() const;
00145 
00146     /**
00147      * Returns an read ticket for the properties. This, and only this, has to be used for external iteration of properties.
00148      *
00149      * \see WSharedObjectTicketRead
00150      * \return the read ticket.
00151      */
00152     virtual PropertySharedContainerType::ReadTicket getReadTicket() const;
00153 
00154     /**
00155      * Searches the property with a given name. It does not throw any exception. It simply returns NULL if it can't be found.
00156      *
00157      * \param name the name of the property to search
00158      *
00159      * \return the property or NULL if not found.
00160      */
00161     virtual boost::shared_ptr< WPropertyBase > findProperty( std::string name ) const;
00162 
00163 protected:
00164    /**
00165     * Helping function to find a property inside a specific group. It does not recursively find properties nested inside other property groups.
00166     *
00167     * \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
00168     * findProperty as it is contained in this or a nested properties instance.
00169     * \param name the name of the property inside THIS group.
00170     *
00171     * \return the property if found, else NULL.
00172     */
00173     virtual boost::shared_ptr< WPropertyBase > findProperty( const WPropertyGroupBase* const props, std::string name ) const;
00174 
00175     /**
00176      * The set of proerties. This uses the operators ==,<,> WProperty to determine equalness.
00177      */
00178     PropertySharedContainerType m_properties;
00179 
00180     /**
00181      * Compares the names of two properties and returns true if they are equal.
00182      *
00183      * \param prop1 the first prop.
00184      * \param prop2 the second prop.
00185      *
00186      * \return Are the names of the two properties equal?
00187      */
00188     bool propNamePredicate( boost::shared_ptr< WPropertyBase > prop1, boost::shared_ptr< WPropertyBase > prop2 ) const;
00189 
00190     /**
00191      * Insert the specified property into the list. This method is protected. It is a convenience method for deriving classes to add properties
00192      * without the need to update several conditions and similar.
00193      *
00194      * \param prop the property to add
00195      */
00196     void addArbitraryProperty( WPropertyBase::SPtr prop );
00197 
00198     /**
00199      * Comfortable template to create a property instance and add it to the group. This is a utility for deriving classes which need to handle
00200      * certain property types and other types during compile time.
00201      *
00202      * At the first glance, this might not look very useful. But this
00203      * is practical to change the add-behaviour for certain property types by specializing this class. For example, the template \ref
00204      * WPropertyStruct uses this to modify the behaviour for the non-property type \ref WPropertyStructHelper::NOTYPE, which is used as
00205      * template list default (to emulate variadic template parameters lists).
00206      *
00207      * \tparam PropertyType the property type to create. It is assumed that this is a shared_ptr< WPropertyXYZ >.
00208      */
00209     template< typename PropertyType >
00210     struct PropertyCreatorAndGroupAdder
00211     {
00212         /**
00213          * The type of the initial value.
00214          */
00215         typedef typename PropertyType::element_type::ValueType ValueType;
00216 
00217         /**
00218          * Actually does the work and adds a new property with the given name, description and other parameters to the specified group.
00219          *
00220          * \param group the group to add the new property to
00221          * \param name the name of the new property
00222          * \param description the description of the new property
00223          * \param initial initial value
00224          */
00225         static void createAndAdd( WPropertyGroupBase* group, std::string name, std::string description, const ValueType& initial = ValueType() )
00226         {
00227             group->addArbitraryProperty(
00228                 PropertyType(
00229                     new typename PropertyType::element_type( name, description, initial )
00230                 )
00231             );
00232        }
00233     };
00234 
00235 private:
00236 };
00237 
00238 #endif  // WPROPERTYGROUPBASE_H
00239