- Main Page
- Related Pages
- Modules
- Classes
- Files

# SchemaCollection.h

Go to the documentation of this file.

    00001 #ifndef _SCHEMACOLLECTION_H_
    00002 #define _SCHEMACOLLECTION_H_
    00003
    00004 //
    00005 // Copyright (C) 2004-2006  Autodesk, Inc.
    00006 //
    00007 // This library is free software; you can redistribute it and/or
    00008 // modify it under the terms of version 2.1 of the GNU Lesser
    00009 // General Public License as published by the Free Software Foundation.
    00010 //
    00011 // This library is distributed in the hope that it will be useful,
    00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
    00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00014 // Lesser General Public License for more details.
    00015 //
    00016 // You should have received a copy of the GNU Lesser General Public
    00017 // License along with this library; if not, write to the Free Software
    00018 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    00019 //
    00020
    00021 #ifdef _WIN32
    00022 #pragma once
    00023 #endif
    00024
    00025 #include <FdoStd.h>
    00026 #include <Common/NamedCollection.h>
    00027 #include <Fdo/Schema/SchemaElement.h>
    00028 #include <Fdo/Schema/SchemaException.h>
    00029
    00030 /// \brief
    00031 /// FdoSchemaCollection is an abstract template class that is used to
    00032 /// define schema collections; FdoClassCollection, FdoDatapropertyDefinitionCollection,
    00033 /// FdoFeatureClassCollection, FdoFeatureSchemaCollection, FdoPropertyDefinitionCollection, and
    00034 /// FdoRelationCollection.
    00035 template <class OBJ> class FdoSchemaCollection : public FdoNamedCollection<OBJ, FdoSchemaException>
    00036 {
    00037
    00038 /// \cond DOXYGEN-IGNORE
    00039 protected:
    00040     FdoSchemaCollection()
    00041     {
    00042     }
    00043
    00044     FdoSchemaCollection(FdoSchemaElement* parent) : FdoNamedCollection<OBJ, FdoSchemaException>()
    00045     {
    00046         m_parent = parent;
    00047         m_changeInfoState = 0;
    00048         m_listCHANGED = NULL;
    00049         m_sizeCHANGED = 0;
    00050         if ( m_parent )
    00051             m_setItemParent = true;
    00052         else
    00053             m_setItemParent = false;
    00054     }
    00055
    00056     virtual ~FdoSchemaCollection()
    00057     {
    00058         if (m_setItemParent && m_parent)
    00059         {
    00060             for(FdoInt32 i = 0; i < FdoNamedCollection<OBJ, FdoSchemaException>::GetCount(); i++)
    00061             {
    00062                 OBJ*    pitem = FdoNamedCollection<OBJ, FdoSchemaException>::GetItem(i);
    00063
    00064             /// When the collection disappears, the ownership does too.
    00065             /// So NULL out the parent.  This is necessary because the
    00066             /// parent reference within items is not refcounted to avoid
    00067             /// circular references/memory leaks.
    00068             ///
    00069             /// \warning
    00070             /// The pitem->GetParent() should always equal m_parent, but we cannot verify this
    00071             /// because the call to pitem->GetParent() might AddRef() an item that has already
    00072             /// been disposed.  So we just NULL it out.
    00073             ///
    00074                 pitem->SetParent(NULL);
    00075                 FDO_SAFE_RELEASE(pitem);
    00076             }
    00077         }
    00078
    00079         /// Dispose of change information
    00080         if (m_listCHANGED)
    00081         {
    00082             for (FdoInt32 i=0; i < m_sizeCHANGED; i++)
    00083             {
    00084                 FDO_SAFE_RELEASE(m_listCHANGED[i]);
    00085             }
    00086             delete [] m_listCHANGED;
    00087             m_listCHANGED = NULL;
    00088         }
    00089     }
    00090 /// \endcond
    00091
    00092 public:
    00093     /// \brief
    00094     /// Sets the item in the collection at the specified index to the specified value. Throws an invalid argument exception if the index is out of range.
    00095     ///
    00096     /// \param index
    00097     /// Input index
    00098     /// \param value
    00099     /// Input value
    00100     ///
    00101     /// \return
    00102     /// Returns nothing
    00103     ///
    00104     FDO_API virtual void SetItem(FdoInt32 index, OBJ* value)
    00105     {
    00106         if (index < FdoNamedCollection<OBJ, FdoSchemaException>::GetCount() && index >= 0)   // verify index is in bounds
    00107         {
    00108             if (m_setItemParent && m_parent)
    00109             {
    00110             /// Validate parentage for object to add.  Membership in a
    00111             /// collection implys parentage, and a object can only have
    00112             /// one parent.
    00113             ///
    00114                 FdoSchemaElement*   pparent = value->GetParent();
    00115                 if (pparent)
    00116                 {
    00117                 /// OK, just restoring collection.
    00118                     if (pparent == m_parent && (m_changeInfoState & CHANGEINFO_PROCESSING))
    00119                         pparent->Release();
    00120                     else
    00121                     {
    00122                         pparent->Release();
    00123                         throw FdoSchemaException::Create(FdoException::NLSGetMessage(FDO_NLSID(SCHEMA_10_OBJECTHASPARENT)));
    00124                     }
    00125                 }
    00126             }
    00127             _StartChanges();
    00128
    00129             if (m_setItemParent && m_parent)
    00130                 value->SetParent(m_parent);
    00131             /// Adding to a non-owning class does not change the state.
    00132             /// \warning
    00133             /// Do not change states during Accept/RejectChanges.
    00134             ///
    00135             if (m_setItemParent
    00136                 && !(m_changeInfoState & CHANGEINFO_PROCESSING))
    00137             {
    00138                 value->SetElementState(FdoSchemaElementState_Added);
    00139             }
    00140
    00141             OBJ*    pitemOld = FdoNamedCollection<OBJ, FdoSchemaException>::GetItem(index);
    00142             FdoSchemaElement*   pparentOldItem = pitemOld->GetParent();
    00143             if ( pparentOldItem == m_parent )
    00144             {
    00145             /// When an object is removed from a collection, that
    00146             /// collection's owner is no longer the object's
    00147             /// parent.
    00148             ///
    00149                 pitemOld->SetParent(NULL);
    00150                 pitemOld->SetElementState(FdoSchemaElementState_Detached);
    00151             }
    00152             FDO_SAFE_RELEASE(pparentOldItem);
    00153             FDO_SAFE_RELEASE(pitemOld);
    00154         }
    00155
    00156         FdoNamedCollection<OBJ, FdoSchemaException>::SetItem(index, value);
    00157     }
    00158
    00159     /// \brief
    00160     /// Adds the specified item to the end of the collection. Returns the index of the newly added item.
    00161     ///
    00162     /// \param value
    00163     /// Input value
    00164     ///
    00165     /// \return
    00166     /// Returns the index of the newly added item
    00167     ///
    00168     FDO_API virtual FdoInt32 Add(OBJ* value)
    00169     {
    00170         if (m_setItemParent && m_parent)
    00171         {
    00172         /// Validate parentage for object to add.  Membership in a
    00173         /// collection implys parentage, and a object can only have
    00174         /// one parent.
    00175         ///
    00176             FdoSchemaElement*   pparent = value->GetParent();
    00177             if (pparent)
    00178             {
    00179                 if (pparent == m_parent && (m_changeInfoState & CHANGEINFO_PROCESSING))
    00180                     pparent->Release(); // OK, just restoring collection
    00181                 else
    00182                 {
    00183                     pparent->Release();
    00184                     throw FdoSchemaException::Create(FdoException::NLSGetMessage(FDO_NLSID(SCHEMA_10_OBJECTHASPARENT)));
    00185                 }
    00186             }
    00187         }
    00188         _StartChanges();
    00189
    00190         if (m_setItemParent && m_parent)
    00191             value->SetParent(m_parent);
    00192         /// Adding to a non-owning class does not change the state.
    00193         /// \warning
    00194         /// Do not change states during Accept/RejectChanges.
    00195         ///
    00196         if (m_setItemParent
    00197             && !(m_changeInfoState & CHANGEINFO_PROCESSING))
    00198         {
    00199             value->SetElementState(FdoSchemaElementState_Added);
    00200         }
    00201         return FdoNamedCollection<OBJ, FdoSchemaException>::Add(value);
    00202     }
    00203
    00204     /// \brief
    00205     /// Inserts the specified item at the specified index within the collection.
    00206     /// Items following the insertion point are moved down to accommodate the new item.
    00207     /// Throws an invalid argument exception if the specified index is out of range.
    00208     ///
    00209     /// \param index
    00210     /// Input index
    00211     /// \param value
    00212     /// Input value
    00213     ///
    00214     /// \return
    00215     /// Returns nothing
    00216     ///
    00217     FDO_API virtual void Insert(FdoInt32 index, OBJ* value)
    00218     {
    00219         if (m_setItemParent && m_parent)
    00220         {
    00221         /// Validate parentage for object to add.  Membership in a
    00222         /// collection implys parentage, and a object can only have
    00223         /// one parent.
    00224         ///
    00225             FdoSchemaElement*   pparent = value->GetParent();
    00226             if (pparent)
    00227             {
    00228             /// OK, just restoring collection.
    00229                 if (pparent == m_parent && (m_changeInfoState & CHANGEINFO_PROCESSING))
    00230                     pparent->Release();
    00231                 else
    00232                 {
    00233                     pparent->Release();
    00234                     throw FdoSchemaException::Create(FdoException::NLSGetMessage(FDO_NLSID(SCHEMA_10_OBJECTHASPARENT)));
    00235                 }
    00236             }
    00237         }
    00238         _StartChanges();
    00239
    00240         if (m_setItemParent && m_parent)
    00241             value->SetParent(m_parent);
    00242         /// Adding to a non-owning class does not change the state.
    00243         /// \warning
    00244         /// Do not change states during Accept/RejectChanges.
    00245         ///
    00246         if (m_setItemParent
    00247             && !(m_changeInfoState & CHANGEINFO_PROCESSING))
    00248         {
    00249             value->SetElementState(FdoSchemaElementState_Added);
    00250         }
    00251         FdoNamedCollection<OBJ, FdoSchemaException>::Insert(index, value);
    00252     }
    00253
    00254     /// \brief
    00255     /// Removes all items from the collection.
    00256     ///
    00257     /// \return
    00258     /// Returns nothing
    00259     ///
    00260     FDO_API virtual void Clear()
    00261     {
    00262         _StartChanges();
    00263
    00264         if (m_setItemParent && m_parent)
    00265         {
    00266             for(FdoInt32 i = 0; i < FdoNamedCollection<OBJ, FdoSchemaException>::GetCount(); i++)
    00267             {
    00268                 OBJ*    pitem = FdoNamedCollection<OBJ, FdoSchemaException>::GetItem(i);
    00269                 FdoSchemaElement*   pparent = pitem->GetParent();
    00270
    00271                 if ( pparent == m_parent )
    00272                 {
    00273                 /// When an object is removed from a collection, that
    00274                 /// collection's owner is no longer the object's
    00275                 /// parent.
    00276                 ///
    00277                     pitem->SetParent(NULL);
    00278                     pitem->SetElementState(FdoSchemaElementState_Detached);
    00279                 }
    00280
    00281                 FDO_SAFE_RELEASE(pparent);
    00282                 FDO_SAFE_RELEASE(pitem);
    00283             }
    00284         }
    00285
    00286         FdoNamedCollection<OBJ, FdoSchemaException>::Clear();
    00287     }
    00288
    00289     /// \brief
    00290     /// Removes the specified item from the collection. Throws an invalid argument exception if the item does not exist within the collection.
    00291     ///
    00292     /// \param value
    00293     /// Input value
    00294     ///
    00295     /// \return
    00296     /// Returns nothing
    00297     ///
    00298     FDO_API virtual void Remove(const OBJ* value)
    00299     {
    00300         _StartChanges();
    00301
    00302         if (m_setItemParent && m_parent)
    00303         {
    00304         /// Cast drops const.
    00305             OBJ*    pitem = (OBJ*)value;
    00306             FdoSchemaElement*   pparent = pitem->GetParent();
    00307
    00308             if ( pparent == m_parent )
    00309             {
    00310             /// When an object is removed from a collection, that
    00311             /// collection's owner is no longer the object's
    00312             /// parent.
    00313             ///
    00314                 pitem->SetParent(NULL);
    00315                 pitem->SetElementState(FdoSchemaElementState_Detached);
    00316             }
    00317
    00318             FDO_SAFE_RELEASE(pparent);
    00319         }
    00320
    00321         FdoNamedCollection<OBJ, FdoSchemaException>::Remove(value);
    00322     }
    00323
    00324     /// \brief
    00325     /// Removes the specified item from the collection. Throws an invalid argument exception if the item does not exist within the collection.
    00326     ///
    00327     /// \param index
    00328     /// Input index
    00329     ///
    00330     /// \return
    00331     /// Returns nothing
    00332     ///
    00333     FDO_API virtual void RemoveAt(FdoInt32 index)
    00334     {
    00335         _StartChanges();
    00336
    00337         if (m_setItemParent && m_parent)
    00338         {
    00339             OBJ*    pitem = FdoNamedCollection<OBJ, FdoSchemaException>::GetItem(index);
    00340             FdoSchemaElement*   pparent = pitem->GetParent();
    00341
    00342             if ( pparent == m_parent )
    00343             {
    00344             /// When an object is removed from a collection, that
    00345             /// collection's owner is no longer the object's
    00346             /// parent.
    00347             ///
    00348                 pitem->SetParent(NULL);
    00349                 pitem->SetElementState(FdoSchemaElementState_Detached);
    00350             }
    00351
    00352             FDO_SAFE_RELEASE(pparent);
    00353             FDO_SAFE_RELEASE(pitem);
    00354         }
    00355
    00356         FdoNamedCollection<OBJ, FdoSchemaException>::RemoveAt(index);
    00357     }
    00358
    00359 /// \cond DOXYGEN-IGNORE
    00360 protected:
    00361     /// States stored in the m_changeInfoState bitfield flag
    00362     static const unsigned int   CHANGEINFO_PRESENT      = 0x00000001;
    00363     static const unsigned int   CHANGEINFO_PROCESSING   = 0x00000002;
    00364     static const unsigned int   CHANGEINFO_PROCESSED    = 0x00000004;
    00365
    00366     FdoSchemaElement*   m_parent;
    00367     bool                m_setItemParent;
    00368
    00369     /// FdoFeatureSchema::RejectChanges() support
    00370     FdoByte             m_changeInfoState;
    00371     OBJ**               m_listCHANGED;
    00372     FdoInt32            m_sizeCHANGED;
    00373
    00374     virtual void _StartChanges()
    00375     {
    00376         if (!(m_changeInfoState & (CHANGEINFO_PRESENT|CHANGEINFO_PROCESSING)))
    00377         {
    00378             m_sizeCHANGED = FdoNamedCollection<OBJ, FdoSchemaException>::GetCount();
    00379
    00380             if (m_sizeCHANGED > 0)
    00381             {
    00382                 m_listCHANGED = new OBJ*[m_sizeCHANGED];
    00383                 for (FdoInt32 i=0; i < m_sizeCHANGED; i++)
    00384                 {
    00385                     m_listCHANGED[i] = FdoNamedCollection<OBJ, FdoSchemaException>::GetItem(i);
    00386                 }
    00387             }
    00388
    00389             m_changeInfoState |= CHANGEINFO_PRESENT;
    00390
    00391             if (m_parent)
    00392                 m_parent->SetElementState(FdoSchemaElementState_Modified);
    00393         }
    00394     }
    00395
    00396     virtual void _AcceptChanges()
    00397     {
    00398     /// Already processed.
    00399         if (m_changeInfoState & CHANGEINFO_PROCESSED)
    00400             return;
    00401         m_changeInfoState |= CHANGEINFO_PROCESSED;
    00402
    00403         if (m_changeInfoState & CHANGEINFO_PRESENT)
    00404         {
    00405         /// Reset.
    00406             for (FdoInt32 i=0; i < m_sizeCHANGED; i++)
    00407             {
    00408             /// Accept changes to items once in this collection.
    00409                 m_listCHANGED[i]->_AcceptChanges();
    00410
    00411             /// Release from change list.
    00412                 FDO_SAFE_RELEASE(m_listCHANGED[i]);
    00413             }
    00414             delete [] m_listCHANGED;
    00415             m_listCHANGED = NULL;
    00416             m_sizeCHANGED = 0;
    00417         }
    00418
    00419         /// Accept changes to items currently in this collection.
    00420         for (FdoInt32 i=0; i < FdoNamedCollection<OBJ, FdoSchemaException>::GetCount(); i++)
    00421         {
    00422             FdoPtr<OBJ>    pitem = FdoNamedCollection<OBJ, FdoSchemaException>::GetItem(i);
    00423
    00424             if (pitem->GetElementState() == FdoSchemaElementState_Deleted)
    00425             {
    00426             /// Really remove items marked for deletion.
    00427                 RemoveAt(i);
    00428                 i--;
    00429             }
    00430
    00431             pitem->_AcceptChanges();
    00432         }
    00433     }
    00434
    00435     virtual void _RejectChanges()
    00436     {
    00437         /// Already processed.
    00438         if (m_changeInfoState & CHANGEINFO_PROCESSED)
    00439             return;
    00440         m_changeInfoState |= CHANGEINFO_PROCESSED;
    00441
    00442         if (m_changeInfoState & CHANGEINFO_PRESENT)
    00443         {
    00444         /// Restore.
    00445
    00446         /// Reject changes to items currently in this collection.
    00447             for (FdoInt32 i=0; i < FdoNamedCollection<OBJ, FdoSchemaException>::GetCount(); i++)
    00448             {
    00449                 OBJ*    pitem = FdoNamedCollection<OBJ, FdoSchemaException>::GetItem(i);
    00450                 pitem->_RejectChanges();
    00451                 FDO_SAFE_RELEASE(pitem);
    00452             }
    00453
    00454             FdoNamedCollection<OBJ, FdoSchemaException>::Clear();
    00455             for (FdoInt32 iChanged=0; iChanged < m_sizeCHANGED; iChanged++)
    00456             {
    00457                 Add(m_listCHANGED[iChanged]);
    00458                 FDO_SAFE_RELEASE(m_listCHANGED[iChanged]);
    00459             }
    00460
    00461             /// Reset.
    00462             delete [] m_listCHANGED;
    00463             m_listCHANGED = NULL;
    00464             m_sizeCHANGED = 0;
    00465         }
    00466
    00467         /// Reject changes to items now in this collection.
    00468         for (FdoInt32 i=0; i < FdoNamedCollection<OBJ, FdoSchemaException>::GetCount(); i++)
    00469         {
    00470             OBJ*    pitem = FdoNamedCollection<OBJ, FdoSchemaException>::GetItem(i);
    00471             pitem->_RejectChanges();
    00472             FDO_SAFE_RELEASE(pitem);
    00473         }
    00474     }
    00475
    00476     virtual void _BeginChangeProcessing()
    00477     {
    00478         /// Already marked for processing.
    00479         if (m_changeInfoState & CHANGEINFO_PROCESSING)
    00480             return;
    00481
    00482         m_changeInfoState |= CHANGEINFO_PROCESSING;
    00483
    00484         for (FdoInt32 i=0; i < FdoNamedCollection<OBJ, FdoSchemaException>::GetCount(); i++)
    00485         {
    00486             OBJ*    pitem = FdoNamedCollection<OBJ, FdoSchemaException>::GetItem(i);
    00487             pitem->_BeginChangeProcessing();
    00488             FDO_SAFE_RELEASE(pitem);
    00489         }
    00490     }
    00491
    00492     virtual void _EndChangeProcessing()
    00493     {
    00494         /// Processing flag already cleared.
    00495         if (!(m_changeInfoState & CHANGEINFO_PROCESSING))
    00496             return;
    00497
    00498         for (FdoInt32 i=0; i < FdoNamedCollection<OBJ, FdoSchemaException>::GetCount(); i++)
    00499         {
    00500             OBJ*    pitem = FdoNamedCollection<OBJ, FdoSchemaException>::GetItem(i);
    00501             pitem->_EndChangeProcessing();
    00502             FDO_SAFE_RELEASE(pitem);
    00503         }
    00504
    00505         m_changeInfoState = 0;
    00506     }
    00507 /// \endcond
    00508 };
    00509 #endif
    00510
    00511

Please send us your comment about this page