/* * Copyright 2006 Sony Computer Entertainment Inc. * * Licensed under the MIT Open Source License, for details please see license.txt or the website * http://www.opensource.org/licenses/mit-license.php * */ #include <dae.h> #include <dae/daeMetaElement.h> #include <dae/daeElement.h> #include <dae/daeDocument.h> #include <dae/domAny.h> #include <dae/daeMetaCMPolicy.h> #include <dae/daeMetaElementAttribute.h> daeElementRef daeMetaElement::create() { daeElementRef ret = (*_createFunc)(dae); ret->setup(this); return ret; } daeElementRef daeMetaElement::create(daeString s) { daeMetaElement* me = NULL; if ( strcmp( s, _name ) == 0 ) { //looking for this meta me = this; } else if ( _contentModel != NULL ) { me = _contentModel->findChild(s); } if (me != NULL) { daeElementRef ret = me->create(); if ( strcmp(s, me->getName() ) != 0 ) { ret->setElementName(s); } return ret; } if ( getAllowsAny() ) { daeElementRef ret = domAny::registerElement(dae)->create(); ret->setElementName(s); return ret; } return NULL; } daeMetaElement::daeMetaElement(DAE& dae) : dae(dae) { _name = "noname"; _createFunc = NULL; _elementSize = sizeof(daeElement); _metaValue = NULL; _metaContents = NULL; _metaContentsOrder = NULL; // sthomas _metaID = NULL; _isTrackableForQueries = true; _usesStringContents = false; _isTransparent = false; _isAbstract = false; _allowsAny = false; _innerClass = false; _contentModel = NULL; _metaCMData = NULL; _numMetaChoices = 0; } daeMetaElement::~daeMetaElement() { delete _metaContents; delete _contentModel; delete _metaContentsOrder; delete _metaCMData; } DAE* daeMetaElement::getDAE() { return &dae; } void daeMetaElement::setCMRoot( daeMetaCMPolicy *cm ) { if (_contentModel) delete _contentModel; _contentModel = cm; } void daeMetaElement::addContents(daeInt offset) { daeMetaElementArrayAttribute* meaa = new daeMetaElementArrayAttribute( this, NULL, 0, 1, -1 ); meaa->setType(dae.getAtomicTypes().get("element")); meaa->setName("contents"); meaa->setOffset(offset); meaa->setContainer( this); _metaContents = meaa; } void daeMetaElement::addContentsOrder(daeInt offset) { daeMetaArrayAttribute* meaa = new daeMetaArrayAttribute(); meaa->setType(dae.getAtomicTypes().get("uint")); meaa->setName("contentsOrder"); meaa->setOffset(offset); meaa->setContainer( this); if (_metaContentsOrder) delete _metaContentsOrder; _metaContentsOrder = meaa; } void daeMetaElement::addCMDataArray(daeInt offset, daeUInt numChoices) { daeMetaArrayAttribute* meaa = new daeMetaArrayAttribute(); meaa->setType(dae.getAtomicTypes().get("int")); meaa->setName("CMData"); meaa->setOffset(offset); meaa->setContainer( this); if (_metaCMData) delete _metaCMData; _metaCMData = meaa; _numMetaChoices = numChoices; } /*void daeMetaElement::appendArrayElement(daeMetaElement* element, daeInt offset, daeString name) { daeMetaElementArrayAttribute* meaa = new daeMetaElementArrayAttribute; meaa->setType(daeAtomicType::get("element")); if ( name ) { meaa->setName(name); } else { meaa->setName(element->getName()); } meaa->setOffset(offset); meaa->setContainer(this); meaa->setElementType( element); _metaElements.append(meaa); } void daeMetaElement::appendElement(daeMetaElement* element, daeInt offset, daeString name) { daeMetaElementAttribute* meaa = new daeMetaElementAttribute; meaa->setType(daeAtomicType::get("element")); if ( name ) { meaa->setName(name); } else { meaa->setName(element->getName()); } meaa->setOffset( offset); meaa->setContainer( this ); meaa->setElementType( element ); _metaElements.append(meaa); }*/ void daeMetaElement::appendAttribute(daeMetaAttribute* attr) { if (attr == NULL) return; if (strcmp(attr->getName(),"_value") == 0) { _metaValue = attr; } else _metaAttributes.append(attr); if ((attr->getName() != NULL) && (strcmp(attr->getName(),"id") == 0)) { _metaID = attr; _isTrackableForQueries = true; } } void daeMetaElement::validate() { if (_elementSize == 0) { daeInt place=0; unsigned int i; for(i=0;i<_metaAttributes.getCount();i++) { place += _metaAttributes[i]->getSize(); int align = _metaAttributes[i]->getAlignment(); place += align; place &= (~(align-1)); } _elementSize = place; } } daeMetaAttribute* daeMetaElement::getMetaAttribute(daeString s) { int cnt = (int)_metaAttributes.getCount(); int i; for(i=0;i<cnt;i++) if (strcmp(_metaAttributes[i]->getName(),s) == 0) return _metaAttributes[i]; return NULL; } // void daeMetaElement::releaseMetas() // { // _metas().clear(); // size_t count = _classMetaPointers().getCount(); // for ( size_t i = 0; i < count; i++ ) // { // *(_classMetaPointers()[i]) = NULL; // } // _classMetaPointers().clear(); // if (mera) // { // delete mera; // mera = NULL; // } // if (mes) // { // delete mes; // mes = NULL; // } // } daeBool daeMetaElement::place(daeElement *parent, daeElement *child, daeUInt *ordinal ) { if (child->getMeta()->getIsAbstract() || parent->getMeta() != this ) { return false; } daeUInt ord; daeElement *retVal = _contentModel->placeElement( parent, child, ord ); if ( retVal != NULL ) { //update document pointer child->setDocument( parent->getDocument() ); retVal->setDocument( parent->getDocument() ); //add to _contents array if (_metaContents != NULL) { daeElementRefArray* contents = (daeElementRefArray*)_metaContents->getWritableMemory(parent); daeUIntArray* contentsOrder = (daeUIntArray*)_metaContentsOrder->getWritableMemory(parent); daeBool needsAppend = true; size_t cnt = contentsOrder->getCount(); for ( size_t x = 0; x < cnt; x++ ) { if ( contentsOrder->get(x) > ord ) { contents->insertAt( x, retVal ); contentsOrder->insertAt( x, ord ); needsAppend = false; break; } } if ( needsAppend ) { contents->append(retVal); contentsOrder->append( ord ); } } if ( ordinal != NULL ) { *ordinal = ord; } } return retVal!=NULL; } daeBool daeMetaElement::placeAt( daeInt index, daeElement *parent, daeElement *child ) { if (child->getMeta()->getIsAbstract() || parent->getMeta() != this || index < 0 ) { return false; } daeUInt ord; daeElement *retVal = _contentModel->placeElement( parent, child, ord ); if ( retVal != NULL ) { //add to _contents array if (_metaContents != NULL) { daeElementRefArray* contents = (daeElementRefArray*)_metaContents->getWritableMemory(parent); daeUIntArray* contentsOrder = (daeUIntArray*)_metaContentsOrder->getWritableMemory(parent); daeBool validLoc; if ( index > 0 ) { validLoc = contentsOrder->get(index) >= ord && contentsOrder->get(index) <= ord; } else { if ( contentsOrder->getCount() == 0 ) { validLoc = true; } else { validLoc = contentsOrder->get(index) >= ord; } } if ( validLoc ) { contents->insertAt( index, retVal ); contentsOrder->insertAt( index, ord ); } else { _contentModel->removeElement( parent, retVal ); retVal = NULL; } } } if ( retVal != NULL ) { //update document pointer child->setDocument( parent->getDocument() ); retVal->setDocument( parent->getDocument() ); } return retVal!=NULL; } daeBool daeMetaElement::placeBefore( daeElement *marker, daeElement *parent, daeElement *child, daeUInt *ordinal ) { if (child->getMeta()->getIsAbstract() || parent->getMeta() != this ) { return false; } daeUInt ord; daeElement *retVal = _contentModel->placeElement( parent, child, ord, 0, marker, NULL ); if ( retVal != NULL ) { //add to _contents array if (_metaContents != NULL) { daeElementRefArray* contents = (daeElementRefArray*)_metaContents->getWritableMemory(parent); daeUIntArray* contentsOrder = (daeUIntArray*)_metaContentsOrder->getWritableMemory(parent); size_t index(0); daeBool validLoc = false; if ( contents->find( marker, index ) == DAE_OK ) { if ( index > 0 ) { daeUInt gt = contentsOrder->get(index-1); daeUInt lt = contentsOrder->get(index); validLoc = gt <= ord && lt >= ord; } else { validLoc = contentsOrder->get(index) >= ord; } } if ( validLoc ) { contents->insertAt( index, retVal ); contentsOrder->insertAt( index, ord ); if ( ordinal != NULL ) { *ordinal = ord; } } else { _contentModel->removeElement( parent, retVal ); retVal = NULL; } } } if ( retVal != NULL ) { //update document pointer child->setDocument( parent->getDocument() ); retVal->setDocument( parent->getDocument() ); } return retVal!=NULL; } daeBool daeMetaElement::placeAfter( daeElement *marker, daeElement *parent, daeElement *child, daeUInt *ordinal ) { if (child->getMeta()->getIsAbstract() || parent->getMeta() != this ) { return false; } daeUInt ord; daeElement *retVal = _contentModel->placeElement( parent, child, ord, 0, NULL, marker ); if ( retVal != NULL ) { //add to _contents array if (_metaContents != NULL) { daeElementRefArray* contents = (daeElementRefArray*)_metaContents->getWritableMemory(parent); daeUIntArray* contentsOrder = (daeUIntArray*)_metaContentsOrder->getWritableMemory(parent); size_t index(0); daeBool validLoc = false; if ( contents->find( marker, index ) == DAE_OK ) { if ( index < contentsOrder->getCount()-1 ) { validLoc = contentsOrder->get(index) <= ord && contentsOrder->get(index+1) >= ord; } else { validLoc = contentsOrder->get(index) <= ord; } } if ( validLoc ) { contents->insertAt( index+1, retVal ); contentsOrder->insertAt( index+1, ord ); if ( ordinal != NULL ) { *ordinal = ord; } } else { _contentModel->removeElement( parent, retVal ); retVal = NULL; } } } if ( retVal != NULL ) { //update document pointer child->setDocument( parent->getDocument() ); retVal->setDocument( parent->getDocument() ); } return retVal!=NULL; } daeBool daeMetaElement::remove(daeElement *parent, daeElement *child) { if ( parent->getMeta() != this ) { return false; } //prevent child from being deleted daeElementRef el( child ); if ( _contentModel->removeElement( parent, child ) ) { if ( _metaContents != NULL) { daeElementRefArray* contents = (daeElementRefArray*)_metaContents->getWritableMemory(parent); daeUIntArray* contentsOrder = (daeUIntArray*)_metaContentsOrder->getWritableMemory(parent); size_t idx(0); if ( contents->remove(child, &idx) == DAE_OK ) { contentsOrder->removeIndex( idx ); } } if ( child->getDocument() ) { child->getDocument()->removeElement( child ); } // Clear the child's parent pointer child->setParentElement( NULL ); return true; } return false; } void daeMetaElement::getChildren( daeElement* parent, daeElementRefArray &array ) { if ( parent->getMeta() != this ) { return; } if ( _metaContents != NULL ) { daeElementRefArray* contents = (daeElementRefArray*)_metaContents->getWritableMemory(parent); for ( size_t x = 0; x < contents->getCount(); x++ ) { array.append( contents->get(x) ); } } else if ( _contentModel != NULL ) { _contentModel->getChildren( parent, array ); } } // daeMetaElementRefArray &daeMetaElement::_metas() // { // if (!mera) // { // mera = new daeMetaElementRefArray(); // } // return *mera; // } // daeTArray< daeMetaElement** > &daeMetaElement::_classMetaPointers() // { // if (!mes) // { // mes = new daeTArray< daeMetaElement** >(); // } // return *mes; // }