OpenWalnut  1.3.1
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 <iostream>
26 #include <map>
27 #include <string>
28 #include <vector>
29 #include <algorithm>
30 
31 #include <boost/tokenizer.hpp>
32 
33 #include "WStringUtils.h"
34 #include "WLogger.h"
35 #include "exceptions/WPropertyUnknown.h"
36 #include "exceptions/WPropertyNotUnique.h"
37 
38 #include "WPropertyHelper.h"
39 
40 #include "WPropertyGroupBase.h"
41 
42 WPropertyGroupBase::WPropertyGroupBase( std::string name, std::string description ):
43  WPropertyBase( name, description ),
44  m_properties()
45 {
46  // this groups update condition also fires upon group modification -> add WSharedObject condition
48 }
49 
51 {
52 }
53 
55  WPropertyBase( from ),
56  m_properties()
57 {
58  // copy the properties inside
59 
60  // lock, unlocked if l looses focus
62 
63  // we need to make a deep copy here.
64  for( PropertyConstIterator iter = l->get().begin(); iter != l->get().end(); ++iter )
65  {
66  // clone them to keep dynamic type
67  addArbitraryProperty( ( *iter )->clone() );
68  }
69 
70  // unlock explicitly
71  l.reset();
72 
73  // this groups update condition also fires upon group modification -> add WSharedObject condition
75 }
76 
77 bool WPropertyGroupBase::propNamePredicate( boost::shared_ptr< WPropertyBase > prop1, boost::shared_ptr< WPropertyBase > prop2 ) const
78 {
79  return ( prop1->getName() == prop2->getName() );
80 }
81 
82 boost::shared_ptr< WPropertyBase > WPropertyGroupBase::findProperty( const WPropertyGroupBase* const props, std::string name ) const
83 {
84  boost::shared_ptr< WPropertyBase > result = boost::shared_ptr< WPropertyBase >();
85 
86  // lock, unlocked if l looses focus
88 
89  // iterate over the items
90  for( PropertyContainerType::const_iterator it = l->get().begin(); it != l->get().end(); ++it )
91  {
92  if( ( *it )->getName() == name )
93  {
94  result = ( *it );
95  break;
96  }
97  }
98 
99  // done. Unlocked after l looses focus.
100  return result;
101 }
102 
103 boost::shared_ptr< WPropertyBase > WPropertyGroupBase::findProperty( std::string name ) const
104 {
105  boost::shared_ptr< WPropertyBase > result = boost::shared_ptr< WPropertyBase >();
106 
107  // tokenize the name -> contains any paths?
108  typedef boost::tokenizer<boost::char_separator< char > > tokenizer;
109  boost::char_separator< char > sep( "/" ); // separate by /
110  tokenizer tok( name, sep );
111 
112  // iterate along the path
113  const WPropertyGroupBase* curProps = this; // the group currently in while traversing the path
114  for( tokenizer::iterator it = tok.begin(); it != tok.end(); ++it )
115  {
116  // was the last token not a group?
117  if( result && !WPVBaseTypes::isPropertyGroup( result->getType() ) )
118  {
119  // no it wasn't. This means that one token inside the path is no group, but it needs to be one
120  return boost::shared_ptr< WPropertyBase >();
121  }
122 
123  // get the properties along the path
124  result = findProperty( curProps, string_utils::toString( *it ) );
125  if( !result )
126  {
127  // not found? Return NULL.
128  return boost::shared_ptr< WPropertyBase >();
129  }
130  else if( result && WPVBaseTypes::isPropertyGroup( result->getType() ) )
131  {
132  // it is a group. Go down
133  curProps = result->toPropGroupBase().get();
134  }
135  }
136 
137  return result;
138 }
139 
140 bool WPropertyGroupBase::existsProperty( std::string name )
141 {
142  return ( findProperty( name ) != boost::shared_ptr< WPropertyBase >() );
143 }
144 
145 boost::shared_ptr< WPropertyBase > WPropertyGroupBase::getProperty( std::string name )
146 {
147  boost::shared_ptr< WPropertyBase > p = findProperty( name );
148  if( p == boost::shared_ptr< WPropertyBase >() )
149  {
150  throw WPropertyUnknown( std::string( "Property \"" + name + "\" can't be found." ) );
151  }
152 
153  return p;
154 }
155 
157 {
158  // lock, unlocked if l looses focus
160 
161  // NOTE: WPropertyBase already prohibits invalid property names -> no check needed here
162 
163  // check uniqueness:
164  if( std::count_if( l->get().begin(), l->get().end(),
165  boost::bind( boost::mem_fn( &WPropertyGroupBase::propNamePredicate ), this, prop, _1 ) ) )
166  {
167  // unlock explicitly
168  l.reset();
169 
170  // oh oh, this property name is not unique in this group
171  if( !getName().empty() )
172  {
173  throw WPropertyNotUnique( std::string( "Property \"" + prop->getName() + "\" is not unique in this group (\"" + getName() + "\")." ) );
174  }
175  else
176  {
177  throw WPropertyNotUnique( std::string( "Property \"" + prop->getName() + "\" is not unique in this group (unnamed root)." ) );
178  }
179  }
180 
181  // PV_PURPOSE_INFORMATION groups do not allow PV_PURPOSE_PARAMETER properties but vice versa.
182  if( getPurpose() == PV_PURPOSE_INFORMATION )
183  {
184  prop->setPurpose( PV_PURPOSE_INFORMATION );
185  }
186  // INFORMATION properties are allowed inside PARAMETER groups -> do not set the properties purpose.
187 
188  l->get().push_back( prop );
189 
190  // add the child's update condition to the list
191  m_updateCondition->add( prop->getUpdateCondition() );
192 }
193 
195 {
196  return m_properties.getReadTicket();
197 }
198 
200 {
201  return m_properties.getReadTicket();
202 }
203