The Battle for Wesnoth  1.17.0-dev
property_handler.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 - 2018 by Yurii Chernyi <terraninfo@terraninfo.net>
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 /**
16  * Composite AI component
17  * @file
18  */
19 
20 #pragma once
21 
22 #include <functional>
23 #include "config.hpp"
25 
26 #include <algorithm>
27 
28 namespace ai{
29 
30 template<typename T>
32 public:
34  : count_(0), element_(element)
35  {
36  }
38 
39  bool operator()(const T& t)
40  {
41  if ( (!element_.id.empty()) && (element_.id == t->get_id()) ) {
42  return true;
43  }
44  if (count_ == element_.position) {
45  return true;
46  }
47  count_++;
48  return false;
49  }
50 
51 private:
52  int count_;
54 };
55 
56 class component;
57 
59 public:
60 
62 
63  virtual component* handle_get(const path_element &child) = 0;
64  virtual bool handle_change(const path_element &child, config cfg) = 0;
65  virtual bool handle_add(const path_element &child, const config &cfg) = 0;
66  virtual bool handle_delete(const path_element &child) = 0;
67  virtual std::vector< component* > handle_get_children() = 0;
68 };
69 
70 typedef std::shared_ptr< base_property_handler > property_handler_ptr;
71 
72 template<typename T>
74 public:
75  typedef std::shared_ptr<T> ptr;
76  typedef std::vector< std::shared_ptr<T>> ptr_vector;
77 
78  vector_property_handler(const std::string &property, ptr_vector &values, std::function<void(ptr_vector&, const config&)> &construction_factory)
79  : factory_(construction_factory), property_(property), values_(values){}
80 
82  {
83  typename ptr_vector::iterator i = std::find_if(values_.begin(),values_.end(),path_element_matches<ptr>(child));
84  if (i!=values_.end()){
85  return &*(*i);
86  }
87  return nullptr;
88  }
89  bool handle_change(const path_element &child, config cfg)
90  {
91  if (!handle_delete(child)) {
92  return false;
93  }
94  if (!cfg.has_attribute("id")) {
95  cfg["id"] = child.id;
96  }
97 
98  return handle_add(child,cfg);
99  }
100  bool handle_add(const path_element &child, const config &cfg)
101  {
102  //if the id is not empty, try to delete all with this id
103  if (!cfg["id"].empty()) {
104  path_element with_same_id;
105  with_same_id.id = cfg["id"].str();
106  with_same_id.property = property_;
107  with_same_id.position=-1;
108  handle_delete(with_same_id);
109  }
110 
111  typename ptr_vector::iterator i = std::find_if(values_.begin(),values_.end(),path_element_matches<ptr>(child));
112  return do_add(i-values_.begin(),cfg);
113  }
114 
115  bool handle_delete(const path_element &child)
116  {
117  //* is a special case - 'delete all'
118  if (child.id == "*") {
119  values_.clear();
120  return true;
121  }
122 
123  typename ptr_vector::iterator i = std::find_if(values_.begin(),values_.end(),path_element_matches<ptr>(child));
124  if (i!=values_.end()){
125  values_.erase(i);
126  return true;
127  }
128  return false;
129  }
130 
131  std::vector<component*> handle_get_children()
132  {
133  std::vector<component*> children;
134  for (ptr v : values_) {
135  children.push_back(&*v);
136  }
137  return children;
138  }
139 
140 protected:
141  void call_factory(ptr_vector& vec, const config& cfg)
142  {
143  factory_(vec, cfg);
144  }
145 private:
146  bool do_add(int pos, const config &cfg)
147  {
148  if (pos<0) {
149  pos = values_.size();
150  }
151  ptr_vector values;
152  call_factory(values,cfg);
153  int j=0;
154  for (ptr b : values ) {
155  values_.insert(values_.begin()+pos+j,b);
156  j++;
157  }
158  return (j>0);
159  }
160 
161  std::function<void(ptr_vector&, const config&)> factory_;
162  const std::string property_;
163  ptr_vector &values_;
164 
165 };
166 
167 template<typename T>
171 public:
172 
173  facets_property_handler(const std::string &property, ptr_vector &values, ptr& def, std::function<void(ptr_vector&, const config&)> &construction_factory)
174  : vector_property_handler<T>(property, values, construction_factory)
175  , default_(def)
176  {
177  }
178 
180  {
181  // special case - 'get the default facet'
182  if (child.id == "default_facet") {
183  return default_.get();
184  }
186  }
187 
188  bool handle_change(const path_element &child, config cfg)
189  {
190  // special case - 'replace the default facet'
191  if (child.id == "default_facet") {
192  ptr_vector values;
193  this->call_factory(values,cfg);
194  default_ = values.back();
195  return true;
196  }
198  }
199 
200  std::vector<component*> handle_get_children()
201  {
202  std::vector<component*> children = vector_property_handler<T>::handle_get_children();
203  children.push_back(default_.get());
204  return children;
205  }
206 
207 private:
208  ptr& default_;
209 };
210 
211 template<typename T>
213 public:
214  typedef std::shared_ptr<T> ptr;
215  typedef std::map< std::string, ptr > aspect_map;
216 
217  aspect_property_handler(const std::string &property, aspect_map &aspects, std::function<void(aspect_map&, const config&, std::string)> &construction_factory)
218  : property_(property), aspects_(aspects), factory_(construction_factory)
219  {
220  }
221 
223  {
224  typename aspect_map::const_iterator a = aspects_.find(child.id);
225  if (a!=aspects_.end()){
226  return &*a->second;
227  }
228  return nullptr;
229  }
230 
231  bool handle_change(const path_element &child, config cfg)
232  {
233  if (aspects_.find(child.id) == aspects_.end()) {
234  return false;
235  }
236  if (!cfg.has_attribute("name")) {
237  cfg["name"] = "composite_aspect";
238  }
239  cfg["id"] = child.id;
240  factory_(aspects_, cfg, child.id);
241  return true;
242  }
243 
244  bool handle_add(const path_element &/*child*/, const config &/*cfg*/)
245  {
246  return false;
247  }
248 
249  bool handle_delete(const path_element &child)
250  {
251  //* is a special case - 'delete all facets'
252  if (child.id == "*") {
253  bool b = false;
254  for (typename aspect_map::value_type a : aspects_) {
255  b |= a.second->delete_all_facets();
256  }
257  return b;
258  }
259  return false;
260  }
261 
262  std::vector<component*> handle_get_children()
263  {
264  std::vector<component*> children;
265  for (typename aspect_map::value_type a : aspects_) {
266  children.push_back(&*a.second);
267  }
268  return children;
269  }
270 
271 private:
272 
273  const std::string &property_;
274  aspect_map &aspects_;
275  std::function<void(aspect_map&, const config&, std::string)> factory_;
276 
277 };
278 
279 template<typename X>
280 static inline void register_vector_property(property_handler_map& property_handlers, const std::string& property,
281  std::vector<std::shared_ptr<X>>& values, std::function<void(std::vector<std::shared_ptr<X>>&, const config&)> construction_factory)
282 {
283  property_handlers.emplace(property,
284  std::make_shared<vector_property_handler<X>>(property, values, construction_factory));
285 }
286 
287 template<typename X>
288 static inline void register_facets_property(property_handler_map& property_handlers, const std::string& property,
289  std::vector<std::shared_ptr<X>>& values, std::shared_ptr<X>& def, std::function<void(std::vector<std::shared_ptr<X>>&, const config&)> construction_factory)
290 {
291  property_handlers.emplace(property,
292  std::make_shared<facets_property_handler<X>>(property, values, def, construction_factory));
293 }
294 
295 template<typename X>
296 static inline void register_aspect_property(property_handler_map& property_handlers, const std::string& property,
297  std::map<std::string, std::shared_ptr<X>>& aspects, std::function<void(std::map<std::string, std::shared_ptr<X>>&, const config&, std::string)> construction_factory)
298 {
299  property_handlers.emplace(property,
300  std::make_shared<aspect_property_handler<X>>(property, aspects, construction_factory));
301 }
302 
303 } //of namespace ai
std::vector< component * > handle_get_children()
bool has_attribute(config_key_type key) const
Definition: config.cpp:210
#define a
void call_factory(ptr_vector &vec, const config &cfg)
bool handle_add(const path_element &, const config &)
bool handle_add(const path_element &child, const config &cfg)
vector_property_handler(const std::string &property, ptr_vector &values, std::function< void(ptr_vector &, const config &)> &construction_factory)
Definitions for the interface to Wesnoth Markup Language (WML).
static void register_vector_property(property_handler_map &property_handlers, const std::string &property, std::vector< std::shared_ptr< X >> &values, std::function< void(std::vector< std::shared_ptr< X >> &, const config &)> construction_factory)
std::vector< component * > handle_get_children()
bool handle_delete(const path_element &child)
bool handle_delete(const path_element &child)
#define b
facets_property_handler(const std::string &property, ptr_vector &values, ptr &def, std::function< void(ptr_vector &, const config &)> &construction_factory)
A small explanation about what&#39;s going on here: Each action has access to two game_info objects First...
Definition: actions.cpp:60
component * handle_get(const path_element &child)
std::vector< component * > handle_get_children()
std::vector< std::shared_ptr< T > > ptr_vector
path_element_matches(const path_element &element)
A component of the AI framework.
bool handle_change(const path_element &child, config cfg)
std::string property
Definition: component.hpp:41
std::string id
Definition: component.hpp:42
std::size_t i
Definition: function.cpp:940
vector_property_handler< T >::ptr ptr
bool do_add(int pos, const config &cfg)
component * handle_get(const path_element &child)
std::function< void(ptr_vector &, const config &)> factory_
double t
Definition: astarsearch.cpp:64
std::map< std::string, ptr > aspect_map
bool handle_change(const path_element &child, config cfg)
std::map< std::string, property_handler_ptr > property_handler_map
Definition: component.hpp:48
component * handle_get(const path_element &child)
std::function< void(aspect_map &, const config &, std::string)> factory_
vector_property_handler< T >::ptr_vector ptr_vector
static void register_facets_property(property_handler_map &property_handlers, const std::string &property, std::vector< std::shared_ptr< X >> &values, std::shared_ptr< X > &def, std::function< void(std::vector< std::shared_ptr< X >> &, const config &)> construction_factory)
std::shared_ptr< base_property_handler > property_handler_ptr
Definition: component.hpp:46
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:59
bool handle_change(const path_element &child, config cfg)
std::string::const_iterator iterator
Definition: tokenizer.hpp:24
static void register_aspect_property(property_handler_map &property_handlers, const std::string &property, std::map< std::string, std::shared_ptr< X >> &aspects, std::function< void(std::map< std::string, std::shared_ptr< X >> &, const config &, std::string)> construction_factory)
aspect_property_handler(const std::string &property, aspect_map &aspects, std::function< void(aspect_map &, const config &, std::string)> &construction_factory)