ai/composite/property_handler.hpp

Go to the documentation of this file.
00001 /* $Id: property_handler.hpp 52533 2012-01-07 02:35:17Z shadowmaster $ */
00002 /*
00003    Copyright (C) 2009 - 2012 by Yurii Chernyi <terraninfo@terraninfo.net>
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY.
00012 
00013    See the COPYING file for more details.
00014 */
00015 
00016 /**
00017  * Composite AI component
00018  * @file
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         //if the id is not empty, try to delete all with this id
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         //* is a special case - 'delete all'
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 &/*child*/, const config &/*cfg*/)
00189     {
00190         return false;
00191     }
00192 
00193     bool handle_add(const path_element &/*child*/, const config &/*cfg*/)
00194     {
00195         return false;
00196     }
00197 
00198     bool handle_delete(const path_element &child)
00199     {
00200         //* is a special case - 'delete all facets'
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 } //of namespace ai
00246 
00247 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Fri May 25 2012 01:02:43 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs