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/daeMetaCMPolicy.h>
14 #include <dae/daeMetaElementAttribute.h>
15 #include <dae/daeDom.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 = registerElementAny(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