The Battle for Wesnoth  1.19.13+dev
property_handler.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 - 2025
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) const = 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() const = 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  template<typename Factory>
80  vector_property_handler(const std::string &property, ptr_vector &values, Factory&& construction_factory)
81  : factory_(construction_factory), property_(property), values_(values){}
82 
83  component* handle_get(const path_element &child) const
84  {
85  typename ptr_vector::iterator i = std::find_if(values_.begin(),values_.end(),path_element_matches<ptr>(child));
86  if (i!=values_.end()){
87  return &*(*i);
88  }
89  return nullptr;
90  }
91  bool handle_change(const path_element &child, config cfg)
92  {
93  if (!handle_delete(child)) {
94  return false;
95  }
96  if (!cfg.has_attribute("id")) {
97  cfg["id"] = child.id;
98  }
99 
100  return handle_add(child,cfg);
101  }
102  bool handle_add(const path_element &child, const config &cfg)
103  {
104  //if the id is not empty, try to delete all with this id
105  if (!cfg["id"].empty()) {
106  path_element with_same_id;
107  with_same_id.id = cfg["id"].str();
108  with_same_id.property = property_;
109  with_same_id.position=-1;
110  handle_delete(with_same_id);
111  }
112 
113  typename ptr_vector::iterator i = std::find_if(values_.begin(),values_.end(),path_element_matches<ptr>(child));
114  return do_add(i-values_.begin(),cfg);
115  }
116 
117  bool handle_delete(const path_element &child)
118  {
119  //* is a special case - 'delete all'
120  if (child.id == "*") {
121  values_.clear();
122  return true;
123  }
124 
125  typename ptr_vector::iterator i = std::find_if(values_.begin(),values_.end(),path_element_matches<ptr>(child));
126  if (i!=values_.end()){
127  values_.erase(i);
128  return true;
129  }
130  return false;
131  }
132 
133  std::vector<component*> handle_get_children() const
134  {
135  std::vector<component*> children;
136  for (ptr v : values_) {
137  children.push_back(&*v);
138  }
139  return children;
140  }
141 
142 protected:
143  void call_factory(ptr_vector& vec, const config& cfg)
144  {
145  factory_(vec, cfg);
146  }
147 private:
148  bool do_add(int pos, const config &cfg)
149  {
150  if (pos<0) {
151  pos = values_.size();
152  }
154  call_factory(values,cfg);
155  int j=0;
156  for (ptr b : values ) {
157  values_.insert(values_.begin()+pos+j,b);
158  j++;
159  }
160  return (j>0);
161  }
162 
163  std::function<void(ptr_vector&, const config&)> factory_;
164  const std::string property_;
166 
167 };
168 
169 template<typename T>
173 public:
174 
175  template<typename Factory>
176  facets_property_handler(const std::string &property, ptr_vector &values, ptr& def, Factory&& construction_factory)
177  : vector_property_handler<T>(property, values, construction_factory)
178  , default_(def)
179  {
180  }
181 
182  component* handle_get(const path_element &child) const
183  {
184  // special case - 'get the default facet'
185  if (child.id == "default_facet") {
186  return default_.get();
187  }
189  }
190 
191  bool handle_change(const path_element &child, config cfg)
192  {
193  // special case - 'replace the default facet'
194  if (child.id == "default_facet") {
196  this->call_factory(values,cfg);
197  default_ = values.back();
198  return true;
199  }
201  }
202 
203  std::vector<component*> handle_get_children() const
204  {
205  std::vector<component*> children = vector_property_handler<T>::handle_get_children();
206  children.push_back(default_.get());
207  return children;
208  }
209 
210 private:
212 };
213 
214 template<typename T>
216 public:
217  typedef std::shared_ptr<T> ptr;
218  typedef std::map< std::string, ptr > aspect_map;
219 
220  template<typename Factory>
221  aspect_property_handler(const std::string &property, aspect_map &aspects, Factory&& construction_factory)
222  : property_(property), aspects_(aspects), factory_(construction_factory)
223  {
224  }
225 
226  component* handle_get(const path_element &child) const
227  {
228  typename aspect_map::const_iterator a = aspects_.find(child.id);
229  if (a!=aspects_.end()){
230  return &*a->second;
231  }
232  return nullptr;
233  }
234 
235  bool handle_change(const path_element &child, config cfg)
236  {
237  if (aspects_.find(child.id) == aspects_.end()) {
238  return false;
239  }
240  if (!cfg.has_attribute("name")) {
241  cfg["name"] = "composite_aspect";
242  }
243  cfg["id"] = child.id;
244  factory_(aspects_, cfg, child.id);
245  return true;
246  }
247 
248  bool handle_add(const path_element &/*child*/, const config &/*cfg*/)
249  {
250  return false;
251  }
252 
253  bool handle_delete(const path_element &child)
254  {
255  //* is a special case - 'delete all facets'
256  if (child.id == "*") {
257  bool b = false;
258  for (typename aspect_map::value_type a : aspects_) {
259  b |= a.second->delete_all_facets();
260  }
261  return b;
262  }
263  return false;
264  }
265 
266  std::vector<component*> handle_get_children() const
267  {
268  std::vector<component*> children;
269  for (typename aspect_map::value_type a : aspects_) {
270  children.push_back(&*a.second);
271  }
272  return children;
273  }
274 
275 private:
276 
277  const std::string &property_;
279  std::function<void(aspect_map&, const config&, std::string)> factory_;
280 
281 };
282 
283 template<typename X, typename Factory>
284 static inline void register_vector_property(property_handler_map& property_handlers, const std::string& property,
285  std::vector<std::shared_ptr<X>>& values, Factory&& construction_factory)
286 {
287  property_handlers.emplace(property,
288  std::make_shared<vector_property_handler<X>>(property, values, std::move(construction_factory)));
289 }
290 
291 template<typename X, typename Factory>
292 static inline void register_facets_property(property_handler_map& property_handlers, const std::string& property,
293  std::vector<std::shared_ptr<X>>& values, std::shared_ptr<X>& def, Factory&& construction_factory)
294 {
295  property_handlers.emplace(property,
296  std::make_shared<facets_property_handler<X>>(property, values, def, std::move(construction_factory)));
297 }
298 
299 template<typename X, typename Factory>
300 static inline void register_aspect_property(property_handler_map& property_handlers, const std::string& property,
301  std::map<std::string, std::shared_ptr<X>>& aspects, Factory&& construction_factory)
302 {
303  property_handlers.emplace(property,
304  std::make_shared<aspect_property_handler<X>>(property, aspects, std::move(construction_factory)));
305 }
306 
307 } //of namespace ai
double t
Definition: astarsearch.cpp:63
bool handle_add(const path_element &, const config &)
std::function< void(aspect_map &, const config &, std::string)> factory_
component * handle_get(const path_element &child) const
std::map< std::string, ptr > aspect_map
std::vector< component * > handle_get_children() const
bool handle_change(const path_element &child, config cfg)
bool handle_delete(const path_element &child)
aspect_property_handler(const std::string &property, aspect_map &aspects, Factory &&construction_factory)
virtual bool handle_delete(const path_element &child)=0
virtual component * handle_get(const path_element &child) const =0
virtual bool handle_add(const path_element &child, const config &cfg)=0
virtual bool handle_change(const path_element &child, config cfg)=0
virtual std::vector< component * > handle_get_children() const =0
std::vector< component * > handle_get_children() const
vector_property_handler< T >::ptr ptr
bool handle_change(const path_element &child, config cfg)
facets_property_handler(const std::string &property, ptr_vector &values, ptr &def, Factory &&construction_factory)
component * handle_get(const path_element &child) const
vector_property_handler< T >::ptr_vector ptr_vector
path_element_matches(const path_element &element)
void call_factory(ptr_vector &vec, const config &cfg)
std::function< void(ptr_vector &, const config &)> factory_
component * handle_get(const path_element &child) const
bool handle_add(const path_element &child, const config &cfg)
vector_property_handler(const std::string &property, ptr_vector &values, Factory &&construction_factory)
bool do_add(int pos, const config &cfg)
std::vector< std::shared_ptr< T > > ptr_vector
std::vector< component * > handle_get_children() const
bool handle_change(const path_element &child, config cfg)
bool handle_delete(const path_element &child)
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:158
bool has_attribute(config_key_type key) const
Definition: config.cpp:157
A component of the AI framework.
Definitions for the interface to Wesnoth Markup Language (WML).
std::size_t i
Definition: function.cpp:1032
A small explanation about what's going on here: Each action has access to two game_info objects First...
Definition: actions.cpp:59
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, Factory &&construction_factory)
std::shared_ptr< base_property_handler > property_handler_ptr
Definition: component.hpp:46
static void register_vector_property(property_handler_map &property_handlers, const std::string &property, std::vector< std::shared_ptr< X >> &values, Factory &&construction_factory)
std::map< std::string, property_handler_ptr > property_handler_map
Definition: component.hpp:48
static void register_aspect_property(property_handler_map &property_handlers, const std::string &property, std::map< std::string, std::shared_ptr< X >> &aspects, Factory &&construction_factory)
constexpr auto values
Definition: ranges.hpp:42
std::string::const_iterator iterator
Definition: tokenizer.hpp:25
std::string property
Definition: component.hpp:41
std::string id
Definition: component.hpp:42
#define b