OpenWalnut 1.3.1
|
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 #include <iostream> 00026 #include <map> 00027 #include <string> 00028 #include <vector> 00029 #include <algorithm> 00030 00031 #include <boost/tokenizer.hpp> 00032 00033 #include "WStringUtils.h" 00034 #include "WLogger.h" 00035 #include "exceptions/WPropertyUnknown.h" 00036 #include "exceptions/WPropertyNotUnique.h" 00037 00038 #include "WPropertyHelper.h" 00039 00040 #include "WPropertyGroupBase.h" 00041 00042 WPropertyGroupBase::WPropertyGroupBase( std::string name, std::string description ): 00043 WPropertyBase( name, description ), 00044 m_properties() 00045 { 00046 // this groups update condition also fires upon group modification -> add WSharedObject condition 00047 m_updateCondition->add( m_properties.getChangeCondition() ); 00048 } 00049 00050 WPropertyGroupBase::~WPropertyGroupBase() 00051 { 00052 } 00053 00054 WPropertyGroupBase::WPropertyGroupBase( const WPropertyGroupBase& from ): 00055 WPropertyBase( from ), 00056 m_properties() 00057 { 00058 // copy the properties inside 00059 00060 // lock, unlocked if l looses focus 00061 PropertySharedContainerType::ReadTicket l = from.m_properties.getReadTicket(); 00062 00063 // we need to make a deep copy here. 00064 for( PropertyConstIterator iter = l->get().begin(); iter != l->get().end(); ++iter ) 00065 { 00066 // clone them to keep dynamic type 00067 addArbitraryProperty( ( *iter )->clone() ); 00068 } 00069 00070 // unlock explicitly 00071 l.reset(); 00072 00073 // this groups update condition also fires upon group modification -> add WSharedObject condition 00074 m_updateCondition->add( m_properties.getChangeCondition() ); 00075 } 00076 00077 bool WPropertyGroupBase::propNamePredicate( boost::shared_ptr< WPropertyBase > prop1, boost::shared_ptr< WPropertyBase > prop2 ) const 00078 { 00079 return ( prop1->getName() == prop2->getName() ); 00080 } 00081 00082 boost::shared_ptr< WPropertyBase > WPropertyGroupBase::findProperty( const WPropertyGroupBase* const props, std::string name ) const 00083 { 00084 boost::shared_ptr< WPropertyBase > result = boost::shared_ptr< WPropertyBase >(); 00085 00086 // lock, unlocked if l looses focus 00087 PropertySharedContainerType::ReadTicket l = props->m_properties.getReadTicket(); 00088 00089 // iterate over the items 00090 for( PropertyContainerType::const_iterator it = l->get().begin(); it != l->get().end(); ++it ) 00091 { 00092 if( ( *it )->getName() == name ) 00093 { 00094 result = ( *it ); 00095 break; 00096 } 00097 } 00098 00099 // done. Unlocked after l looses focus. 00100 return result; 00101 } 00102 00103 boost::shared_ptr< WPropertyBase > WPropertyGroupBase::findProperty( std::string name ) const 00104 { 00105 boost::shared_ptr< WPropertyBase > result = boost::shared_ptr< WPropertyBase >(); 00106 00107 // tokenize the name -> contains any paths? 00108 typedef boost::tokenizer<boost::char_separator< char > > tokenizer; 00109 boost::char_separator< char > sep( "/" ); // separate by / 00110 tokenizer tok( name, sep ); 00111 00112 // iterate along the path 00113 const WPropertyGroupBase* curProps = this; // the group currently in while traversing the path 00114 for( tokenizer::iterator it = tok.begin(); it != tok.end(); ++it ) 00115 { 00116 // was the last token not a group? 00117 if( result && !WPVBaseTypes::isPropertyGroup( result->getType() ) ) 00118 { 00119 // no it wasn't. This means that one token inside the path is no group, but it needs to be one 00120 return boost::shared_ptr< WPropertyBase >(); 00121 } 00122 00123 // get the properties along the path 00124 result = findProperty( curProps, string_utils::toString( *it ) ); 00125 if( !result ) 00126 { 00127 // not found? Return NULL. 00128 return boost::shared_ptr< WPropertyBase >(); 00129 } 00130 else if( result && WPVBaseTypes::isPropertyGroup( result->getType() ) ) 00131 { 00132 // it is a group. Go down 00133 curProps = result->toPropGroupBase().get(); 00134 } 00135 } 00136 00137 return result; 00138 } 00139 00140 bool WPropertyGroupBase::existsProperty( std::string name ) 00141 { 00142 return ( findProperty( name ) != boost::shared_ptr< WPropertyBase >() ); 00143 } 00144 00145 boost::shared_ptr< WPropertyBase > WPropertyGroupBase::getProperty( std::string name ) 00146 { 00147 boost::shared_ptr< WPropertyBase > p = findProperty( name ); 00148 if( p == boost::shared_ptr< WPropertyBase >() ) 00149 { 00150 throw WPropertyUnknown( std::string( "Property \"" + name + "\" can't be found." ) ); 00151 } 00152 00153 return p; 00154 } 00155 00156 void WPropertyGroupBase::addArbitraryProperty( WPropertyBase::SPtr prop ) 00157 { 00158 // lock, unlocked if l looses focus 00159 PropertySharedContainerType::WriteTicket l = m_properties.getWriteTicket(); 00160 00161 // NOTE: WPropertyBase already prohibits invalid property names -> no check needed here 00162 00163 // check uniqueness: 00164 if( std::count_if( l->get().begin(), l->get().end(), 00165 boost::bind( boost::mem_fn( &WPropertyGroupBase::propNamePredicate ), this, prop, _1 ) ) ) 00166 { 00167 // unlock explicitly 00168 l.reset(); 00169 00170 // oh oh, this property name is not unique in this group 00171 if( !getName().empty() ) 00172 { 00173 throw WPropertyNotUnique( std::string( "Property \"" + prop->getName() + "\" is not unique in this group (\"" + getName() + "\")." ) ); 00174 } 00175 else 00176 { 00177 throw WPropertyNotUnique( std::string( "Property \"" + prop->getName() + "\" is not unique in this group (unnamed root)." ) ); 00178 } 00179 } 00180 00181 // PV_PURPOSE_INFORMATION groups do not allow PV_PURPOSE_PARAMETER properties but vice versa. 00182 if( getPurpose() == PV_PURPOSE_INFORMATION ) 00183 { 00184 prop->setPurpose( PV_PURPOSE_INFORMATION ); 00185 } 00186 // INFORMATION properties are allowed inside PARAMETER groups -> do not set the properties purpose. 00187 00188 l->get().push_back( prop ); 00189 00190 // add the child's update condition to the list 00191 m_updateCondition->add( prop->getUpdateCondition() ); 00192 } 00193 00194 WPropertyGroupBase::PropertySharedContainerType::ReadTicket WPropertyGroupBase::getProperties() const 00195 { 00196 return m_properties.getReadTicket(); 00197 } 00198 00199 WPropertyGroupBase::PropertySharedContainerType::ReadTicket WPropertyGroupBase::getReadTicket() const 00200 { 00201 return m_properties.getReadTicket(); 00202 } 00203