Atlas  0.7.0
Networking protocol for the Worldforge system.
Factories.cpp
1 /*
2  Copyright 2000-2001 Aloril.
3  Copyright 2001-2005 Alistair Riddoch.
4  Copyright (C) 2019 Erik Ogenvik
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 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program; if not, write to the Free Software
18  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20 
21 #include "Factories.h"
22 
23 #include "Atlas/Objects/Anonymous.h"
24 #include "Atlas/Objects/Generic.h"
25 
26 namespace Atlas {
27 namespace Objects {
28 
30 using Atlas::Message::ListType;
31 using Atlas::Message::MapType;
32 
33 SmartPtr<RootData> generic_factory(const std::string& name, int no) {
34  Operation::Generic obj;
35  obj->setType(name, no);
36  return obj;
37 }
38 
39 SmartPtr<RootData> anonymous_factory(const std::string& name, int no) {
40  Entity::Anonymous obj;
41  obj->setType(name, no);
42  return obj;
43 }
44 
45 Factories::Factories() {
46  installStandardTypes();
47 }
48 
49 Factories::~Factories() = default;
50 
51 bool Factories::hasFactory(const std::string& name) const {
52  auto I = m_factories.find(name);
53  return I != m_factories.end();
54 }
55 
56 Root Factories::createObject(const std::string& name) const {
57  auto I = m_factories.find(name);
58  if (I == m_factories.end()) {
59  return Root(nullptr);
60  } else {
61  return (*I).second.factory_method(name, (*I).second.classno);
62  }
63 }
64 
65 Root Factories::createObject(const MapType& msg_map) const {
66  Root obj = instantiateObject(msg_map);
67 
68  for (auto& entry : msg_map) {
69  obj->setAttr(entry.first, entry.second, this);
70  }
71  return obj;
72 }
73 
74 Root Factories::createObject(Atlas::Message::MapType&& msg_map) const {
75  Root obj = instantiateObject(msg_map);
76 
77  for (auto& entry : msg_map) {
78  obj->setAttr(entry.first, std::move(entry.second), this);
79  }
80  return obj;
81 }
82 
83 
84 Root Factories::instantiateObject(const Atlas::Message::MapType& msg_map) const {
85  // is this instance of entity or operation?
86  auto I = msg_map.find(Atlas::Objects::OBJTYPE_ATTR);
87  auto Iend = msg_map.end();
88  if (I != Iend && I->second.isString()) {
89  auto& objtype = I->second.String();
90  if (objtype == "op" || objtype == "obj" || objtype == "object") {
91  // get parent
92  I = msg_map.find(Atlas::Objects::PARENT_ATTR);
93  if (I != Iend && I->second.isString()) {
94  auto& parent = I->second.String();
95  // objtype and parent ok, try to create it:
96  auto J = m_factories.find(parent);
97  if (J != m_factories.end()) {
98  return J->second.factory_method(parent, J->second.classno);
99  } else {
100  if (objtype == "op") {
102  } else {
104  }
105  }
106  // FIXME We might want to do something different here.
107  } // has parent attr?
108  } // has known objtype
109  } // has objtype attr
110  // Should we really use factory? Why not just instantiate by hand?
112 }
113 
114 
115 Root Factories::getDefaultInstance(const std::string& name) const {
116  auto I = m_factories.find(name);
117  if (I == m_factories.end()) {
118  //perhaps throw something instead?
119  return Root(nullptr);
120  } else {
121  return (*I).second.default_instance_method(name, (*I).second.classno);
122  }
123 }
124 
125 std::list<std::string> Factories::getKeys() const {
126  std::list<std::string> keys;
127  for (const auto& factory : m_factories) {
128  keys.push_back(factory.first);
129  }
130  return keys;
131 }
132 
133 void Factories::addFactory(const std::string& name, FactoryMethod method, DefaultInstanceMethod defaultInstanceMethod, int classno) {
134  Factory factory{};
135  factory.classno = classno;
136  factory.default_instance_method = defaultInstanceMethod;
137  factory.factory_method = method;
138  m_factories[name] = factory;
139 }
140 
141 int Factories::addFactory(const std::string& name, FactoryMethod method, DefaultInstanceMethod defaultInstanceMethod) {
142  int classno = ++enumMax;
143  Factory factory{};
144  factory.classno = classno;
145  factory.default_instance_method = defaultInstanceMethod;
146  factory.factory_method = method;
147  m_factories[name] = factory;
148  return classno;
149 }
150 
151 std::vector<Root> Factories::parseListOfObjects(const Atlas::Message::ListType& val) const {
152  std::vector<Root> objects;
153  objects.reserve(val.size());
154  for (const auto& entry : val) {
155  if (entry.isMap()) {
156  objects.emplace_back(createObject(entry.Map()));
157  }
158  }
159  return objects;
160 }
161 
162 std::vector<Root> Factories::parseListOfObjects(Atlas::Message::ListType&& val) const {
163  std::vector<Root> objects;
164  objects.reserve(val.size());
165  for (auto& entry : val) {
166  if (entry.isMap()) {
167  objects.emplace_back(createObject(entry.moveMap()));
168  }
169  }
170  return objects;
171 }
172 
173 }
174 } // namespace Atlas::Objects
std::vector< Root > parseListOfObjects(const Atlas::Message::ListType &val) const
Definition: Factories.cpp:151
Definition: Bridge.h:21