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