1 /*
2 * Copyright 2006 Sony Computer Entertainment Inc.
3 *
4 * Licensed under the MIT Open Source License, for details please see license.txt or the website
5 * http://www.opensource.org/licenses/mit-license.php
6 *
7 */
8
9 #include <dae.h>
10 #include <dae/daeMetaElement.h>
11 #include <dae/daeElement.h>
12 #include <dae/daeDocument.h>
13 #include <dae/domAny.h>
14 #include <dae/daeMetaCMPolicy.h>
15 #include <dae/daeMetaElementAttribute.h>
16
17 daeElementRef
create()18 daeMetaElement::create()
19 {
20 daeElementRef ret = (*_createFunc)(dae);
21 ret->setup(this);
22
23 return ret;
24 }
25
26 daeElementRef
create(daeString s)27 daeMetaElement::create(daeString s)
28 {
29 daeMetaElement* me = NULL;
30 if ( strcmp( s, _name ) == 0 ) {
31 //looking for this meta
32 me = this;
33 }
34 else if ( _contentModel != NULL ) {
35 me = _contentModel->findChild(s);
36 }
37 if (me != NULL) {
38 daeElementRef ret = me->create();
39 if ( strcmp(s, me->getName() ) != 0 ) {
40 ret->setElementName(s);
41 }
42 return ret;
43 }
44 if ( getAllowsAny() ) {
45 daeElementRef ret = domAny::registerElement(dae)->create();
46 ret->setElementName(s);
47 return ret;
48 }
49 return NULL;
50 }
51
daeMetaElement(DAE & dae)52 daeMetaElement::daeMetaElement(DAE& dae) : dae(dae)
53 {
54 _name = "noname";
55 _createFunc = NULL;
56 _elementSize = sizeof(daeElement);
57 _metaValue = NULL;
58 _metaContents = NULL;
59 _metaContentsOrder = NULL; // sthomas
60 _metaID = NULL;
61 _isTrackableForQueries = true;
62 _usesStringContents = false;
63 _isTransparent = false;
64 _isAbstract = false;
65 _allowsAny = false;
66 _innerClass = false;
67 _contentModel = NULL;
68 _metaCMData = NULL;
69 _numMetaChoices = 0;
70 }
71
~daeMetaElement()72 daeMetaElement::~daeMetaElement()
73 {
74 delete _metaContents;
75 delete _contentModel;
76 delete _metaContentsOrder;
77 delete _metaCMData;
78 }
79
getDAE()80 DAE* daeMetaElement::getDAE() {
81 return &dae;
82 }
83
setCMRoot(daeMetaCMPolicy * cm)84 void daeMetaElement::setCMRoot( daeMetaCMPolicy *cm )
85 {
86 if (_contentModel)
87 delete _contentModel;
88 _contentModel = cm;
89 }
90
91 void
addContents(daeInt offset)92 daeMetaElement::addContents(daeInt offset)
93 {
94 daeMetaElementArrayAttribute* meaa = new daeMetaElementArrayAttribute( this, NULL, 0, 1, -1 );
95 meaa->setType(dae.getAtomicTypes().get("element"));
96 meaa->setName("contents");
97 meaa->setOffset(offset);
98 meaa->setContainer( this);
99 _metaContents = meaa;
100 }
101 void
addContentsOrder(daeInt offset)102 daeMetaElement::addContentsOrder(daeInt offset)
103 {
104 daeMetaArrayAttribute* meaa = new daeMetaArrayAttribute();
105 meaa->setType(dae.getAtomicTypes().get("uint"));
106 meaa->setName("contentsOrder");
107 meaa->setOffset(offset);
108 meaa->setContainer( this);
109
110 if (_metaContentsOrder)
111 delete _metaContentsOrder;
112
113 _metaContentsOrder = meaa;
114 }
115
addCMDataArray(daeInt offset,daeUInt numChoices)116 void daeMetaElement::addCMDataArray(daeInt offset, daeUInt numChoices)
117 {
118 daeMetaArrayAttribute* meaa = new daeMetaArrayAttribute();
119 meaa->setType(dae.getAtomicTypes().get("int"));
120 meaa->setName("CMData");
121 meaa->setOffset(offset);
122 meaa->setContainer( this);
123
124 if (_metaCMData)
125 delete _metaCMData;
126
127 _metaCMData = meaa;
128
129 _numMetaChoices = numChoices;
130 }
131
132
133 /*void
134 daeMetaElement::appendArrayElement(daeMetaElement* element, daeInt offset, daeString name)
135 {
136 daeMetaElementArrayAttribute* meaa = new daeMetaElementArrayAttribute;
137 meaa->setType(daeAtomicType::get("element"));
138 if ( name ) {
139 meaa->setName(name);
140 }
141 else {
142 meaa->setName(element->getName());
143 }
144 meaa->setOffset(offset);
145 meaa->setContainer(this);
146 meaa->setElementType( element);
147 _metaElements.append(meaa);
148 }
149 void
150 daeMetaElement::appendElement(daeMetaElement* element, daeInt offset, daeString name)
151 {
152 daeMetaElementAttribute* meaa = new daeMetaElementAttribute;
153 meaa->setType(daeAtomicType::get("element"));
154 if ( name ) {
155 meaa->setName(name);
156 }
157 else {
158 meaa->setName(element->getName());
159 }
160 meaa->setOffset( offset);
161 meaa->setContainer( this );
162 meaa->setElementType( element );
163 _metaElements.append(meaa);
164 }*/
165
166 void
appendAttribute(daeMetaAttribute * attr)167 daeMetaElement::appendAttribute(daeMetaAttribute* attr)
168 {
169 if (attr == NULL)
170 return;
171
172 if (strcmp(attr->getName(),"_value") == 0) {
173 _metaValue = attr;
174 }
175 else
176 _metaAttributes.append(attr);
177
178 if ((attr->getName() != NULL) &&
179 (strcmp(attr->getName(),"id") == 0)) {
180 _metaID = attr;
181 _isTrackableForQueries = true;
182 }
183 }
184
185 void
validate()186 daeMetaElement::validate()
187 {
188 if (_elementSize == 0)
189 {
190 daeInt place=0;
191 unsigned int i;
192 for(i=0;i<_metaAttributes.getCount();i++) {
193 place += _metaAttributes[i]->getSize();
194 int align = _metaAttributes[i]->getAlignment();
195 place += align;
196 place &= (~(align-1));
197 }
198 _elementSize = place;
199 }
200 }
201
202 daeMetaAttribute*
getMetaAttribute(daeString s)203 daeMetaElement::getMetaAttribute(daeString s)
204 {
205 int cnt = (int)_metaAttributes.getCount();
206 int i;
207 for(i=0;i<cnt;i++)
208 if (strcmp(_metaAttributes[i]->getName(),s) == 0)
209 return _metaAttributes[i];
210 return NULL;
211 }
212
213
214 // void daeMetaElement::releaseMetas()
215 // {
216 // _metas().clear();
217 // size_t count = _classMetaPointers().getCount();
218 // for ( size_t i = 0; i < count; i++ )
219 // {
220 // *(_classMetaPointers()[i]) = NULL;
221 // }
222 // _classMetaPointers().clear();
223 // if (mera)
224 // {
225 // delete mera;
226 // mera = NULL;
227 // }
228 // if (mes)
229 // {
230 // delete mes;
231 // mes = NULL;
232 // }
233 // }
234
place(daeElement * parent,daeElement * child,daeUInt * ordinal)235 daeBool daeMetaElement::place(daeElement *parent, daeElement *child, daeUInt *ordinal )
236 {
237 if (child->getMeta()->getIsAbstract() || parent->getMeta() != this ) {
238 return false;
239 }
240 daeUInt ord;
241 daeElement *retVal = _contentModel->placeElement( parent, child, ord );
242 if ( retVal != NULL ) {
243 //update document pointer
244 child->setDocument( parent->getDocument() );
245 retVal->setDocument( parent->getDocument() );
246 //add to _contents array
247 if (_metaContents != NULL) {
248 daeElementRefArray* contents =
249 (daeElementRefArray*)_metaContents->getWritableMemory(parent);
250 daeUIntArray* contentsOrder =
251 (daeUIntArray*)_metaContentsOrder->getWritableMemory(parent);
252 daeBool needsAppend = true;
253 size_t cnt = contentsOrder->getCount();
254 for ( size_t x = 0; x < cnt; x++ ) {
255 if ( contentsOrder->get(x) > ord ) {
256 contents->insertAt( x, retVal );
257 contentsOrder->insertAt( x, ord );
258 needsAppend = false;
259 break;
260 }
261 }
262 if ( needsAppend ) {
263 contents->append(retVal);
264 contentsOrder->append( ord );
265 }
266 }
267 if ( ordinal != NULL ) {
268 *ordinal = ord;
269 }
270 }
271 return retVal!=NULL;
272 }
273
placeAt(daeInt index,daeElement * parent,daeElement * child)274 daeBool daeMetaElement::placeAt( daeInt index, daeElement *parent, daeElement *child )
275 {
276 if (child->getMeta()->getIsAbstract() || parent->getMeta() != this || index < 0 ) {
277 return false;
278 }
279 daeUInt ord;
280 daeElement *retVal = _contentModel->placeElement( parent, child, ord );
281 if ( retVal != NULL ) {
282 //add to _contents array
283 if (_metaContents != NULL) {
284 daeElementRefArray* contents =
285 (daeElementRefArray*)_metaContents->getWritableMemory(parent);
286 daeUIntArray* contentsOrder =
287 (daeUIntArray*)_metaContentsOrder->getWritableMemory(parent);
288 daeBool validLoc;
289 if ( index > 0 ) {
290 validLoc = contentsOrder->get(index) >= ord && contentsOrder->get(index) <= ord;
291 }
292 else {
293 if ( contentsOrder->getCount() == 0 ) {
294 validLoc = true;
295 }
296 else {
297 validLoc = contentsOrder->get(index) >= ord;
298 }
299 }
300 if ( validLoc ) {
301 contents->insertAt( index, retVal );
302 contentsOrder->insertAt( index, ord );
303 }
304 else {
305 _contentModel->removeElement( parent, retVal );
306 retVal = NULL;
307 }
308 }
309 }
310 if ( retVal != NULL ) {
311 //update document pointer
312 child->setDocument( parent->getDocument() );
313 retVal->setDocument( parent->getDocument() );
314 }
315 return retVal!=NULL;
316 }
317
placeBefore(daeElement * marker,daeElement * parent,daeElement * child,daeUInt * ordinal)318 daeBool daeMetaElement::placeBefore( daeElement *marker, daeElement *parent, daeElement *child, daeUInt *ordinal )
319 {
320 if (child->getMeta()->getIsAbstract() || parent->getMeta() != this ) {
321 return false;
322 }
323 daeUInt ord;
324 daeElement *retVal = _contentModel->placeElement( parent, child, ord, 0, marker, NULL );
325 if ( retVal != NULL ) {
326 //add to _contents array
327 if (_metaContents != NULL) {
328 daeElementRefArray* contents =
329 (daeElementRefArray*)_metaContents->getWritableMemory(parent);
330 daeUIntArray* contentsOrder =
331 (daeUIntArray*)_metaContentsOrder->getWritableMemory(parent);
332 size_t index(0);
333 daeBool validLoc = false;
334 if ( contents->find( marker, index ) == DAE_OK ) {
335 if ( index > 0 ) {
336 daeUInt gt = contentsOrder->get(index-1);
337 daeUInt lt = contentsOrder->get(index);
338 validLoc = gt <= ord && lt >= ord;
339 }
340 else {
341 validLoc = contentsOrder->get(index) >= ord;
342 }
343 }
344 if ( validLoc ) {
345 contents->insertAt( index, retVal );
346 contentsOrder->insertAt( index, ord );
347 if ( ordinal != NULL ) {
348 *ordinal = ord;
349 }
350 }
351 else {
352 _contentModel->removeElement( parent, retVal );
353 retVal = NULL;
354 }
355 }
356 }
357 if ( retVal != NULL ) {
358 //update document pointer
359 child->setDocument( parent->getDocument() );
360 retVal->setDocument( parent->getDocument() );
361 }
362 return retVal!=NULL;
363 }
364
placeAfter(daeElement * marker,daeElement * parent,daeElement * child,daeUInt * ordinal)365 daeBool daeMetaElement::placeAfter( daeElement *marker, daeElement *parent, daeElement *child, daeUInt *ordinal )
366 {
367 if (child->getMeta()->getIsAbstract() || parent->getMeta() != this ) {
368 return false;
369 }
370 daeUInt ord;
371 daeElement *retVal = _contentModel->placeElement( parent, child, ord, 0, NULL, marker );
372 if ( retVal != NULL ) {
373 //add to _contents array
374 if (_metaContents != NULL) {
375 daeElementRefArray* contents =
376 (daeElementRefArray*)_metaContents->getWritableMemory(parent);
377 daeUIntArray* contentsOrder =
378 (daeUIntArray*)_metaContentsOrder->getWritableMemory(parent);
379 size_t index(0);
380 daeBool validLoc = false;
381 if ( contents->find( marker, index ) == DAE_OK ) {
382 if ( index < contentsOrder->getCount()-1 ) {
383 validLoc = contentsOrder->get(index) <= ord && contentsOrder->get(index+1) >= ord;
384 }
385 else {
386 validLoc = contentsOrder->get(index) <= ord;
387 }
388 }
389 if ( validLoc ) {
390 contents->insertAt( index+1, retVal );
391 contentsOrder->insertAt( index+1, ord );
392 if ( ordinal != NULL ) {
393 *ordinal = ord;
394 }
395 }
396 else {
397 _contentModel->removeElement( parent, retVal );
398 retVal = NULL;
399 }
400 }
401 }
402 if ( retVal != NULL ) {
403 //update document pointer
404 child->setDocument( parent->getDocument() );
405 retVal->setDocument( parent->getDocument() );
406 }
407 return retVal!=NULL;
408 }
409
remove(daeElement * parent,daeElement * child)410 daeBool daeMetaElement::remove(daeElement *parent, daeElement *child)
411 {
412 if ( parent->getMeta() != this ) {
413 return false;
414 }
415 //prevent child from being deleted
416 daeElementRef el( child );
417 if ( _contentModel->removeElement( parent, child ) ) {
418 if ( _metaContents != NULL)
419 {
420 daeElementRefArray* contents = (daeElementRefArray*)_metaContents->getWritableMemory(parent);
421 daeUIntArray* contentsOrder = (daeUIntArray*)_metaContentsOrder->getWritableMemory(parent);
422 size_t idx(0);
423 if ( contents->remove(child, &idx) == DAE_OK ) {
424 contentsOrder->removeIndex( idx );
425 }
426 }
427 if ( child->getDocument() ) {
428 child->getDocument()->removeElement( child );
429 }
430
431 // Clear the child's parent pointer
432 child->setParentElement( NULL );
433
434 return true;
435 }
436 return false;
437 }
438
getChildren(daeElement * parent,daeElementRefArray & array)439 void daeMetaElement::getChildren( daeElement* parent, daeElementRefArray &array )
440 {
441 if ( parent->getMeta() != this ) {
442 return;
443 }
444 if ( _metaContents != NULL ) {
445 daeElementRefArray* contents = (daeElementRefArray*)_metaContents->getWritableMemory(parent);
446 for ( size_t x = 0; x < contents->getCount(); x++ ) {
447 array.append( contents->get(x) );
448 }
449 }
450 else if ( _contentModel != NULL ) {
451 _contentModel->getChildren( parent, array );
452 }
453 }
454
455 // daeMetaElementRefArray &daeMetaElement::_metas()
456 // {
457 // if (!mera)
458 // {
459 // mera = new daeMetaElementRefArray();
460 // }
461 // return *mera;
462 // }
463
464 // daeTArray< daeMetaElement** > &daeMetaElement::_classMetaPointers()
465 // {
466 // if (!mes)
467 // {
468 // mes = new daeTArray< daeMetaElement** >();
469 // }
470 // return *mes;
471 // }
472
473