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

# IdentifierCollection.h

Go to the documentation of this file.

    00001 #ifndef _IDENTIFIERCOLLECTION_H_
    00002 #define _IDENTIFIERCOLLECTION_H_
    00003 //
    00004
    00005 //
    00006 // Copyright (C) 2004-2006  Autodesk, Inc.
    00007 //
    00008 // This library is free software; you can redistribute it and/or
    00009 // modify it under the terms of version 2.1 of the GNU Lesser
    00010 // General Public License as published by the Free Software Foundation.
    00011 //
    00012 // This library is distributed in the hope that it will be useful,
    00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
    00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00015 // Lesser General Public License for more details.
    00016 //
    00017 // You should have received a copy of the GNU Lesser General Public
    00018 // License along with this library; if not, write to the Free Software
    00019 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    00020 //
    00021
    00022 #ifdef _WIN32
    00023 #pragma once
    00024 #endif
    00025
    00026 #include <FdoStd.h>
    00027 #include <Fdo/Expression/Identifier.h>
    00028 #include <Fdo/Commands/CommandException.h>
    00029
    00030 /// \brief
    00031 /// The FdoIdentifierCollection class represents a collection of FdoIdentifier objects.
    00032 class FdoIdentifierCollection : public FdoCollection<FdoIdentifier, FdoCommandException>
    00033 {
    00034 /// \cond DOXYGEN-IGNORE
    00035 protected:
    00036     virtual void Dispose();
    00037 /// \endcond
    00038
    00039 public:
    00040     /// \brief
    00041     /// Constructs a default empty instance of an FdoIdentifierCollection.
    00042     ///
    00043     /// \return
    00044     /// Returns nothing
    00045     ///
    00046     FDO_API static FdoIdentifierCollection* Create();
    00047
    00048
    00049     /// \brief
    00050     /// Gets the item in the collection at the specified index. Throws an invalid argument exception if the index is out of range.
    00051     ///
    00052     /// \param index
    00053     /// Input index
    00054     ///
    00055     /// \return
    00056     /// Returns the item in the collection at the specified index
    00057     ///
    00058     FDO_API FdoIdentifier* GetItem(FdoInt32 index)
    00059     {
    00060         return FdoCollection<FdoIdentifier, FdoCommandException>::GetItem(index);
    00061     }
    00062
    00063     /// \brief
    00064     /// Gets the item in the collection with the specified name. Throws an exception if the item is not found.
    00065     ///
    00066     /// \param name
    00067     /// Input item name
    00068     ///
    00069     /// \return
    00070     /// Returns the item in the collection with the specified name
    00071     ///
    00072     FDO_API FdoIdentifier* GetItem(const wchar_t* name)
    00073     {
    00074         FdoIdentifier* item = FindItem( name );
    00075         if ( !item )
    00076             throw FdoCommandException::Create(
    00077                 FdoException::NLSGetMessage(
    00078                     FDO_NLSID(FDO_38_ITEMNOTFOUND),
    00079                     name
    00080                 )
    00081             );
    00082
    00083         return(item);
    00084     }
    00085
    00086
    00087     /// \brief
    00088     /// Finds the item in the collection with the specified name.
    00089     ///
    00090     /// \param name
    00091     /// Input item name
    00092     ///
    00093     /// \return
    00094     /// Returns the item in the collection with the specified name.
    00095     /// Returns NULL if the item was not found.
    00096     ///
    00097     FDO_API FdoIdentifier* FindItem(const wchar_t* name)
    00098     {
    00099     // trigger the building of a map when the collection reaches the threshold size.
    00100         ((FdoIdentifierCollection*) this)->InitMap();
    00101
    00102         FdoIdentifier* obj = NULL;
    00103
    00104         if ( mpNameMap ) {
    00105     // Accessing the map is faster for large collections, so use it if built.
    00106             obj = GetMap(name);
    00107
    00108     // If the object name can't be modified then we're done.
    00109     // Otherwise, there's a chance the object name was modified,
    00110     // meaning that it can be in the collection but not the map,
    00111     // or in the wrong place in the map.
    00112     /*  FdoIdentifier supports SetText() so we have to assume the text might have changed
    00113             if ( (obj != NULL) && !obj->CanSetName() )
    00114                 return(obj);
    00115     */
    00116
    00117     // If the found object's name is the same as the given name
    00118     // then we're done. Otherwise, this object's name has changed
    00119     // and a linear search is needed to find the requested object.
    00120             if ( (obj != NULL) && (Compare(obj->GetText(), name) != 0) )
    00121                 FDO_SAFE_RELEASE( obj );
    00122         }
    00123
    00124         if ( obj == NULL ) {
    00125     // No map so do linear search.
    00126             for ( FdoInt32 i = 0; i < FdoCollection<FdoIdentifier, FdoCommandException>::GetCount(); i++ ) {
    00127                 FdoIdentifier* obj = GetItem(i);
    00128
    00129                 if ( Compare(name, obj->GetText()) == 0 )
    00130                     return(obj);
    00131
    00132                 FDO_SAFE_RELEASE(obj);
    00133             }
    00134         }
    00135
    00136         return (obj);
    00137     }
    00138
    00139     /// \brief
    00140     /// 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.
    00141     ///
    00142     /// \param index
    00143     /// Input index
    00144     /// \param value
    00145     /// Input value
    00146     ///
    00147     /// \return
    00148     /// Returns nothing
    00149     ///
    00150     virtual void SetItem(FdoInt32 index, FdoIdentifier* value)
    00151     {
    00152         CheckDuplicate( value, index );
    00153
    00154     // Remove the old item from the map
    00155         if ( mpNameMap )
    00156             RemoveMapAt(index);
    00157
    00158     // Add the new item to the map
    00159         if ( mpNameMap && value )
    00160             InsertMap( value );
    00161
    00162     // Set the new item in the collection.
    00163         FdoCollection<FdoIdentifier, FdoCommandException>::SetItem(index, value);
    00164     }
    00165
    00166     /// \brief
    00167     /// Adds the specified item to the end of the collection. Returns the index of the newly added item.
    00168     ///
    00169     /// \param value
    00170     /// Input value
    00171     ///
    00172     /// \return
    00173     /// Returns the index of the newly added item
    00174     ///
    00175     virtual FdoInt32 Add( FdoIdentifier* value)
    00176     {
    00177         CheckDuplicate( value, -1 );
    00178
    00179     // Insert the new item in the map
    00180         if ( mpNameMap && value ) {
    00181             InsertMap(value);
    00182         }
    00183
    00184     // add it to the list.
    00185         return( FdoCollection<FdoIdentifier, FdoCommandException>::Add(value) );
    00186     }
    00187
    00188     /// \brief
    00189     /// Inserts the specified item at the specified index within the collection.
    00190     /// Items following the insertion point are moved down to accommodate the new item.
    00191     /// Throws an invalid argument exception if the specified index is out of range.
    00192     ///
    00193     /// \param item
    00194     /// Input index
    00195     /// \param value
    00196     /// Input value
    00197     ///
    00198     /// \return
    00199     /// Returns nothing
    00200     ///
    00201     virtual void Insert( FdoInt32 item, FdoIdentifier* value)
    00202     {
    00203         CheckDuplicate( value, -1 );
    00204
    00205     // Insert the new item in the map
    00206         if ( mpNameMap ) {
    00207             InsertMap(value);
    00208         }
    00209
    00210     // Insert it in the list
    00211         return( FdoCollection<FdoIdentifier, FdoCommandException>::Insert(item, value) );
    00212     }
    00213
    00214     /// \brief
    00215     /// Removes all items from the collection.
    00216     ///
    00217     /// \return
    00218     /// Returns nothing
    00219     ///
    00220     virtual void Clear()
    00221     {
    00222     // Clear the map
    00223         if (mpNameMap ) {
    00224             delete mpNameMap;
    00225             mpNameMap = NULL;
    00226         }
    00227
    00228     // Clear the list
    00229         FdoCollection<FdoIdentifier, FdoCommandException>::Clear();
    00230     }
    00231
    00232     /// \brief
    00233     /// Removes the specified item from the collection. Throws an invalid argument exception if the item does not exist within the collection.
    00234     ///
    00235     /// \param value
    00236     /// Input value
    00237     ///
    00238     /// \return
    00239     /// Returns nothing
    00240     ///
    00241     virtual void Remove(const FdoIdentifier* value)
    00242     {
    00243     // Remove the item from the map.
    00244         if ( mpNameMap )
    00245             RemoveMap( value );
    00246
    00247     // Remove it from the list
    00248         FdoCollection<FdoIdentifier, FdoCommandException>::Remove(value);
    00249     }
    00250
    00251     /// \brief
    00252     /// Removes the specified item from the collection. Throws an invalid argument exception if the item does not exist within the collection.
    00253     ///
    00254     /// \param index
    00255     /// Input index
    00256     ///
    00257     /// \return
    00258     /// Returns nothing
    00259     ///
    00260     virtual void RemoveAt(FdoInt32 index)
    00261     {
    00262     // Remove the item from the map.
    00263         if ( mpNameMap )
    00264             RemoveMapAt(index);
    00265
    00266     // Remove it from the list
    00267         FdoCollection<FdoIdentifier, FdoCommandException>::RemoveAt(index);
    00268     }
    00269
    00270     /// \brief
    00271     /// Returns true if the collection contains the specified item, false otherwise.
    00272     ///
    00273     /// \param value
    00274     /// Input value
    00275     ///
    00276     /// \return
    00277     /// Returns true if the collection contains the specified item, false otherwise
    00278     ///
    00279     virtual bool Contains(const FdoIdentifier* value)
    00280     {
    00281     // trigger the building of a map when the collection reaches the threshold size.
    00282         ((FdoIdentifierCollection*) this)->InitMap();
    00283
    00284         if (mpNameMap )
    00285         {
    00286     // If map is built, use it since it is faster.
    00287             FdoPtr <FdoIDisposable> temp = GetMap (((FdoIdentifier*)value)->GetText());
    00288             bool ret = (temp != NULL);
    00289             return (ret);
    00290         }
    00291         else // Otherwise, linear search
    00292         {
    00293             FdoString * valueName = ((FdoIdentifier*)value)->GetText();
    00294             FdoInt32 count = FdoCollection<FdoIdentifier, FdoCommandException>::GetCount();
    00295             bool ret = false;
    00296             for (FdoInt32 i = 0; !ret && i < count; i++)
    00297             {
    00298                 FdoPtr<FdoIdentifier> item = GetItem(i);
    00299                 FdoString * itemName = item->GetText();
    00300                 ret = (Compare(itemName, valueName)==0);
    00301             }
    00302             return ret;
    00303         }
    00304     }
    00305
    00306     /// \brief
    00307     /// Returns true if the collection contains the specified item, false otherwise.
    00308     ///
    00309     /// \param name
    00310     /// Input the item name
    00311     ///
    00312     /// \return
    00313     /// Returns true if the collection contains the specified item, false otherwise
    00314     ///
    00315     virtual bool Contains(FdoString* name)
    00316     {
    00317         FdoIdentifier* item = FindItem(name);
    00318         bool found = (item != NULL);
    00319
    00320         FDO_SAFE_RELEASE(item);
    00321
    00322         return(found);
    00323     }
    00324
    00325     /// \brief
    00326     /// Returns the index of the specified item in the collection or -1 if the item does not exist.
    00327     ///
    00328     /// \param value
    00329     /// Input value
    00330     ///
    00331     /// \return
    00332     /// Returns the index of the specified item in the collection or -1 if the item does not exist
    00333     ///
    00334     virtual FdoInt32 IndexOf(const FdoIdentifier* value)
    00335     {
    00336         return(FdoCollection<FdoIdentifier, FdoCommandException>::IndexOf(value));
    00337     }
    00338
    00339     /// \brief
    00340     /// Returns the index of the specified item (by name) in the collection or -1 if the item does not exist.
    00341     ///
    00342     /// \param name
    00343     /// Input the item name
    00344     ///
    00345     /// \return
    00346     /// Returns the index of the specified item in the collection or -1 if the item does not exist
    00347     ///
    00348     virtual FdoInt32 IndexOf(FdoString* name)
    00349     {
    00350         if (name == NULL)
    00351             throw FdoCommandException::Create(FdoException::NLSGetMessage(FDO_NLSID(FDO_2_BADPARAMETER)));
    00352
    00353         FdoInt32    size = FdoCollection<FdoIdentifier, FdoCommandException>::GetCount();
    00354         for (FdoInt32 i = 0; i < size; i++)
    00355         {
    00356             FdoPtr<FdoIdentifier> pitem = GetItem(i);
    00357             if (pitem != NULL && pitem->GetText() != (FdoString*) NULL && Compare(name, pitem->GetText()) == 0) {
    00358                 return i;
    00359             }
    00360         }
    00361
    00362         return(-1);
    00363     }
    00364
    00365 protected:
    00366     FdoIdentifierCollection( bool caseSensitive = true )
    00367     {
    00368         mbCaseSensitive = caseSensitive;
    00369         mpNameMap = NULL;
    00370     }
    00371
    00372     virtual ~FdoIdentifierCollection(void)
    00373     {
    00374         if (mpNameMap )
    00375             delete mpNameMap;
    00376     }
    00377
    00378 /// \cond DOXYGEN-IGNORE
    00379     int Compare( FdoString* str1, FdoString* str2 ) const
    00380     {
    00381         if ( mbCaseSensitive )
    00382             return ( wcscmp(str1, str2) );
    00383
    00384     // Try case-insensitive comparison.
    00385 #ifdef _WIN32
    00386         return ( _wcsicmp(str1, str2) );
    00387 #else
    00388         return ( wcscasecmp(str1, str2) );
    00389 #endif
    00390     }
    00391
    00392     void CheckDuplicate( FdoIdentifier* item, FdoInt32 index )
    00393     {
    00394         FdoPtr<FdoIdentifier> foundItem1 = FindItem( item->GetText() );
    00395         FdoPtr<FdoIdentifier> foundItem2;
    00396
    00397         if ( index >= 0 ) {
    00398             foundItem2 = GetItem(index);
    00399         }
    00400
    00401         if ( (foundItem1 !=NULL) && (foundItem1.p != foundItem2.p ) ) {
    00402             throw FdoCommandException::Create(
    00403                 FdoException::NLSGetMessage(
    00404                     FDO_NLSID(FDO_45_ITEMINCOLLECTION),
    00405                     (FdoString*) item->GetText()
    00406                 )
    00407             );
    00408         }
    00409     }
    00410 /// \endcond
    00411
    00412 private:
    00413     void InitMap()
    00414     {
    00415     // Build the map if not already built and the collection has hit the threshold
    00416         if ( !mpNameMap && ( FdoCollection<FdoIdentifier, FdoCommandException>::GetCount() > FDO_COLL_MAP_THRESHOLD ) ) {
    00417             mpNameMap = new std::map<FdoStringP,FdoIdentifier*>();
    00418
    00419     // Put all the current elements into the map
    00420             for ( FdoInt32 i = (FdoCollection<FdoIdentifier, FdoCommandException>::GetCount() - 1); i >= 0; i-- )
    00421                 InsertMap( FdoPtr<FdoIdentifier>(GetItem(i)) );
    00422         }
    00423     }
    00424
    00425     void InsertMap( FdoIdentifier* value ) const
    00426     {
    00427     // Add an element to the map. Elements are keyed by name, which may or may not be case sensitive.
    00428     // Case insensitive names are stored in lower case.
    00429         if ( mbCaseSensitive )
    00430             mpNameMap->insert( std::pair<FdoStringP,FdoIdentifier*> ( value->GetText(), value ) );
    00431         else
    00432             mpNameMap->insert( std::pair<FdoStringP,FdoIdentifier*> ( FdoStringP(value->GetText()).Lower(), value ) );
    00433     }
    00434
    00435     // Remove the element at the specified index, from the map
    00436     void RemoveMapAt( FdoInt32 index )
    00437     {
    00438     // Remove the old item from the map
    00439         FdoIdentifier* pItem = FdoCollection<FdoIdentifier, FdoCommandException>::GetItem(index);
    00440
    00441         if ( pItem ) {
    00442             RemoveMap( pItem );
    00443             pItem->Release();
    00444         }
    00445     }
    00446
    00447     // Remove the given element from the map.
    00448     void RemoveMap( const FdoIdentifier* value )
    00449     {
    00450     // handle the current case sensitivity of the element name.
    00451         if ( mbCaseSensitive )
    00452             mpNameMap->erase( FdoStringP( ((FdoIdentifier*)value)->GetText() ) );
    00453         else
    00454             mpNameMap->erase( FdoStringP( ((FdoIdentifier*)value)->GetText() ).Lower() );
    00455     }
    00456
    00457     // Get the named element from the map. Returns NULL if element not in map.
    00458     FdoIdentifier* GetMap( const wchar_t* name ) const
    00459     {
    00460         FdoIdentifier* pItem = NULL;
    00461
    00462         /*typename*/ std::map <FdoStringP,FdoIdentifier*> :: const_iterator iter;
    00463
    00464         if ( mbCaseSensitive )
    00465             iter = mpNameMap->find( FdoStringP(name) );
    00466         else
    00467     // Case sensitive names are stored in lower case.
    00468             iter = mpNameMap->find( FdoStringP(name).Lower() );
    00469
    00470         if ( iter != mpNameMap->end() ) {
    00471             pItem = (FdoIdentifier*) iter->second;
    00472             FDO_SAFE_ADDREF(pItem);
    00473         }
    00474
    00475         return( pItem );
    00476     }
    00477
    00478     bool mbCaseSensitive;
    00479
    00480     // A map keyed by name, to help performance of large collections.
    00481     std::map<FdoStringP,FdoIdentifier*> *mpNameMap;
    00482
    00483 };
    00484 #endif
    00485

Please send us your comment about this page