00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef AI_COMPOSITE_PROPERTY_HANDLER_HPP_INCLUDED
00023 #define AI_COMPOSITE_PROPERTY_HANDLER_HPP_INCLUDED
00024
00025 #include <boost/function.hpp>
00026
00027 #include "config.hpp"
00028 #include "foreach.hpp"
00029 #include "ai/composite/component.hpp"
00030
00031 namespace ai{
00032
00033 template<typename T>
00034 class path_element_matches{
00035 public:
00036 path_element_matches(const path_element &element)
00037 : count_(0), element_(element)
00038 {
00039 }
00040 virtual ~path_element_matches(){}
00041
00042 bool operator()(const T& t)
00043 {
00044 if ( (!element_.id.empty()) && (element_.id == t->get_id()) ) {
00045 return true;
00046 }
00047 if (count_ == element_.position) {
00048 return true;
00049 }
00050 count_++;
00051 return false;
00052 }
00053
00054 private:
00055 int count_;
00056 path_element element_;
00057 };
00058
00059
00060 class component;
00061
00062 class base_property_handler {
00063 public:
00064
00065 virtual ~base_property_handler() {}
00066
00067 virtual component* handle_get(const path_element &child) = 0;
00068 virtual bool handle_change(const path_element &child, const config &cfg) = 0;
00069 virtual bool handle_add(const path_element &child, const config &cfg) = 0;
00070 virtual bool handle_delete(const path_element &child) = 0;
00071 virtual std::vector< component* > handle_get_children() = 0;
00072 };
00073
00074 typedef boost::shared_ptr< base_property_handler > property_handler_ptr;
00075
00076 template<typename T>
00077 class vector_property_handler : public base_property_handler {
00078 public:
00079 typedef boost::shared_ptr<T> t_ptr;
00080 typedef std::vector< boost::shared_ptr<T> > t_ptr_vector;
00081
00082 vector_property_handler(const std::string &property, t_ptr_vector &values, boost::function2<void, t_ptr_vector&, const config&> &construction_factory)
00083 : factory_(construction_factory), property_(property), values_(values){}
00084
00085
00086 component* handle_get(const path_element &child)
00087 {
00088 typename t_ptr_vector::iterator i = std::find_if(values_.begin(),values_.end(),path_element_matches<t_ptr>(child));
00089 if (i!=values_.end()){
00090 return &*(*i);
00091 }
00092 return NULL;
00093 }
00094 bool handle_change(const path_element &child, const config &cfg)
00095 {
00096 if (!handle_delete(child)) {
00097 return false;
00098 }
00099
00100 return handle_add(child,cfg);
00101 }
00102 bool handle_add(const path_element &child, const config &cfg)
00103 {
00104
00105 if (!cfg["id"].empty()) {
00106 path_element with_same_id;
00107 with_same_id.id = cfg["id"].str();
00108 with_same_id.property = property_;
00109 with_same_id.position=-1;
00110 handle_delete(with_same_id);
00111 }
00112
00113 typename t_ptr_vector::iterator i = std::find_if(values_.begin(),values_.end(),path_element_matches<t_ptr>(child));
00114 return do_add(i-values_.begin(),cfg);
00115 }
00116
00117 bool handle_delete(const path_element &child)
00118 {
00119
00120 if (child.id == "*") {
00121 values_.clear();
00122 return true;
00123 }
00124
00125 typename t_ptr_vector::iterator i = std::find_if(values_.begin(),values_.end(),path_element_matches<t_ptr>(child));
00126 if (i!=values_.end()){
00127 values_.erase(i);
00128 return true;
00129 }
00130 return false;
00131 }
00132
00133
00134 std::vector<component*> handle_get_children()
00135 {
00136 std::vector<component*> children;
00137 foreach (t_ptr v, values_) {
00138 children.push_back(&*v);
00139 }
00140 return children;
00141 }
00142
00143 private:
00144 bool do_add(int pos, const config &cfg)
00145 {
00146 if (pos<0) {
00147 pos = values_.size();
00148 }
00149 t_ptr_vector values;
00150 factory_(values,cfg);
00151 int j=0;
00152 foreach (t_ptr b, values ){
00153 values_.insert(values_.begin()+pos+j,b);
00154 j++;
00155 }
00156 return (j>0);
00157 }
00158
00159 boost::function2<void, t_ptr_vector&, const config&> factory_;
00160 const std::string property_;
00161 t_ptr_vector &values_;
00162
00163 };
00164
00165
00166
00167 template<typename T>
00168 class aspect_property_handler : public base_property_handler {
00169 public:
00170 typedef boost::shared_ptr<T> t_ptr;
00171 typedef std::map< std::string, t_ptr > aspect_map;
00172
00173 aspect_property_handler(const std::string &property, aspect_map &aspects)
00174 : property_(property), aspects_(aspects)
00175 {
00176 }
00177
00178
00179 component* handle_get(const path_element &child)
00180 {
00181 typename aspect_map::const_iterator a = aspects_.find(child.id);
00182 if (a!=aspects_.end()){
00183 return &*a->second;
00184 }
00185 return NULL;
00186 }
00187
00188 bool handle_change(const path_element &, const config &)
00189 {
00190 return false;
00191 }
00192
00193 bool handle_add(const path_element &, const config &)
00194 {
00195 return false;
00196 }
00197
00198 bool handle_delete(const path_element &child)
00199 {
00200
00201 if (child.id == "*") {
00202 bool b = false;
00203 foreach(typename aspect_map::value_type a, aspects_) {
00204 b |= a.second->delete_all_facets();
00205 }
00206 return b;
00207 }
00208 return false;
00209 }
00210
00211
00212 std::vector<component*> handle_get_children()
00213 {
00214 std::vector<component*> children;
00215 foreach(typename aspect_map::value_type a, aspects_) {
00216 children.push_back(&*a.second);
00217 }
00218 return children;
00219 }
00220
00221 private:
00222
00223 const std::string &property_;
00224 aspect_map &aspects_;
00225
00226 };
00227
00228
00229
00230 template<typename X>
00231 static void register_vector_property(std::map<std::string,property_handler_ptr> &property_handlers, const std::string &property, std::vector< boost::shared_ptr<X> > &values, boost::function2<void, std::vector< boost::shared_ptr<X> >&, const config&> construction_factory)
00232 {
00233 property_handler_ptr handler_ptr = property_handler_ptr(new vector_property_handler<X>(property,values,construction_factory));
00234 property_handlers.insert(std::make_pair(property,handler_ptr));
00235 }
00236
00237 template<typename X>
00238 static void register_aspect_property(std::map<std::string,property_handler_ptr> &property_handlers, const std::string &property, std::map< std::string, boost::shared_ptr<X> > &aspects)
00239 {
00240 property_handler_ptr handler_ptr = property_handler_ptr(new aspect_property_handler<X>(property,aspects));
00241 property_handlers.insert(std::make_pair(property,handler_ptr));
00242 }
00243
00244
00245 }
00246
00247 #endif