OpenWalnut  1.5.0dev
WPropertyGroupBase.cpp
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 #include <algorithm>
26 #include <iostream>
27 #include <map>
28 #include <memory>
29 #include <string>
30 #include <vector>
31 
32 #include <boost/algorithm/string/predicate.hpp>
33 #include <boost/tokenizer.hpp>
34 
35 #include "WLogger.h"
36 #include "WPropertyGroupBase.h"
37 #include "WPropertyHelper.h"
38 #include "WStringUtils.h"
39 #include "exceptions/WPropertyNotUnique.h"
40 #include "exceptions/WPropertyUnknown.h"
41 
42 const std::string WPropertyGroupBase::separator = "/";
43 
44 WPropertyGroupBase::WPropertyGroupBase( std::string name, std::string description ):
45  WPropertyBase( name, description ),
46  m_properties(),
47  m_autoHideEmpty( true )
48 {
49  // this groups update condition also fires upon group modification -> add WSharedObject condition
51 }
52 
54 {
55 }
56 
58  WPropertyBase( from ),
59  m_properties()
60 {
61  // copy the properties inside
62 
63  // lock, unlocked if l looses focus
65 
66  // we need to make a deep copy here.
67  for( PropertyConstIterator iter = l->get().begin(); iter != l->get().end(); ++iter )
68  {
69  // clone them to keep dynamic type
70  addArbitraryProperty( ( *iter )->clone() );
71  }
72 
73  // unlock explicitly
74  l.reset();
75 
76  // this groups update condition also fires upon group modification -> add WSharedObject condition
78 }
79 
80 bool WPropertyGroupBase::propNamePredicate( std::shared_ptr< WPropertyBase > prop1, std::shared_ptr< WPropertyBase > prop2 ) const
81 {
82  return ( prop1->getName() == prop2->getName() );
83 }
84 
85 std::shared_ptr< WPropertyBase > WPropertyGroupBase::findProperty( const WPropertyGroupBase* const props, std::string name ) const
86 {
87  std::shared_ptr< WPropertyBase > result = std::shared_ptr< WPropertyBase >();
88 
89  // lock, unlocked if l looses focus
91 
92  // iterate over the items
93  for( PropertyContainerType::const_iterator it = l->get().begin(); it != l->get().end(); ++it )
94  {
95  if( ( *it )->getName() == name )
96  {
97  result = ( *it );
98  break;
99  }
100  }
101 
102  // done. Unlocked after l looses focus.
103  return result;
104 }
105 
106 std::shared_ptr< WPropertyBase > WPropertyGroupBase::findProperty( std::string name ) const
107 {
108  std::shared_ptr< WPropertyBase > result = std::shared_ptr< WPropertyBase >();
109 
110  // tokenize the name -> contains any paths?
111  typedef boost::tokenizer<boost::char_separator< char > > tokenizer;
112  boost::char_separator< char > sep( WPropertyGroupBase::separator.c_str() ); // separate by /
113  tokenizer tok( name, sep );
114 
115  // iterate along the path
116  const WPropertyGroupBase* curProps = this; // the group currently in while traversing the path
117  for( tokenizer::iterator it = tok.begin(); it != tok.end(); ++it )
118  {
119  // was the last token not a group?
120  if( result && !WPVBaseTypes::isPropertyGroup( result->getType() ) )
121  {
122  // no it wasn't. This means that one token inside the path is no group, but it needs to be one
123  return std::shared_ptr< WPropertyBase >();
124  }
125 
126  // get the properties along the path
127  result = findProperty( curProps, string_utils::toString( *it ) );
128  if( !result )
129  {
130  // not found? Return NULL.
131  return std::shared_ptr< WPropertyBase >();
132  }
133  else if( result && WPVBaseTypes::isPropertyGroup( result->getType() ) )
134  {
135  // it is a group. Go down
136  curProps = result->toPropGroupBase().get();
137  }
138  }
139 
140  return result;
141 }
142 
144 {
145  // read access
147 
148  for( PropertyConstIterator it = r->get().begin(); it != r->get().end(); ++it )
149  {
150  // path: handle some special cases:
151  std::string propName = pathPrefix + WPropertyGroupBase::separator + ( *it )->getName();
152 
153  // 1: user added a separator
154  if( boost::algorithm::ends_with( pathPrefix, WPropertyGroupBase::separator ) )
155  {
156  propName = pathPrefix + ( *it )->getName();
157  }
158  // 2: avoid separator if prefix is empty
159  if( pathPrefix.empty() )
160  {
161  propName = ( *it )->getName();
162  }
163 
164  // is it a group type?
165  WPropertyGroupBase::SPtr g = ( *it )->toPropGroupBase();
166  if( g )
167  {
168  // recurse down
169  g->visitAsString( visitor, propName );
170  }
171  else
172  {
173  // it is a leaf, call visitor
174  std::string value = ( *it )->getAsString();
175  visitor( propName, value );
176  }
177  }
178 }
179 
180 bool WPropertyGroupBase::existsProperty( std::string name )
181 {
182  return ( findProperty( name ) != std::shared_ptr< WPropertyBase >() );
183 }
184 
185 std::shared_ptr< WPropertyBase > WPropertyGroupBase::getProperty( std::string name )
186 {
187  std::shared_ptr< WPropertyBase > p = findProperty( name );
188  if( p == std::shared_ptr< WPropertyBase >() )
189  {
190  throw WPropertyUnknown( std::string( "Property \"" + name + "\" can't be found." ) );
191  }
192 
193  return p;
194 }
195 
197 {
198  // lock, unlocked if l looses focus
200 
201  // NOTE: WPropertyBase already prohibits invalid property names -> no check needed here
202 
203  // check uniqueness:
204  if( std::count_if( l->get().begin(), l->get().end(),
205  boost::bind( boost::mem_fn( &WPropertyGroupBase::propNamePredicate ), this, prop, boost::placeholders::_1 ) ) )
206  {
207  // unlock explicitly
208  l.reset();
209 
210  // oh oh, this property name is not unique in this group
211  if( !getName().empty() )
212  {
213  throw WPropertyNotUnique( std::string( "Property \"" + prop->getName() + "\" is not unique in this group (\"" + getName() + "\")." ) );
214  }
215  else
216  {
217  throw WPropertyNotUnique( std::string( "Property \"" + prop->getName() + "\" is not unique in this group (unnamed root)." ) );
218  }
219  }
220 
221  // PV_PURPOSE_INFORMATION groups do not allow PV_PURPOSE_PARAMETER properties but vice versa.
222  if( getPurpose() == PV_PURPOSE_INFORMATION )
223  {
224  prop->setPurpose( PV_PURPOSE_INFORMATION );
225  }
226  // INFORMATION properties are allowed inside PARAMETER groups -> do not set the properties purpose.
227 
228  l->get().push_back( prop );
229 
230  // add the child's update condition to the list
231  m_updateCondition->add( prop->getUpdateCondition() );
232 }
233 
235 {
236  return m_properties.getReadTicket();
237 }
238 
240 {
241  return m_properties.getReadTicket();
242 }
243 
245 {
246  return m_autoHideEmpty;
247 }
248 
250 {
251  m_autoHideEmpty = autoHide;
252 }
253 
Abstract base class for all properties.
Definition: WPropertyBase.h:48
std::shared_ptr< WPropertyGroupBase > toPropGroupBase()
Convert the property to a WPropertyGroupBase.
std::string getName() const
Gets the name of the class.
std::shared_ptr< WConditionSet > m_updateCondition
Condition notified whenever something changes.
virtual PROPERTY_PURPOSE getPurpose() const
Gets the purpose of a property.
std::shared_ptr< WPropertyBase > SPtr
Convenience typedef for a std::shared_ptr< WPropertyBase >
Definition: WPropertyBase.h:53
This is the base class and interface for property groups.
PropertyContainerType::const_iterator PropertyConstIterator
The const iterator type of the container.
bool propNamePredicate(std::shared_ptr< WPropertyBase > prop1, std::shared_ptr< WPropertyBase > prop2) const
Compares the names of two properties and returns true if they are equal.
bool autoHideEmpty() const
Checks whether the property group should be hidden if it is empty.
void addArbitraryProperty(WPropertyBase::SPtr prop)
Insert the specified property into the list.
virtual ~WPropertyGroupBase()
Destructor.
virtual PropertySharedContainerType::ReadTicket getProperties() const
Returns a read ticket for read-access to the list of properties.
void setAutoHideEmpty(bool autoHide=true)
Should the property group be hidden automatically if it is empty? By default, this is true.
virtual PropertySharedContainerType::ReadTicket getReadTicket() const
Returns an read ticket for the properties.
bool m_autoHideEmpty
True if the prop should be hidden if if empty.
virtual std::shared_ptr< WPropertyBase > getProperty(std::string name)
Function searches the property.
static const std::string separator
The separator used to separate groups and subgroups.
std::shared_ptr< WPropertyGroupBase > SPtr
Convenience typedef for a std::shared_ptr< WPropertyGroupBase >.
virtual std::shared_ptr< WPropertyBase > findProperty(std::string name) const
Searches the property with a given name.
virtual bool existsProperty(std::string name)
Helper function that finds a property by its name.
WPropertyGroupBase(std::string name, std::string description)
Constructor.
virtual void visitAsString(PropertyStringVisitor visitor, std::string pathPrefix="") const
Visit all leafs in the property three that aren't empty groups.
PropertySharedContainerType m_properties
The set of proerties.
boost::function< void(std::string, std::string)> PropertyStringVisitor
The visitor type used to visit properties as strings.
Indicates that a given property is not unique in a group of properties.
Indicates invalid element access of a container.
std::shared_ptr< WSharedObjectTicketRead< T > > ReadTicket
Type for read tickets.
Definition: WSharedObject.h:65
ReadTicket getReadTicket() const
Returns a ticket to get read access to the contained data.
std::shared_ptr< WSharedObjectTicketWrite< T > > WriteTicket
Type for write tickets.
Definition: WSharedObject.h:70
WriteTicket getWriteTicket(bool suppressNotify=false) const
Returns a ticket to get write access to the contained data.
std::shared_ptr< WCondition > getChangeCondition() const
This condition fires whenever the encapsulated object changed.
bool isPropertyGroup(PROPERTY_TYPE type)
Checks which property types are derived from WPropertyGroupBase.
std::string toString(const T &value)
Convert a given value to a string.
Definition: WStringUtils.h:120