[mapguide-commits] r5427 - trunk/MgDev/Common/CoordinateSystem
svn_mapguide at osgeo.org
svn_mapguide at osgeo.org
Wed Dec 1 08:24:53 EST 2010
Author: baertelchen
Date: 2010-12-01 05:24:53 -0800 (Wed, 01 Dec 2010)
New Revision: 5427
Modified:
trunk/MgDev/Common/CoordinateSystem/CoordSys.cpp
trunk/MgDev/Common/CoordinateSystem/CoordSys.h
trunk/MgDev/Common/CoordinateSystem/CoordSysDatum.cpp
trunk/MgDev/Common/CoordinateSystem/CoordSysDatum.h
trunk/MgDev/Common/CoordinateSystem/CoordSysDatumDictionary.cpp
trunk/MgDev/Common/CoordinateSystem/CoordSysDatumDictionary.h
trunk/MgDev/Common/CoordinateSystem/CoordSysDictionary.cpp
trunk/MgDev/Common/CoordinateSystem/CoordSysDictionary.h
trunk/MgDev/Common/CoordinateSystem/CoordSysEllipsoidDictionary.cpp
trunk/MgDev/Common/CoordinateSystem/CoordSysEllipsoidDictionary.h
trunk/MgDev/Common/CoordinateSystem/CoordSysEnum.cpp
trunk/MgDev/Common/CoordinateSystem/CoordSysEnum.h
trunk/MgDev/Common/CoordinateSystem/MentorDictionary.cpp
trunk/MgDev/Common/CoordinateSystem/MentorDictionary.h
Log:
Fix for trac ticket 1538 "Speed up Coordinate System Dictionary lookup when reading all CS definitions at once"
When reading all available coordinate system definitions from the dictionaries via the Mg API, the code in CoordSysEnum.cpp did call back into CsMap for every system. This resulted in unnecessary disk IO access as CsMap does always read from the dictionary files.
This submission adds an API-internal ReadAll* method to the CCoordinateSystem* dictionary classes for ellipsoids, datums and for coordinate systems. Whenever an API client is about to read !all! available coordinate systems via the CoordSysEnum::Next(UINT) method, the enum will basically call back into the respective dictionary via the ReadAll* method. This will return all entries instead of having to read all entries one by one in the enum.
After having retrieved the collection of all MgCS objects, CoordSysEnum will simply return that to the caller. This does not increase the memory foot print, as the code did before also read all systems and did also create the thousands of objects before having returned to the caller.
No public API changes.
Reviewed by Norm and Hugues.
Modified: trunk/MgDev/Common/CoordinateSystem/CoordSys.cpp
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSys.cpp 2010-12-01 11:11:48 UTC (rev 5426)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSys.cpp 2010-12-01 13:24:53 UTC (rev 5427)
@@ -102,7 +102,9 @@
//without loading the DT from the dictionary
//The DT can then be set via CCoordinateSystem::SetDatumDefinition
//
-void CCoordinateSystem::InitFromCatalog(const cs_Csdef_& csdef)
+void CCoordinateSystem::InitFromCatalog(const cs_Csdef_& csdef,
+ const map<STRING, Ptr<MgDisposable> >* const ellipsoidMap,
+ const map<STRING, Ptr<MgDisposable> >* const datumMap)
{
MG_TRY()
@@ -134,21 +136,43 @@
bool bGeodetic=CsdefIsGeodetic(csdef);
if (bGeodetic)
{
+ wchar_t* pwszDtName = Convert_Ascii_To_Wide(csdef.dat_knm);
+ STRING sDtName(pwszDtName);
+
+ delete[] pwszDtName;
+ pwszDtName = NULL;
+
+ Ptr<MgGuardDisposable> pDatum;
+
//It's geodetic. We need a datum definition.
- Ptr<MgCoordinateSystemDatumDictionary> pDtDict=m_pCatalog->GetDatumDictionary();
- if (!pDtDict)
+ if (NULL != datumMap)
{
- throw new MgCoordinateSystemInitializationFailedException(L"MgCoordinateSystem.InitFromCatalog", __LINE__, __WFILE__, NULL, L"MgCoordinateSystemNoDatumDictionaryException", NULL);
+ map<STRING, Ptr<MgDisposable> >::const_iterator datumMapIterator = datumMap->find(sDtName);
+ if (datumMapIterator != datumMap->end())
+ {
+ Ptr<MgDisposable> disposableCsObject = datumMapIterator->second;
+ MgCoordinateSystemDatum* datumInfo = dynamic_cast<MgCoordinateSystemDatum*>(disposableCsObject.p);
+ if (NULL == datumInfo)
+ throw new MgInvalidArgumentException(L"MgCoordinateSystem.InitFromCatalog", __LINE__, __WFILE__, NULL, L"", NULL);
+
+ pDatum = SAFE_ADDREF(datumInfo);
+ }
}
- wchar_t* pwszDtName=Convert_Ascii_To_Wide(csdef.dat_knm);
- STRING sDtName(pwszDtName);
- delete[] pwszDtName;
- Ptr<MgGuardDisposable> pDatum=pDtDict->Get(sDtName);
- assert(pDatum);
- if (!pDatum)
+ if (NULL == pDatum)
{
- throw new MgCoordinateSystemInitializationFailedException(L"MgCoordinateSystem.InitFromCatalog", __LINE__, __WFILE__, NULL, L"MgCoordinateSystemNoDatumInDictionaryException", NULL);
+ Ptr<MgCoordinateSystemDatumDictionary> pDtDict = m_pCatalog->GetDatumDictionary();
+ if (!pDtDict)
+ {
+ throw new MgCoordinateSystemInitializationFailedException(L"MgCoordinateSystem.InitFromCatalog", __LINE__, __WFILE__, NULL, L"MgCoordinateSystemNoDatumDictionaryException", NULL);
+ }
+
+ pDatum = pDtDict->Get(sDtName);
+ assert(pDatum);
+ if (!pDatum)
+ {
+ throw new MgCoordinateSystemInitializationFailedException(L"MgCoordinateSystem.InitFromCatalog", __LINE__, __WFILE__, NULL, L"MgCoordinateSystemNoDatumInDictionaryException", NULL);
+ }
}
//We've got a datum object. Complete the initialization.
@@ -156,23 +180,44 @@
} //if it's geodetic
else
{
- //It's cartographic. We need an ellipsoid definition.
- Ptr<MgCoordinateSystemEllipsoidDictionary> pElDict=m_pCatalog->GetEllipsoidDictionary();
- if (!pElDict)
- {
- throw new MgCoordinateSystemInitializationFailedException(L"MgCoordinateSystem.InitFromCatalog", __LINE__, __WFILE__, NULL, L"MgCoordinateSystemNoEllipsoidDictionaryException", NULL);
- }
- wchar_t* pwszElName=Convert_Ascii_To_Wide(csdef.elp_knm);
+ wchar_t* pwszElName = Convert_Ascii_To_Wide(csdef.elp_knm);
STRING sElName(pwszElName);
delete[] pwszElName;
+ pwszElName = NULL;
- Ptr<MgGuardDisposable> pEllipsoid=pElDict->Get(sElName);
- assert(pEllipsoid);
- if (!pEllipsoid)
+ Ptr<MgGuardDisposable> pEllipsoid;
+
+ if (NULL != ellipsoidMap)
{
- throw new MgCoordinateSystemInitializationFailedException(L"MgCoordinateSystem.InitFromCatalog", __LINE__, __WFILE__, NULL, L"MgCoordinateSystemNoEllipsoidInDictionaryException", NULL);
+ map<STRING, Ptr<MgDisposable> >::const_iterator ellipsoidMapIterator = ellipsoidMap->find(sElName);
+ if (ellipsoidMapIterator != ellipsoidMap->end())
+ {
+ Ptr<MgDisposable> disposableCsObject = ellipsoidMapIterator->second;
+ MgCoordinateSystemEllipsoid* ellipsoidInfo = dynamic_cast<MgCoordinateSystemEllipsoid*>(disposableCsObject.p);
+ if (NULL == ellipsoidInfo)
+ throw new MgInvalidArgumentException(L"MgCoordinateSystem.InitFromCatalog", __LINE__, __WFILE__, NULL, L"", NULL);
+
+ pEllipsoid = SAFE_ADDREF(ellipsoidInfo);
+ }
}
+ if (NULL == pEllipsoid)
+ {
+ //It's cartographic. We need an ellipsoid definition.
+ Ptr<MgCoordinateSystemEllipsoidDictionary> pElDict = m_pCatalog->GetEllipsoidDictionary();
+ if (!pElDict)
+ {
+ throw new MgCoordinateSystemInitializationFailedException(L"MgCoordinateSystem.InitFromCatalog", __LINE__, __WFILE__, NULL, L"MgCoordinateSystemNoEllipsoidDictionaryException", NULL);
+ }
+
+ pEllipsoid = pElDict->Get(sElName);
+ assert(pEllipsoid);
+ if (!pEllipsoid)
+ {
+ throw new MgCoordinateSystemInitializationFailedException(L"MgCoordinateSystem.InitFromCatalog", __LINE__, __WFILE__, NULL, L"MgCoordinateSystemNoEllipsoidInDictionaryException", NULL);
+ }
+ }
+
//We've got the ellipsoid definition. Complete the initialization.
return SetEllipsoidDefinition(dynamic_cast<MgCoordinateSystemEllipsoid*>(pEllipsoid.p));
} //if it's cartographic
Modified: trunk/MgDev/Common/CoordinateSystem/CoordSys.h
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSys.h 2010-12-01 11:11:48 UTC (rev 5426)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSys.h 2010-12-01 13:24:53 UTC (rev 5427)
@@ -39,7 +39,9 @@
virtual ~CCoordinateSystem();
bool InitArbitrary(const cs_Csprm_ &csprm);
- void InitFromCatalog(const cs_Csdef_& def);
+ void InitFromCatalog(const cs_Csdef_& def,
+ const map<STRING, Ptr<MgDisposable> >* const ellipsoidMap = NULL,
+ const map<STRING, Ptr<MgDisposable> >* const datumMap = NULL);
void GetMentorDef(cs_Csdef_& def){def=m_csprm.csdef;};
//from MgCoordinateSystem
Modified: trunk/MgDev/Common/CoordinateSystem/CoordSysDatum.cpp
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysDatum.cpp 2010-12-01 11:11:48 UTC (rev 5426)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysDatum.cpp 2010-12-01 13:24:53 UTC (rev 5427)
@@ -114,7 +114,11 @@
//without loading the ellipsoid from the dictionary
//The ellipsoid can then be set via CCoordinateSystemDatum::SetEllipsoidDefinition
//
-void CCoordinateSystemDatum::InitFromCatalog(const cs_Dtdef_& def)
+//When passing a non-NULL pointer for the [ellipsoidMap] parameter, the ellipsoid information is tried
+//being read from there; if still not found in the std::map, the fallback
+//is to read the information from CsMap, i.e. the dictionary files
+void CCoordinateSystemDatum::InitFromCatalog(const cs_Dtdef_& def,
+ const map<STRING, Ptr<MgDisposable> >* const ellipsoidMap)
{
MG_TRY()
@@ -144,12 +148,6 @@
return;
}
- //Get the ellipsoid dictionary
- Ptr<MgCoordinateSystemEllipsoidDictionary> pElDict=m_pCatalog->GetEllipsoidDictionary();
- if (!pElDict)
- {
- throw new MgCoordinateSystemInitializationFailedException(L"MgCoordinateSystemDatum.InitFromCatalog", __LINE__, __WFILE__, NULL, L"MgCoordinateSystemDatumNoEllipsoidDictionaryException", NULL);
- }
//Get the ellipsoid name the datum uses
wchar_t* pwszElName=Convert_Ascii_To_Wide(def.ell_knm);
if (!pwszElName)
@@ -158,15 +156,43 @@
}
STRING sElName(pwszElName);
delete[] pwszElName;
+ pwszElName = NULL;
- //load the ellipsoid defintion from the dictionary
- Ptr<MgGuardDisposable> pEllipsoid=pElDict->Get(sElName);
- assert(pEllipsoid);
- if (!pEllipsoid)
+ Ptr<MgGuardDisposable> pEllipsoid;
+
+ //if the caller passed in a std::map of known ellipsoids, we're trying to take the information from there
+ if (NULL != ellipsoidMap)
{
- throw new MgCoordinateSystemInitializationFailedException(L"MgCoordinateSystemDatum.InitFromCatalog", __LINE__, __WFILE__, NULL, L"MgCoordinateSystemDatumNoEllipsoidInDictionaryException", NULL);
+ map<STRING, Ptr<MgDisposable> >::const_iterator ellipsoidsIterator = ellipsoidMap->find(sElName);
+ if (ellipsoidsIterator != ellipsoidMap->end())
+ {
+ Ptr<MgDisposable> disposableCsObject = ellipsoidsIterator->second;
+ MgCoordinateSystemEllipsoid* ellipsoidInfo = dynamic_cast<MgCoordinateSystemEllipsoid*>(disposableCsObject.p);
+ if (NULL == ellipsoidInfo)
+ throw new MgInvalidArgumentException(L"MgCoordinateSystemDatum.InitFromCatalog", __LINE__, __WFILE__, NULL, L"", NULL);
+
+ pEllipsoid = SAFE_ADDREF(ellipsoidInfo);
+ }
}
+ //either no [ellipsoidMap] or the information we're interested in, hasn't been found in the map
+ if (NULL == pEllipsoid)
+ {
+ //Get the ellipsoid dictionary
+ Ptr<MgCoordinateSystemEllipsoidDictionary> pElDict = m_pCatalog->GetEllipsoidDictionary();
+ if (!pElDict)
+ {
+ throw new MgCoordinateSystemInitializationFailedException(L"MgCoordinateSystemDatum.InitFromCatalog", __LINE__, __WFILE__, NULL, L"MgCoordinateSystemDatumNoEllipsoidDictionaryException", NULL);
+ }
+
+ //load the ellipsoid defintion from the dictionary
+ pEllipsoid = pElDict->Get(sElName);
+ assert(pEllipsoid);
+ }
+
+ if (NULL == pEllipsoid)
+ throw new MgCoordinateSystemInitializationFailedException(L"MgCoordinateSystemDatum.InitFromCatalog", __LINE__, __WFILE__, NULL, L"MgCoordinateSystemDatumNoEllipsoidInDictionaryException", NULL);
+
//Initialize from ellipsoid definitions we have
SetEllipsoidDefinition(dynamic_cast<MgCoordinateSystemEllipsoid*>(pEllipsoid.p));
@@ -175,6 +201,7 @@
{
Uninitialize();
}
+
MG_THROW()
}
Modified: trunk/MgDev/Common/CoordinateSystem/CoordSysDatum.h
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysDatum.h 2010-12-01 11:11:48 UTC (rev 5426)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysDatum.h 2010-12-01 13:24:53 UTC (rev 5427)
@@ -27,7 +27,7 @@
CCoordinateSystemDatum(MgCoordinateSystemCatalog* pCatalog);
virtual ~CCoordinateSystemDatum();
- void InitFromCatalog(const cs_Dtdef_& def);
+ void InitFromCatalog(const cs_Dtdef_& def, const map<STRING, Ptr<MgDisposable> >* const ellipsoidMap = NULL);
void GetMentorDef(cs_Dtdef_& def){def=m_DtDef;};
virtual STRING GetDtCode();
Modified: trunk/MgDev/Common/CoordinateSystem/CoordSysDatumDictionary.cpp
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysDatumDictionary.cpp 2010-12-01 11:11:48 UTC (rev 5426)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysDatumDictionary.cpp 2010-12-01 13:24:53 UTC (rev 5427)
@@ -247,8 +247,6 @@
return CS_dtdef(kpName);
}
- throw new MgInvalidOperationException(L"CCoordinateSystemDatumDictionary.dtdef", __LINE__, __WFILE__, NULL, L"", NULL);
-
//It's an old version. We need to do a special search
//in the file, and then, if found, update it to a current struct.
@@ -515,27 +513,29 @@
//returns it (user is responsible for freeing the def via Release()
//function).
//Throws an exception (if no such definition exists in the catalog).
+//Delegates the call to the ::GetDatum(CREFSTRING) method
MgGuardDisposable* CCoordinateSystemDatumDictionary::Get(CREFSTRING sName)
{
return GetDatum(sName);
}
+//--------------------------------------------------------------
+//Reads a CsMap definition from the dictionaries and then creates an MgCoordinateSystemDatum
+//out of it - this method is the more expensive one as it interacts with CsMap and
+//the dictionary files; if you've already read all ellipsoid information
+//you may want to consider using the overloaded [GetDatum(std::*)] method instead
MgCoordinateSystemDatum* CCoordinateSystemDatumDictionary::GetDatum(CREFSTRING sName)
{
- Ptr<MgCoordinateSystemDatum> pDefinition;
cs_Dtdef_ *pDef = NULL;
char *pName = NULL;
+ Ptr<MgCoordinateSystemDatum> pDatum;
+
MG_TRY()
//Get the name to search for
pName = Convert_Wide_To_Ascii(sName.c_str()); //need to delete [] pName
- if (NULL == pName)
- {
- throw new MgOutOfMemoryException(L"MgCoordinateSystemDatumDictionary.GetDatum", __LINE__, __WFILE__, NULL, L"", NULL);
- }
-
//Look in the dictionary
pDef = dtdef(pName);
@@ -549,33 +549,44 @@
//Okay, at this point we have a Mentor coordsys definition
//struct. Build an object out of it.
- pDefinition=NewDatum();
+ pDatum = this->GetDatum(pDef, NULL /* we don't have a std::map available that contains all ellipsoids*/);
- if (NULL == pDefinition.p)
- {
- throw new MgOutOfMemoryException(L"MgCoordinateSystemDatumDictionary.GetDatum", __LINE__, __WFILE__, NULL, L"", NULL);
- }
+ MG_CATCH(L"MgCoordinateSystemDatumDictionary.GetDatum")
- CCoordinateSystemDatum* pImp=dynamic_cast<CCoordinateSystemDatum*>(pDefinition.p);
- assert(pImp);
- if (!pImp)
+ delete [] pName;
+ if (NULL != pDef)
{
- MgStringCollection arguments;
- arguments.Add(sName);
- throw new MgCoordinateSystemLoadFailedException(L"MgCoordinateSystemDatumDictionary.GetDatum", __LINE__, __WFILE__, &arguments, L"", NULL);
+ CS_free(pDef);
+ pDef = NULL;
}
- pImp->InitFromCatalog(*pDef);
- //And return success!
+ MG_THROW()
- MG_CATCH(L"MgCoordinateSystemDatumDictionary.GetDatum")
+ return pDatum.Detach();
+}
- CS_free(pDef);
- delete [] pName;
+//--------------------------------------------------------------
+//Method that creates an [MgCoordinateSystemDatum] from a CsMap [cs_Dtdef_] struct
+//and (optionally) a std::map of ellipsoids the caller knows of. Passing this
+//information in, will prevent the [InitFromCatalog] method from making too many calls
+//into the File-IO methods of CsMap. [ellipsoidInfos] can be NULL - the necessary information is then
+//read from via CsMap
+MgCoordinateSystemDatum* CCoordinateSystemDatumDictionary::GetDatum(const cs_Dtdef_* pDef,
+ const std::vector<std::map<STRING,Ptr<MgDisposable> >*>* const ellipsoidInfos)
+{
+ Ptr<CCoordinateSystemDatum> pDatum = static_cast<CCoordinateSystemDatum*>(NewDatum());
+
+ assert(NULL == ellipsoidInfos || 1 == ellipsoidInfos->size());
+ if (NULL != ellipsoidInfos && 1 == ellipsoidInfos->size())
+ {
+ pDatum->InitFromCatalog(*pDef, ellipsoidInfos->at(0));
+ }
+ else
+ {
+ pDatum->InitFromCatalog(*pDef);
+ }
- MG_THROW()
-
- return pDefinition.Detach();
+ return pDatum.Detach();
}
//--------------------------------------------------------------
@@ -638,15 +649,22 @@
csFILE *pFile=NULL;
SmartCriticalClass critical(true);
+ //use to create an optimized enum that returns *all* available definitions in a block
+ //this does only work for the latest versions of the dictionaries
+ bool setReadAllDatumsCallback = false;
+
MG_TRY()
+
STRING strPath=GetPath();
pFile=MentorDictionary::Open(m_lMagic, DatumValidMagic, strPath.c_str(), Read);
+ const int nVersion = DatumVersion(m_lMagic);
+ assert(nVersion > 0);
+ setReadAllDatumsCallback = (7 == nVersion || 8 == nVersion);
+
//Generate a summary list, if we don't already have one
if (NULL == m_pmapSystemNameDescription)
{
- int nVersion = DatumVersion(m_lMagic);
- assert(nVersion > 0);
switch (nVersion)
{
case 5:
@@ -690,27 +708,67 @@
{
throw new MgOutOfMemoryException(L"MgCoordinateSystemDatumDictionary.GetEnum", __LINE__, __WFILE__, NULL, L"", NULL);
}
- if (0!=CS_fclose(pFile))
- {
- throw new MgFileIoException(L"MgCoordinateSystemDatumDictionary.GetEnum", __LINE__, __WFILE__, NULL, L"MgCoordinateSystemDictionaryCloseFailedException", NULL);
- }
- pFile=NULL;
MG_CATCH(L"MgCoordinateSystemDatumDictionary.GetEnum")
if (pFile)
{
- CS_fclose(pFile);
+ const bool fileClosed = (0 == CS_fclose(pFile));
+ if (!fileClosed && NULL == mgException) //throw this exception in case no other exception has already been caught
+ mgException = new MgFileIoException(L"MgCoordinateSystemDatumDictionary.GetEnum", __LINE__, __WFILE__, NULL, L"MgCoordinateSystemDictionaryCloseFailedException", NULL);
+
+ pFile = NULL;
}
MG_THROW()
//Set it up to use our list
pNew->Initialize(this, m_pmapSystemNameDescription);
+
+ if (setReadAllDatumsCallback) //if we're working on the latest dictionaries, allow read-as-block, if so required by the caller in the ::Next(ULONG) method
+ pNew->SetReadAllDefinitionCallback(CCoordinateSystemDatumDictionary::ReadAllDatums);
return pNew.Detach();
}
+//--------------------------------------------------------------
+//Reads all datums in one run - opens the dictionary file and then scans the whole file
+//all definitions found are stored in the [definitionsFound] collection that the caller will
+//have to release - incl. its content (what is done automatically, when disposing the collection itself)
+MgDisposableCollection* CCoordinateSystemDatumDictionary::ReadAllDatums(/*IN, required*/MgCoordinateSystemDictionaryBase* targetDictionary,
+ /*IN, optional*/const std::vector<MgCoordinateSystemFilter*>* const filters)
+{
+ if (NULL == targetDictionary)
+ throw new MgNullArgumentException(L"CCoordinateSystemDatumDictionary.ReadAllDatums", __LINE__, __WFILE__, NULL, L"", NULL);
+
+ CCoordinateSystemDatumDictionary* datumDictionary = dynamic_cast<CCoordinateSystemDatumDictionary*>(targetDictionary);
+ if (NULL == datumDictionary) //everything else is an implementation defect
+ throw new MgInvalidArgumentException(L"CCoordinateSystemDatumDictionary.ReadAllDatums", __LINE__, __WFILE__, NULL, L"", NULL);
+
+ //place a lock here - we don't want any interference; what we need is the *current* status of all dictionary files
+ SmartCriticalClass dictionaryLock(true);
+
+ Ptr<MgCoordinateSystemCatalog> catalog = targetDictionary->GetCatalog();
+ Ptr<MgCoordinateSystemEllipsoidDictionary> ellipsoidDictionary = catalog->GetEllipsoidDictionary();
+
+ //read all ellipsoids
+ map<STRING, Ptr<MgDisposable> > ellipsoidMap;
+ MentorDictionary::ReadAllDefinitions<MgCoordinateSystemEllipsoid>(ellipsoidDictionary, &MgCoordinateSystemEllipsoid::GetElCode, ellipsoidMap);
+
+ //place the std::maps in a vector which later be passed to the [GetDatum] method
+ std::vector<std::map<STRING,Ptr<MgDisposable> >*> ellipsoidInfos;
+ ellipsoidInfos.push_back(&ellipsoidMap);
+
+ //finally, read all "root" coordinate system definitions from the dictionary
+ return MentorDictionary::ReadAllDefinitions<MgCoordinateSystemDatum, cs_Dtdef_, CCoordinateSystemDatumDictionary>(
+ datumDictionary,
+ CS_dtrd,
+ NULL, //no additional processing
+ &CCoordinateSystemDatumDictionary::GetDatum,
+ &ellipsoidInfos,
+ filters);
+}
+
//MgDisposable
void CCoordinateSystemDatumDictionary::Dispose()
{
Modified: trunk/MgDev/Common/CoordinateSystem/CoordSysDatumDictionary.h
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysDatumDictionary.h 2010-12-01 11:11:48 UTC (rev 5426)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysDatumDictionary.h 2010-12-01 13:24:53 UTC (rev 5427)
@@ -57,6 +57,12 @@
//Private member functions
cs_Dtdef_ * dtdef(const char *kpName) const;
CCoordinateSystemEnumDatum* GetEnumImp();
+
+ MgCoordinateSystemDatum* GetDatum(const cs_Dtdef_* datumDef,
+ const std::vector<std::map<STRING,Ptr<MgDisposable> >*>* const ellipsoidInfos = NULL);
+
+ static MgDisposableCollection* ReadAllDatums(MgCoordinateSystemDictionaryBase* targetDictionary,
+ const std::vector<MgCoordinateSystemFilter*>* const filters);
private:
//Unimplemented stuff
Modified: trunk/MgDev/Common/CoordinateSystem/CoordSysDictionary.cpp
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysDictionary.cpp 2010-12-01 11:11:48 UTC (rev 5426)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysDictionary.cpp 2010-12-01 13:24:53 UTC (rev 5427)
@@ -243,19 +243,11 @@
cs_Csdef_* pDef=CS_csdef(kpName);
if (pDef)
{
- INT32 unit=UnitFromString(pDef->unit);
- INT32 unitType;
- double dfUnitScale=0.;
- if (GetUnitInfo(unit, &unitType, &dfUnitScale))
- {
- pDef->unit_scl=dfUnitScale;
- }
+ this->DoCsDefPostReadProcessing(pDef);
}
return pDef;
}
- throw new MgInvalidOperationException(L"CCoordinateSystemDictionary.csdef", __LINE__, __WFILE__, NULL, L"", NULL);
-
//It's an old version. We need to do a special search
//in the file, and then, if found, update it to a current struct.
UINT32 nStructSize, nNameSize;
@@ -308,19 +300,27 @@
CS_fclose(pFile);
if (pDef)
{
- INT32 unit=UnitFromString(pDef->unit);
- INT32 unitType;
- double dfUnitScale=0.;
- if (GetUnitInfo(unit, &unitType, &dfUnitScale))
- {
- pDef->unit_scl=dfUnitScale;
- }
+ this->DoCsDefPostReadProcessing(pDef);
}
return pDef;
}
//------------------------------------------------------------------------
+//does some post processing after a [cs_Csdef_] struct has been read from the
+//CsMap dictionary; [pDef] might get changed!
+void CCoordinateSystemDictionary::DoCsDefPostReadProcessing(cs_Csdef_* pDef)
+{
+ INT32 unit = UnitFromString(pDef->unit);
+ INT32 unitType;
+ double dfUnitScale=0.;
+ if (GetUnitInfo(unit, &unitType, &dfUnitScale))
+ {
+ pDef->unit_scl=dfUnitScale;
+ }
+}
+
+//------------------------------------------------------------------------
MgCoordinateSystem* CCoordinateSystemDictionary::NewCoordinateSystem()
{
Ptr<CCoordinateSystem> pNewDef;
@@ -537,6 +537,10 @@
return GetCoordinateSystem(sName);
}
+//creates an MgCoordinateSystem by querying the underlying dictionary files - incl.
+//these for the ellipsoids and the datums.
+//If no such CS exists, an exception will be thrown, i.e. this method does
+//never return NULL
MgCoordinateSystem* CCoordinateSystemDictionary::GetCoordinateSystem(CREFSTRING sName)
{
Ptr<MgCoordinateSystem> pDefinition;
@@ -544,6 +548,7 @@
char *pName = NULL;
MG_TRY()
+
//Get the name to search for
pName = Convert_Wide_To_Ascii(sName.c_str()); //need to delete [] pName
@@ -565,29 +570,51 @@
//Okay, at this point we have a Mentor coordsys definition
//struct. Build an object out of it.
- pDefinition=NewCoordinateSystem();
+ pDefinition = this->GetCoordinateSystem(pDef, NULL);
+ assert(NULL != pDefinition);
- if (NULL == pDefinition.p)
+ MG_CATCH(L"MgCoordinateSystemDictionary.GetCoordinateSystem")
+
+ if (NULL != pDef)
{
- throw new MgOutOfMemoryException(L"MgCoordinateSystemDictionary.GetCoordinateSystem", __LINE__, __WFILE__, NULL, L"", NULL);
+ CS_free(pDef);
+ pDef = NULL;
}
- CCoordinateSystem* pImp=dynamic_cast<CCoordinateSystem*>(pDefinition.p);
- assert(pImp);
- if (!pImp)
+ delete [] pName;
+ pName = NULL;
+
+ MG_THROW()
+
+ return pDefinition.Detach();
+}
+
+//creates an MgCoordinateSystem; basically, it forward the
+//call to [InitFromCatalog] which will deal with the information
+//as it might have been passed by [datumEllipsoidInfos]
+MgCoordinateSystem* CCoordinateSystemDictionary::GetCoordinateSystem(const cs_Csdef_* csDef,
+ const std::vector<std::map<STRING,Ptr<MgDisposable> >*>* const datumEllipsoidInfos)
+{
+ Ptr<MgCoordinateSystem> pDefinition;
+
+ MG_TRY()
+
+ pDefinition = NewCoordinateSystem();
+
+ CCoordinateSystem* pImp = static_cast<CCoordinateSystem*>(pDefinition.p);
+
+ assert(NULL == datumEllipsoidInfos || 2 == datumEllipsoidInfos->size());
+ if (NULL != datumEllipsoidInfos && 2 == datumEllipsoidInfos->size())
{
- MgStringCollection arguments;
- arguments.Add(sName);
- throw new MgCoordinateSystemLoadFailedException(L"MgCoordinateSystemDictionary.GetCoordinateSystem", __LINE__, __WFILE__, &arguments, L"", NULL);
+ pImp->InitFromCatalog(*csDef, datumEllipsoidInfos->at(0) /* ellipsoids */, datumEllipsoidInfos->at(1) /* datums */);
}
+ else
+ {
+ pImp->InitFromCatalog(*csDef);
+ }
- pImp->InitFromCatalog(*pDef);
-
MG_CATCH(L"MgCoordinateSystemDictionary.GetCoordinateSystem")
- CS_free(pDef);
- delete [] pName;
-
MG_THROW()
return pDefinition.Detach();
@@ -628,6 +655,49 @@
return bHas;
}
+//------------------------------------------------------------------------
+//Reads *all* coordinate systems from the dictionary in one run
+//Does also read the necessary datum and ellipsoid information from the respective dictionaries
+MgDisposableCollection* CCoordinateSystemDictionary::ReadAllCoordinateSystems(/*IN, required*/ MgCoordinateSystemDictionaryBase* targetDictionary,
+ /*IN, optional*/ const std::vector<MgCoordinateSystemFilter*>* const filters)
+{
+ if (NULL == targetDictionary)
+ throw new MgNullArgumentException(L"MgCoordinateSystemDictionary.ReadAllCoordinateSystems", __LINE__, __WFILE__, NULL, L"", NULL);
+
+ CCoordinateSystemDictionary* csDictionary = dynamic_cast<CCoordinateSystemDictionary*>(targetDictionary);
+ if (NULL == csDictionary)
+ throw new MgInvalidArgumentException(L"MgCoordinateSystemDictionary.ReadAllCoordinateSystems", __LINE__, __WFILE__, NULL, L"", NULL);
+
+ //in order to create the MgCoordinateSystem objects, we have to have also the information on the datums and ellipsoids
+ map<STRING, Ptr<MgDisposable> > ellipsoidMap;
+ map<STRING, Ptr<MgDisposable> > datumMap;
+
+ //place a lock here - we don't want any interference; what we need is the *current* status of all dictionary files
+ SmartCriticalClass dictionaryLock(true);
+
+ Ptr<MgCoordinateSystemCatalog> catalog = targetDictionary->GetCatalog();
+ Ptr<MgCoordinateSystemEllipsoidDictionary> ellipsoidDictionary = catalog->GetEllipsoidDictionary();
+ Ptr<MgCoordinateSystemDatumDictionary> datumDictionary = catalog->GetDatumDictionary();
+
+ //read all ellipsoids and all datums
+ MentorDictionary::ReadAllDefinitions<MgCoordinateSystemEllipsoid>(ellipsoidDictionary, &MgCoordinateSystemEllipsoid::GetElCode, ellipsoidMap);
+ MentorDictionary::ReadAllDefinitions<MgCoordinateSystemDatum>(datumDictionary, &MgCoordinateSystemDatum::GetDtCode, datumMap);
+
+ //place the std::maps in a vector which later be passed to the [GetCoordinateSystem] method - the oder is important!
+ std::vector<std::map<STRING,Ptr<MgDisposable> >*> datumEllipsoidInfos;
+ datumEllipsoidInfos.push_back(&ellipsoidMap);
+ datumEllipsoidInfos.push_back(&datumMap);
+
+ //finally, read all "root" coordinate system definitions from the dictionary
+ return MentorDictionary::ReadAllDefinitions<MgCoordinateSystem, cs_Csdef_, CCoordinateSystemDictionary>(
+ csDictionary,
+ CS_csrd,
+ &CCoordinateSystemDictionary::DoCsDefPostReadProcessing,
+ &CCoordinateSystemDictionary::GetCoordinateSystem,
+ &datumEllipsoidInfos,
+ filters);
+}
+
//--------------------------------------------------------------
//Gets an enumerator for all the defs
MgCoordinateSystemEnum* CCoordinateSystemDictionary::GetEnum()
@@ -653,15 +723,21 @@
csFILE *pFile=NULL;
SmartCriticalClass critical(true);
+ bool setQuickReadCallback = false;
+
MG_TRY()
+
STRING strPath=GetPath();
pFile=MentorDictionary::Open(m_lMagic, CoordinateSystemValidMagic, strPath.c_str(), Read);
+ const int nVersion = CoordinateSystemVersion(m_lMagic);
+ assert(nVersion > 0);
+
+ setQuickReadCallback = (7 == nVersion || 8 == nVersion);
+
//Generate a summary list, if we don't already have one
if (NULL == m_pmapSystemNameDescription)
{
- int nVersion = CoordinateSystemVersion(m_lMagic);
- assert(nVersion > 0);
switch (nVersion)
{
case 5:
@@ -723,6 +799,8 @@
//Set it up to use our list
pNew->Initialize(this, m_pmapSystemNameDescription);
+ if (setQuickReadCallback)
+ pNew->SetReadAllDefinitionCallback(CCoordinateSystemDictionary::ReadAllCoordinateSystems);
return pNew.Detach();
}
Modified: trunk/MgDev/Common/CoordinateSystem/CoordSysDictionary.h
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysDictionary.h 2010-12-01 11:11:48 UTC (rev 5426)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysDictionary.h 2010-12-01 13:24:53 UTC (rev 5427)
@@ -58,6 +58,11 @@
cs_Csdef_ * csdef(const char *kpName);
CCoordinateSystemEnum* GetEnumImp();
+ //static (helper) members
+ void DoCsDefPostReadProcessing(cs_Csdef_* pDef);
+ static MgDisposableCollection* ReadAllCoordinateSystems(MgCoordinateSystemDictionaryBase* targetDictionary, const std::vector<MgCoordinateSystemFilter*>* const filters);
+ MgCoordinateSystem* GetCoordinateSystem(const cs_Csdef_* csDef, const std::vector<std::map<STRING,Ptr<MgDisposable> >*>* const datumEllipsoidInfos);
+
private:
//Unimplemented stuff
CCoordinateSystemDictionary();
Modified: trunk/MgDev/Common/CoordinateSystem/CoordSysEllipsoidDictionary.cpp
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysEllipsoidDictionary.cpp 2010-12-01 11:11:48 UTC (rev 5426)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysEllipsoidDictionary.cpp 2010-12-01 13:24:53 UTC (rev 5427)
@@ -188,8 +188,6 @@
return CS_eldef(kpName);
}
- throw new MgInvalidOperationException(L"CCoordinateSystemEllipsoidDictionary.eldef", __LINE__, __WFILE__, NULL, L"", NULL);
-
//It's an old version. We need to do a special search
//in the file, and then, if found, update it to a current struct.
UINT32 nStructSize, nNameSize;
@@ -462,6 +460,7 @@
return GetEllipsoid(sName);
}
+//--------------------------------------------------------------
MgCoordinateSystemEllipsoid* CCoordinateSystemEllipsoidDictionary::GetEllipsoid(CREFSTRING sName)
{
Ptr<MgCoordinateSystemEllipsoid> pEllipsoidDef;
@@ -473,11 +472,6 @@
//Get the name to search for
pName = Convert_Wide_To_Ascii(sName.c_str()); //need to delete [] pName
- if (NULL == pName)
- {
- throw new MgOutOfMemoryException(L"MgCoordinateSystemEllipsoidDictionary.GetEllipsoid", __LINE__, __WFILE__, NULL, L"", NULL);
- }
-
//Look in the dictionary
pDef = eldef(pName);
@@ -492,17 +486,19 @@
//Okay, at this point we have a Mentor ellipsoid definition
//struct. Build an object out of it.
//Try to get the def from the set
- pEllipsoidDef = BuildInterfaceFromElDef(*pDef, m_pCatalog);
+ pEllipsoidDef = this->GetEllipsoid(pDef);
+ assert(NULL != pEllipsoidDef);
- if (NULL == pEllipsoidDef.p)
+ MG_CATCH(L"MgCoordinateSystemEllipsoidDictionary.GetEllipsoid")
+
+ if (NULL != pDef)
{
- throw new MgCoordinateSystemInitializationFailedException(L"MgCoordinateSystemEllipsoidDictionary.GetEllipsoid", __LINE__, __WFILE__, NULL, L"", NULL);
+ CS_free(pDef);
+ pDef = NULL;
}
- //And return success!
- MG_CATCH(L"MgCoordinateSystemEllipsoidDictionary.GetEllipsoid")
- CS_free(pDef);
delete [] pName;
+ pName = NULL;
MG_THROW()
@@ -510,6 +506,20 @@
}
//--------------------------------------------------------------
+//needed to work with the [ReadAllEllipsoids] method
+MgCoordinateSystemEllipsoid* CCoordinateSystemEllipsoidDictionary::GetEllipsoid(const cs_Eldef_* elDef, const std::vector<std::map<STRING,Ptr<MgDisposable> >*>* const /* unused */)
+{
+ Ptr<MgCoordinateSystemEllipsoid> pEllipsoidDef = BuildInterfaceFromElDef(*elDef, m_pCatalog);
+
+ if (NULL == pEllipsoidDef.p)
+ {
+ throw new MgCoordinateSystemInitializationFailedException(L"MgCoordinateSystemEllipsoidDictionary.GetEllipsoid", __LINE__, __WFILE__, NULL, L"", NULL);
+ }
+
+ return pEllipsoidDef.Detach();
+}
+
+//--------------------------------------------------------------
//Returns whether the set contains a def with the specified name.
bool CCoordinateSystemEllipsoidDictionary::Has(CREFSTRING sName)
{
@@ -609,10 +619,31 @@
//Set it up to use our list
pNew->Initialize(this, m_pmapSystemNameDescription);
+ pNew->SetReadAllDefinitionCallback(CCoordinateSystemEllipsoidDictionary::ReadAllEllipsoids);
return pNew.Detach();
}
+//----------------------------------------------------------------------
+MgDisposableCollection* CCoordinateSystemEllipsoidDictionary::ReadAllEllipsoids(/*IN, required*/MgCoordinateSystemDictionaryBase* targetDictionary,
+ /*IN, optional*/const std::vector<MgCoordinateSystemFilter*>* const filters)
+{
+ if (NULL == targetDictionary)
+ throw new MgNullArgumentException(L"CCoordinateSystemEllipsoidDictionary.ReadAllEllipsoids", __LINE__, __WFILE__, NULL, L"", NULL);
+
+ CCoordinateSystemEllipsoidDictionary* ellipsoidDictionary = dynamic_cast<CCoordinateSystemEllipsoidDictionary*>(targetDictionary);
+ if (NULL == ellipsoidDictionary)
+ throw new MgInvalidArgumentException(L"CCoordinateSystemEllipsoidDictionary.ReadAllEllipsoids", __LINE__, __WFILE__, NULL, L"", NULL);
+
+ return MentorDictionary::ReadAllDefinitions<MgCoordinateSystemEllipsoid, cs_Eldef_, CCoordinateSystemEllipsoidDictionary>(
+ ellipsoidDictionary,
+ CS_elrd,
+ NULL, //no post processing needed
+ &CCoordinateSystemEllipsoidDictionary::GetEllipsoid,
+ NULL, //no additional info needed/used to create an MgCoordinateSystemEllipsoid object
+ filters);
+}
+
//MgDisposable
void CCoordinateSystemEllipsoidDictionary::Dispose()
{
Modified: trunk/MgDev/Common/CoordinateSystem/CoordSysEllipsoidDictionary.h
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysEllipsoidDictionary.h 2010-12-01 11:11:48 UTC (rev 5426)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysEllipsoidDictionary.h 2010-12-01 13:24:53 UTC (rev 5427)
@@ -58,6 +58,9 @@
cs_Eldef_ * eldef(const char *kpName) const;
CCoordinateSystemEnumEllipsoid* GetEnumImp();
+ static MgDisposableCollection* ReadAllEllipsoids(MgCoordinateSystemDictionaryBase* targetDictionary, const std::vector<MgCoordinateSystemFilter*>* const filters);
+ MgCoordinateSystemEllipsoid* GetEllipsoid(const cs_Eldef_* elDef, const std::vector<std::map<STRING,Ptr<MgDisposable> >*>* const /* unused */ = NULL);
+
private:
//Unimplemented stuff
CCoordinateSystemEllipsoidDictionary();
Modified: trunk/MgDev/Common/CoordinateSystem/CoordSysEnum.cpp
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysEnum.cpp 2010-12-01 11:11:48 UTC (rev 5426)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysEnum.cpp 2010-12-01 13:24:53 UTC (rev 5427)
@@ -26,7 +26,7 @@
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CCoordinateSystemEnum::CCoordinateSystemEnum() :
- m_pmapSystemNameDescription(NULL)
+ m_pmapSystemNameDescription(NULL), m_readAllDefCallback(NULL)
{
}
@@ -66,6 +66,8 @@
{
m_pmapSystemNameDescription = NULL;
m_pDict = NULL;
+ m_readAllDefCallback = NULL;
+
ClearFilter();
}
@@ -93,6 +95,7 @@
}
//----------------------------------------------------------
+//Reads the entries from the parent dictionary
MgDisposableCollection* CCoordinateSystemEnum::Next(UINT32 ulCount)
{
Ptr<MgDisposableCollection> pOutput;
@@ -103,6 +106,25 @@
{
throw new MgOutOfMemoryException(L"MgCoordinateSystemEnum.Next", __LINE__, __WFILE__, NULL, L"", NULL);
}
+
+ //optimization:
+ //if the caller intends to read all information at once, that is...
+ // - if our iterator points to the map's beginning and
+ // - the number of entries to read is at least the size of the entries we know of
+ //
+ //use the the callback (if there's any) into our parent dictionary to read all entries
+ if (ulCount >= this->m_pmapSystemNameDescription->size() && this->m_iter == this->m_pmapSystemNameDescription->begin())
+ {
+ if (NULL != this->m_readAllDefCallback)
+ {
+ pOutput = this->m_readAllDefCallback(this->m_pDict, &this->m_vectFilter);
+ this->m_iter = this->m_pmapSystemNameDescription->end(); //set our iterator to end() as we've read all entries
+
+ return pOutput.Detach();
+ }
+ }
+
+ //default behavior - read each entry one by one and add it to the list to be returned
for (; m_iter != m_pmapSystemNameDescription->end(); m_iter++)
{
if (pOutput->GetCount() == ulCount)
@@ -358,7 +380,17 @@
SAFE_ADDREF(m_vectFilter[i]);
}
+ pNew->m_readAllDefCallback = this->m_readAllDefCallback;
+
MG_CATCH_AND_THROW(L"MgCoordinateSystemEnum.CreateClone")
return pNew.Detach();
}
+
+//----------------------------------------------------------
+//Sets the [m_readAllDefCallback] member; if set, the method
+//will be invoked by [::Next(UINT32)]
+void CCoordinateSystemEnum::SetReadAllDefinitionCallback(ReadAllDictionaryDefinitionsCallback callback)
+{
+ this->m_readAllDefCallback = callback;
+}
\ No newline at end of file
Modified: trunk/MgDev/Common/CoordinateSystem/CoordSysEnum.h
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysEnum.h 2010-12-01 11:11:48 UTC (rev 5426)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysEnum.h 2010-12-01 13:24:53 UTC (rev 5427)
@@ -20,7 +20,15 @@
namespace CSLibrary
{
-
+ //defines the callback that's being invoked, when *all* definitions are to be read from the dictionary
+ //as passed in by [targetDictionary]
+ //
+ //param targetDictionary: the dictionary to read all MgCs objects from
+ //param filters: a list of filters to determine, whether an MgCs object found should be added to the list being returned; can be null or empty
+ //
+ //return: MgDisposableCollection that contains the filtered MgCs objects from the dictionary. The caller has to release it
+ typedef MgDisposableCollection* (*ReadAllDictionaryDefinitionsCallback)(MgCoordinateSystemDictionaryBase* targetDictionary, const std::vector<MgCoordinateSystemFilter*>* const filters);
+
class CCoordinateSystemEnum : public MgCoordinateSystemEnum
{
public:
@@ -38,6 +46,8 @@
virtual MgStringCollection* NextName(UINT32 ulCount);
virtual MgStringCollection* NextDescription(UINT32 ulCount);
+ void SetReadAllDefinitionCallback(ReadAllDictionaryDefinitionsCallback callback);
+
protected:
virtual void Dispose();
@@ -52,6 +62,7 @@
CSystemNameDescriptionMap::iterator m_iter;
Ptr<MgCoordinateSystemDictionaryBase> m_pDict;
std::vector<MgCoordinateSystemFilter*> m_vectFilter;
+ ReadAllDictionaryDefinitionsCallback m_readAllDefCallback;
private:
CCoordinateSystemEnum(const CCoordinateSystemEnum&);
Modified: trunk/MgDev/Common/CoordinateSystem/MentorDictionary.cpp
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/MentorDictionary.cpp 2010-12-01 11:11:48 UTC (rev 5426)
+++ trunk/MgDev/Common/CoordinateSystem/MentorDictionary.cpp 2010-12-01 13:24:53 UTC (rev 5427)
@@ -154,8 +154,7 @@
_ASSERT(!sFileName.empty());
- //ABA: don't understand the rational behind the logic here - if the file name is empty we're doing nothing?
- if (!sFileName.empty()) //ABA: should it be rather [sDirectory]; if filename is given, also a path must have been given?
+ if (!sFileName.empty())
{
if (sDirectory.empty())
{
@@ -185,9 +184,13 @@
}//if dictionary is specified
//ok, so, save the file name
- //ABA: sFileName is never touched - same with sFileNameSet; why would a caller wanted us to that
- //is it rather [sFileNameSet = sPath]?
sFileNameSet=sFileName;
MG_CATCH_AND_THROW(kpMethodName)
}
+
+//Default callback used to force opening an arbitrary dictionary file in reading mode
+CsDictionaryOpenMode MentorDictionary::OpenReadDictionaryOpenCallback(long dictMagicNumber)
+{
+ return Read;
+}
Modified: trunk/MgDev/Common/CoordinateSystem/MentorDictionary.h
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/MentorDictionary.h 2010-12-01 11:11:48 UTC (rev 5426)
+++ trunk/MgDev/Common/CoordinateSystem/MentorDictionary.h 2010-12-01 13:24:53 UTC (rev 5427)
@@ -27,18 +27,116 @@
#ifndef MG_MENTORDICTIONARY_H
#define MG_MENTORDICTIONARY_H
+
#pragma once
+#include <memory>
+
#include "MentorUtil.h"
#include "Foundation.h"
#define DICTIONARY_SYS_DEF 1
+#define CALL_MEMBER_FN(object,ptrToMember) ((object)->*(ptrToMember))
+
namespace MentorDictionary
{
void SetFileName(INT32& lMagic, CsDictionaryOpenMode (*ValidMagic)(long), CREFSTRING sDirectory, CREFSTRING sFileName, REFSTRING sFileNameSet, const wchar_t* kpMethodName);
csFILE* Open(INT32& lMagic, CsDictionaryOpenMode (*ValidMagic)(long), const wchar_t* kpPath, CsDictionaryOpenMode nOpenMode);
+ CsDictionaryOpenMode OpenReadDictionaryOpenCallback(long dictMagicNumber);
+ //reads the next 'CsMap' entry from the file passed in by [pFile]
+ //the file is assumed to have been opened already
+ //returns:
+ // [true]: if an entry has been read
+ // [false]: if no entry has been read, i.e. EOF has been reached
+ //
+ //throws an [MgFileIoException] for any other condition, e.g. CsMap has encountered unexpected content
+ template <class T>
+ bool GetNextEntry(csFILE *pFile, T& def, int& nCrypt, int (*CS_Trd)(csFILE*, T *, int *))
+ {
+ int nResult = CS_Trd(pFile, &def, &nCrypt);
+ if (nResult > 0) //read successfull
+ return true;
+
+ if (0 == nResult) //we've reached the file's end
+ return false;
+
+ //i.e. nResult < 0
+ throw new MgFileIoException(L"MentorDictionary.GetNextEntry", __LINE__, __WFILE__, NULL, L"", NULL);
+ }
+
+ //iterates through all entries return a vector of definitions in the same order as they've been returned by CsMap
+ //return NULL, if the file couldn't be read successfully
+ template <class T>
+ vector<T>*
+ ReadDictionaryEntries(
+ csFILE *pFile,
+ int (*CS_Trd)(csFILE*, T *, int *))
+ {
+ //Scan through the file - add an entry for each definition we find
+ try
+ {
+ auto_ptr<vector<T> > allDictEntries(new vector<T>);
+
+ int nCrypt;
+ T def;
+
+ while (MentorDictionary::GetNextEntry(pFile, def, nCrypt, CS_Trd))
+ {
+ allDictEntries->push_back(def);
+
+ } //for each def in the file
+
+ return allDictEntries.release();
+ }
+ catch(MgFileIoException* ioException)
+ {
+ ioException->Release();
+ }
+ catch (std::bad_alloc&)
+ {
+ }
+
+ return NULL;
+ }
+
+ //opens a dictionary file for reading and then iterates over all entries and returns them as a vector; the order is the same as returned by CsMap
+ //before accessing the file, a global lock is placed through an [SmartCriticalClass] object
+ template <class T>
+ vector<T>* ReadDictionaryEntries(
+ /*IN*/ MgCoordinateSystemDictionaryBase* targetDictionary,
+ /*IN*/ int (*CS_Trd)(csFILE*, T *, int *))
+ {
+ auto_ptr<vector<T> > allDefs;
+ csFILE *pFile = NULL;
+
+ MG_TRY()
+
+ INT32 dictionaryMagicNumber;
+
+ SmartCriticalClass critical(true);
+
+ STRING strPath = targetDictionary->GetPath();
+ pFile = MentorDictionary::Open(dictionaryMagicNumber, OpenReadDictionaryOpenCallback, strPath.c_str(), Read);
+
+ allDefs.reset(MentorDictionary::ReadDictionaryEntries<T>(pFile, CS_Trd));
+ if (NULL == allDefs.get())
+ throw new MgInvalidArgumentException(L"MentorDictionary.ReadDictionaryEntries", __LINE__, __WFILE__, NULL, L"", NULL);
+
+ MG_CATCH(L"MentorDictionary.ReadDictionaryEntries")
+
+ bool fileClosed = (0 == CS_fclose(pFile));
+ pFile = NULL;
+
+ if (!fileClosed && NULL == mgException)
+ throw new MgFileIoException(L"MentorDictionary.ReadDictionaryEntries", __LINE__, __WFILE__, NULL, L"MgCoordinateSystemDictionaryCloseFailedException", NULL);
+
+ MG_THROW()
+
+ return allDefs.release();
+ }
+
//Template function which generates a summary from a dictionary
//file. The caller is responsible for deleting the returned map.
//Function returns NULL if it runs out of memory. Note that this
@@ -63,46 +161,146 @@
CS_fseek(pFile, sizeof(cs_magic_t), SEEK_SET);
assert(!ferror(pFile));
- //Make a collection to return.
- CSystemNameDescriptionMap *pmapSystemNameDescription = new CSystemNameDescriptionMap;
- if (NULL == pmapSystemNameDescription) return NULL;
-
- //Scan through the file, inserting a summary entry
- //for each def we encounter.
- int nResult, nCrypt;
- T def;
try
{
- while ((nResult = CS_Trd(pFile, &def, &nCrypt)) > 0)
+ //Make a collection to return - we first read all entries from the dictionary file
+ //and use those to fill up the dictionary we're returning
+ auto_ptr<CSystemNameDescriptionMap> pmapSystemNameDescription(new CSystemNameDescriptionMap);
+
+ auto_ptr<vector<T> > allDictEntries(MentorDictionary::ReadDictionaryEntries(pFile, CS_Trd));
+ if (NULL == allDictEntries.get())
+ return NULL;
+
+ for(vector<T>::size_type i = 0; i < allDictEntries->size(); i++)
{
+ T& def = allDictEntries->at(i);
+
const char* keyName = CS_Tkey(def);
-
pmapSystemNameDescription->insert(
CSystemNameDescriptionPair(
CSystemName(keyName),
CSystemDescription(description(def))
)
);
- } //for each def in the file
+ }
+
+ return pmapSystemNameDescription.release();
}
- catch (std::bad_alloc)
+ catch(std::bad_alloc&)
{
- delete pmapSystemNameDescription;
- return NULL;
}
- if (nResult < 0)
+
+ return NULL;
+ }
+
+ //Reads all Mg definitions from the dictionary [targetDictionary] and returns them
+ //in the std::map [definitions], where the code is mapped to the MgDisposable
+ template <class T>
+ void ReadAllDefinitions(
+ /*IN, required*/ MgCoordinateSystemDictionaryBase* targetDictionary,
+ /*IN, required*/ STRING (T::*GetCode)(),
+ /*IN/OUT, required*/ std::map<STRING, Ptr<MgDisposable> >& definitions)
+ {
+ if (NULL == targetDictionary || NULL == GetCode)
+ throw new MgNullArgumentException(L"MentorDictionary.ReadAllDefinitions", __LINE__, __WFILE__, NULL, L"", NULL);
+
+ if (0 != definitions.size())
+ throw new MgInvalidArgumentException(L"MentorDictionary.ReadAllDefinitions", __LINE__, __WFILE__, NULL, L"", NULL);
+
+ const UINT32 entryCount = targetDictionary->GetSize();;
+
+ Ptr<MgCoordinateSystemEnum> entryEnum = targetDictionary->GetEnum();
+ Ptr<MgDisposableCollection> entryList = entryEnum->Next(entryCount);
+
+ for(INT32 entryIndex = 0; entryIndex < entryList->GetCount(); entryIndex++)
{
- //An error occurred while reading the file.
- delete pmapSystemNameDescription;
- return NULL;
+ Ptr<T> entry = static_cast<T*>(entryList->GetItem(entryIndex));
+ STRING entryCode = CALL_MEMBER_FN(entry, GetCode)();
+ definitions.insert(pair<STRING, Ptr<MgDisposable> >(entryCode, entry));
}
+ }
- //And we're done! Return the collection we've built.
- return pmapSystemNameDescription;
+ //takes the [toBeFiltered] MgDisposableCollection which is assumed to contain only items of type
+ //[T] and runs the [MgCoordinateSystemFilter]s passed in by [filters] on it (optional)
+ //the caller is responsible for deleting the collection being returned
+ //if [filters] is NULL or empty, the same(!) collection as passed by [toBeFiltered]
+ //is returned - but still the caller has to release it ([toBeFiltered] had been ADDREFed then)
+ template <class T>
+ MgDisposableCollection* FilterDefinitions(
+ /*IN, required*/MgDisposableCollection* toBeFiltered,
+ /*IN, optional*/const std::vector<MgCoordinateSystemFilter*>* const filters)
+ {
+ if (NULL == toBeFiltered)
+ throw new MgNullArgumentException(L"MentorDictionary.FilterDefinitions", __LINE__, __WFILE__, NULL, L"", NULL);
+
+ if (NULL == filters)
+ return SAFE_ADDREF(toBeFiltered); //see coment - the caller does always have to release the collection being returned
+
+ const std::vector<MgCoordinateSystemFilter*>::size_type filterCount = filters->size();
+ if (0 == filterCount)
+ return SAFE_ADDREF(toBeFiltered); //see coment - the caller does always have to release the collection being returned
+
+ Ptr<MgDisposableCollection> filteredCollection = new MgDisposableCollection();
+ for(std::vector<MgCoordinateSystemFilter*>::size_type j = 0; j < filterCount; j++)
+ {
+ Ptr<MgDisposable> disposableItem = toBeFiltered->GetItem(j);
+ T* mgCsItem = dynamic_cast<T*>(disposableItem.p);
+ if (NULL == mgCsItem)
+ throw new MgInvalidArgumentException(L"MentorDictionary.FilterDefinitions", __LINE__, __WFILE__, NULL, L"", NULL);
+
+ //exclude the [mgCsItem], if it's not accepted by the filter we got
+ if (filters->at(j)->IsFilteredOut(mgCsItem))
+ continue;
+
+ filteredCollection->Add(disposableItem);
+ }
+
+ return filteredCollection.Detach();
}
- #define CALL_MEMBER_FN(object,ptrToMember) ((object)->*(ptrToMember))
+ //Reads all definitions from the dictionary and returns them as an [MgDisposableCollection] the
+ //caller has to release
+ template <class T /* The MgCS type [primaryDictionary] contains*/, class U /* The CsMap struct type*/, class V /* The dictionary type that will return items of type T*/>
+ MgDisposableCollection* ReadAllDefinitions(
+ /*IN, required*/ V* primaryDictionary, //the primary MgCS dictionary to read the items of type T from
+ /*IN, required*/ int (*CS_Trd)(csFILE*, U *, int *), //The file access method as retrieved from CsMap
+ /*IN, optional*/ void (V::*PostProcess)(U*), //A method that's being called with the CsMap definition struct just read from the file
+ /*IN, required*/ T* (V::*GetMgItem)(const U*, const std::vector<std::map<STRING,Ptr<MgDisposable> >*>* const), //the method on the [primaryDictionary] to read the actual MgCS item from
+ /*IN, optional*/ const std::vector<std::map<STRING,Ptr<MgDisposable> >*>* const secondaryDictionaryInfos, //infos that have been read from the dictionaries before; will be passed to [V::*GetMgItem]
+ /*IN, optional*/ const std::vector<MgCoordinateSystemFilter*>* const filters) //a list of filters - if passed in, the [MgDisposableCollection] will be filtered before being returned
+ {
+ //'true' input parameter check
+ if (NULL == primaryDictionary)
+ throw new MgNullArgumentException(L"MentorDictionary.ReadAllDefinitionsCascaded", __LINE__, __WFILE__, NULL, L"", NULL);
+ //method pointer checks
+ if (NULL == GetMgItem || NULL == CS_Trd)
+ throw new MgNullArgumentException(L"MentorDictionary.ReadAllDefinitionsCascaded", __LINE__, __WFILE__, NULL, L"", NULL);
+
+ auto_ptr<vector<U> > allDefs(MentorDictionary::ReadDictionaryEntries<U>(primaryDictionary, CS_Trd));
+ if (NULL == allDefs.get()) //[ReadDictionaryEntries] will return NULL, if the dictionary entries couldn't be read
+ throw new MgInvalidArgumentException(L"MgCoordinateSystemDictionary.ReadAllCoordinateSystems", __LINE__, __WFILE__, NULL, L"", NULL);
+
+ const bool doPostProcess = (NULL != PostProcess);
+ Ptr<MgDisposableCollection> filteredDefinitions = new MgDisposableCollection();
+
+ //go through all defs as we've read them from CsMap, do some post processing and finally
+ //retrieve the MgCs item we'll later return to the caller
+ for(vector<U>::size_type i = 0; i < allDefs->size(); i++)
+ {
+ U csMapDef = allDefs->at(i); //don't work on the reference
+ if (doPostProcess)
+ CALL_MEMBER_FN(primaryDictionary, PostProcess)(&csMapDef);
+
+ Ptr<T> mgItem = CALL_MEMBER_FN(primaryDictionary, GetMgItem)(&csMapDef, secondaryDictionaryInfos); //throws an exception, if the entry hasn't been found
+ filteredDefinitions->Add(mgItem);
+ }
+
+ //we might get the same reference back - what isn't a problem as we're using the Ptr<> here
+ filteredDefinitions = MentorDictionary::FilterDefinitions<MgCoordinateSystem>(filteredDefinitions, filters);
+ return filteredDefinitions.Detach();
+ }
+
//Template function for updating a def in a dictionary.
//Works for ellipsoids, datums, and coordinate systems.
//The bAlreadyExists parameter specifies whether there
@@ -111,7 +309,6 @@
//is the corresponding public API interface (MgCoordinateSystem
//et al).
//
-
template <class T, class Tinterface>
void UpdateDef(
CSystemNameDescriptionMap *pmapSystemNameDescription,
More information about the mapguide-commits
mailing list