Added ai command setEquipment
[ryzomcore.git] / ryzom / server / src / persistant_data_service / pds_attribute.cpp
blobf78805dc5860edf155fbfab1c6f585b270f13483
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "../pd_lib/pds_common.h"
19 #include "pds_attribute.h"
20 #include "pds_type.h"
21 #include "pds_table.h"
22 #include "pds_database.h"
23 #include "../pd_lib/db_description_parser.h"
25 #include <nel/misc/debug.h>
27 using namespace std;
28 using namespace NLMISC;
31 /// Destructor
32 CAttribute::~CAttribute()
34 //PDS_DEBUG("delete()");
39 * Initialize attribute using a full xml node
41 bool CAttribute::init(CDatabase *root, CTable* parent, const CAttributeNode& attribute)
43 // set parent logger
44 setParentLogger(parent);
46 _Parent = parent;
47 _Root = root;
49 _Name = attribute.Name;
50 _Id = attribute.Id;
52 _MetaType = attribute.MetaType;
53 _TypeId = attribute.TypeId;
55 switch (_MetaType)
57 case PDS_Type:
59 const CType* type = _Root->getType(_TypeId);
60 if (type == NULL)
62 PDS_WARNING("init(): unknown type '%d'", _TypeId);
63 return false;
66 _DataType = type->getDataType();
68 break;
70 case PDS_Class:
71 _DataType = PDS_UnknownDataType;
72 break;
74 case PDS_BackRef:
75 _DataType = PDS_Index;
76 _ReferencedAttribute = attribute.Reference;
77 break;
79 case PDS_ForwardRef:
80 _DataType = PDS_Index;
81 _ReferencedAttribute = attribute.Reference;
82 break;
84 case PDS_ArrayType:
86 const CType* index = _Root->getType(attribute.Index);
87 if (index == NULL || !index->isIndex())
89 PDS_WARNING("init(): type '%d' unknown or not an index", attribute.Index);
90 return false;
93 _IndexId = attribute.Index;
95 const CType* type = _Root->getType(_TypeId);
96 if (type == NULL)
98 PDS_WARNING("init(): unknown type '%d'", _TypeId);
99 return false;
102 _DataType = type->getDataType();
104 break;
106 case PDS_ArrayClass:
108 const CType* type = _Root->getType(attribute.Index);
109 if (type == NULL || !type->isIndex())
111 PDS_WARNING("init(): type '%d' unknown or not an index", attribute.Index);
112 return false;
115 _IndexId = attribute.Index;
116 _DataType = PDS_UnknownDataType;
118 break;
120 case PDS_ArrayRef:
122 const CType* type = _Root->getType(attribute.Index);
123 if (type == NULL || !type->isIndex())
125 PDS_WARNING("init(): type '%d' unknown or not an index", attribute.Index);
126 return false;
129 _IndexId = attribute.Index;
130 _DataType = PDS_Index;
131 _ReferencedAttribute = attribute.Reference;
132 _AllowNull = attribute.AllowNull;
134 break;
136 case PDS_Set:
137 _DataType = PDS_List;
138 _ReferencedAttribute = attribute.Reference;
139 break;
142 _Init = true;
144 return true;
148 * Build columns for this attribute
150 bool CAttribute::buildColumns()
152 vector<CColumn>& columns = _Parent->_Columns;
154 _Offset = (uint32)columns.size();
156 switch (_MetaType)
158 case PDS_Type:
160 CColumn column;
161 column._Parent = this;
162 column._Root = _Root;
163 column._Id = (uint32)columns.size();
164 column._Name = _Name;
165 column._MetaType = PDS_Type;
166 column._DataType = _DataType;
167 column._TypeId = _TypeId;
168 const CType* type = _Root->getType(_TypeId);
169 if (type == NULL)
171 PDS_WARNING("init(): unknown type '%d'", _TypeId);
172 return false;
174 column._ByteSize = type->getByteSize();
175 column._Init = true;
176 columns.push_back(column);
178 break;
180 case PDS_Class:
182 CTable* sub = const_cast<CTable*>(_Root->getTable(_TypeId));
184 if (sub == NULL || !sub->buildColumns())
185 return false;
187 uint i;
188 for (i=0; i<sub->_Columns.size(); ++i)
190 CColumn column = sub->_Columns[i];
191 column._Parent = this;
192 column._Root = _Root;
193 column._Id = (uint32)columns.size();
194 column._Name = _Name+"."+column._Name;
195 column._Init = true;
196 columns.push_back(column);
199 break;
201 case PDS_BackRef:
202 case PDS_ForwardRef:
203 case PDS_Set:
205 CColumn column;
206 column._Parent = this;
207 column._Root = _Root;
208 column._Id = (uint32)columns.size();
209 column._Name = _Name;
210 column._MetaType = _MetaType;
211 column._DataType = _DataType;
212 column._TypeId = _TypeId;
213 column._ByteSize = getStandardByteSize(column._DataType);
214 column._Init = true;
215 columns.push_back(column);
217 break;
219 case PDS_ArrayType:
221 const CType* type = _Root->getType(_TypeId);
222 const CType* index = _Root->getType(_IndexId);
224 if (type == NULL)
226 PDS_WARNING("init(): unknown type '%d'", _TypeId);
227 return false;
230 if (index == NULL || !index->isIndex())
232 PDS_WARNING("buildColumns(): type '%d' unknown or not an index", _IndexId);
233 return false;
236 uint i;
237 for (i=0; i<index->getIndexSize(); ++i)
239 CColumn column;
240 column._Parent = this;
241 column._Root = _Root;
242 column._Id = (uint32)columns.size();
243 column._Name = _Name+"["+index->getIndexName(i)+"]";
244 column._MetaType = PDS_Type;
245 column._DataType = _DataType;
246 column._TypeId = _TypeId;
247 column._ByteSize = type->getByteSize();
248 column._Init = true;
249 columns.push_back(column);
252 break;
254 case PDS_ArrayClass:
256 CTable* sub = const_cast<CTable*>(_Root->getTable(_TypeId));
257 const CType* index = _Root->getType(_IndexId);
259 if (sub == NULL || sub == NULL || !sub->buildColumns())
261 PDS_WARNING("buildColumns(): unknown table '%d' or failed to build its columns", _TypeId);
262 return false;
265 if (index == NULL || index == NULL || !index->isIndex())
267 PDS_WARNING("buildColumns(): type '%d' unknown or not an index", _IndexId);
268 return false;
271 uint i;
272 for (i=0; i<index->getIndexSize(); ++i)
274 uint j;
275 for (j=0; j<sub->_Columns.size(); ++j)
277 CColumn column = sub->_Columns[j];
278 column._Parent = this;
279 column._Root = _Root;
280 column._Id = (uint32)columns.size();
281 column._Name = _Name+"["+index->getIndexName(i)+"]"+"."+column._Name;
282 column._Init = true;
283 columns.push_back(column);
287 break;
289 case PDS_ArrayRef:
291 const CType* index = _Root->getType(_IndexId);
293 if (index == NULL || !index->isIndex())
295 PDS_WARNING("buildColumns(): type '%d' unknown or not an index", _IndexId);
296 return false;
299 uint i;
300 for (i=0; i<index->getIndexSize(); ++i)
302 CColumn column;
303 column._Parent = this;
304 column._Root = _Root;
305 column._Id = (uint32)columns.size();
306 column._Name = _Name+"["+index->getIndexName(i)+"]";;
307 column._MetaType = PDS_ForwardRef;
308 column._DataType = _DataType;
309 column._TypeId = _TypeId;
310 column._ByteSize = getStandardByteSize(column._DataType);
311 column._Init = true;
312 columns.push_back(column);
315 break;
317 default:
318 PDS_WARNING("buildColumns(): attribute '%s' metatype is unknown", _Name.c_str());
319 return false;
320 break;
323 _Columns = (uint32)columns.size() - _Offset;
325 return true;
330 * Compute back reference key
332 bool CAttribute::computeBackRefKey()
334 if (_MetaType == PDS_BackRef)
336 const CTable* parentTable = _Root->getTable(_TypeId);
337 const CAttribute* parentAttribute = parentTable->getAttribute(_ReferencedAttribute);
339 // should check parentAttribute is a forward reference of any kind
341 const CTable* childTable = _Root->getTable(parentAttribute->getTypeId());
343 _Key = childTable->getKey();
345 else if (_MetaType == PDS_ArrayRef || _MetaType == PDS_Set)
347 const CTable* childTable = _Root->getTable(_TypeId);
348 const CAttribute* childAttribute = childTable->getAttribute(_ReferencedAttribute);
350 if (childAttribute == NULL)
352 PDS_WARNING("computeBackRefKey(): failed, child backref not initialised");
353 return false;
356 if (childAttribute->getMetaType() != PDS_BackRef)
358 PDS_WARNING("computeBackRefKey(): failed, child backref actually not a backref");
359 return false;
362 _Key = childTable->getKey();
363 if (_Key == INVALID_TYPE_ID)
365 PDS_WARNING("computeBackRefKey(): failed, child key is invalid");
366 return false;
369 const CAttribute* keyAttribute = childTable->getAttribute(_Key);
371 if (keyAttribute == NULL)
373 PDS_WARNING("computeBackRefKey(): failed, child key '%d' attribute cannot be found", _Key);
374 return false;
377 if (_Key != childAttribute->getBackRefKey())
379 PDS_WARNING("computeBackRefKey(): failed, child backref key '%d' mismatch child key '%d'", childAttribute->getBackRefKey(), _Key);
380 return false;
384 return true;