root/spike/sfcom_oledb/client/sfc_tutorial.dox

Revision 12207, 9.6 kB (checked in by warmerdam, 10 months ago)

segregate sfc/oledb client stuff into client directory for move to spike

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /*! \page sfc_tutorial Simple Features Client Tutorial
2
3 \section sfc_tutorial_intro Introduction
4
5 The Simple Features Client API is a set of classes, and support functions
6 that simplify access to OpenGIS SF OLE DB providers. <p>
7
8 Most of the classes are based on the ATL OLE DB consumer templates.  To fully
9 understand the classes it is critical to also review the Microsoft provided
10 information on these classes.  It can be accessed in the <a
11 href="http://msdn.microsoft.com/">MSDN Online Library</a>. <p>
12
13 In general terms, the OpenGIS SF COM interface specification requires
14 geographic data providers to make their datasets look like a database. 
15 A <b>data source</b> (usually a single data file, or group of related data
16 files) can contain one or more spatial tables which roughly correspond to
17 what be called layers in most systems.  Each table has a schema defining the
18 set of attributes (table fields) that apply to each feature in that table
19 (layer).  Each record in the table corresponds to a features, with a
20 set of attributes, and some geometry.  The geometry is stored in one field
21 of the table as a BLOB (binary large object) encoded in a particular format
22 (OpenGIS SF Well Known Binary Format). <p>
23
24 The Simple Features Client classes help model the different parts of this
25 data model:<p>
26
27 <ul>
28
29 <li> SFCEnumerator: This class allows the application to look through all
30 the OLE DB drivers installed on this system, including the ability to identify
31 which of these claim to be OpenGIS data providers.<p>
32
33 <li> SFCDataSource: This class allows a file to be opened with a data provider
34 (driver) selected from the SFCEnumerator.   It also provides a method to
35 instantiate an SFCTable for a particular table (layer) in that data source.
36 Eventually it will include methods to identify all the tables in the data
37 source, and to identify which of these is spatially enabled.  Some other
38 metadata about the datastore will also be available from this class.<p>
39
40 <li> SFCTable: This class allows a table (layer) in a data source to be read.
41 It includes SF COM related methods for extracting the geometry column and
42 translating them into in memory geometry objects using the
43 OGRGeometryFactory.
44
45 <li> OGRGeometry: This is the base class for all types of simple features
46 geometry.   Geometry objects returned from an SFCTable will be of a class
47 derived from OGRGeometry, and be queried with a variety of methods. 
48 Review the <a href="hierarchy.html">class hierarchy</a> to learn more about
49 the possible geometry types.
50
51 </ul>
52
53 \section sfc_tutorial_example Example Client
54
55 The console program SFCDUMP is intended to be an example of how to use
56 the client api (as well as being a useful debugging tool in it's own
57 right).  The full source should be available in
58 <a href="http://svn.osgeo.org/gdal/trunk/gdal/ogr/sfcdump.cpp" title="sfcdump.cpp linked directly from GDAL SVN">gdal/ogr/sfcdump.cpp</a>.<p>
59
60
61 \subsection sfc_tutorial_enum SFCEnumerator: Finding a Provider
62
63 The SFCEnumerator class is used to identify all the installed OLE DB
64 providers (drivers) installed on a system.  It essentially makes the
65 list of OLE DB providers appear to be a table.  The following code
66 sequence demonstrates how to create an SFCEnumerator, loop through all
67 the records, and print out some information for each record.<p>
68
69 <pre>
70 static void SFCDumpProviders()
71
72 {
73     SFCEnumerator      oEnum;
74
75     printf( "Available OLE DB Providers\n" );
76     printf( "==========================\n" );
77
78     if( FAILED(oEnum.Open()) )
79     {
80         printf( "Failed to initialize SFCEnumerator.\n" );
81         return;
82     }
83
84     while( oEnum.MoveNext() == S_OK )
85     {
86         printf( "%S: %S\n",
87                 oEnum.m_szName, oEnum.m_szDescription );
88
89         if( oEnum.IsOGISProvider() )
90             printf( "    (OGISDataProvider)\n" );
91
92         printf( "\n" );
93     }
94 }
95 </pre>
96
97 Some things to note are that:
98
99 <ul>
100 <li> The m_szName, and m_szDescription data members are unicode strings,
101 so we have to use %S instead of %s to display them. <p>
102
103 <li> The MoveNext() method is used to go from record to record.  This is
104 the same method used to read records in an SFCTable. <p>
105
106 <li> The IsOGISProvider() method will query the registry to see if the
107 provider claims to be an OGISDataProvider.  Generic databases such as
108 MS Access can still be used to store spatial data, but they will generally
109 be less completely configured, and less capable than a OGIS data provider.<p>
110
111 <li> The SFCEnumerator hides all the COM machinery such as
112 instantiating COM objects, querying for interfaces and maintaining reference
113 counts.<p>
114
115 </ul>
116
117 \subsection sfc_tutorial_open Opening a Simple Features File
118
119 In order to open a file with OGIS simple features information in it, the
120 following steps should be followed.  First, it is necessary to identify the
121 provider to use.  In this example the user gives the provider name as a
122 string, perhaps after having reviewed a list of possible providers from
123 SFCDumpProviders().  Second, the filename is needed for the creation of
124 an SFCDataStore.<p>
125
126 <pre>
127 static SFCDataSource * SFCOpenDataSource( const char * pszProvider,
128                                           const char * pszDataSource )
129
130 {
131     SFCEnumerator      oEnumerator;
132
133     if( FAILED(oEnumerator.Open()) )
134     {
135         printf( "Can't open ole db enumerator.\n" );
136         return NULL;
137     }
138
139     if( !oEnumerator.Find((char*) pszProvider) )
140     {
141         printf( "Can't find OLE DB provider `%s'.\n", pszProvider );
142         return NULL;
143     }
144
145     SFCDataSource *poDS;
146
147     poDS = new SFCDataSource;
148
149     if( FAILED(poDS->Open( oEnumerator, pszDataSource  )) )
150     {
151         delete poDS;
152         printf( "Attempt to access datasource %s failed.\n",
153                 pszDataSource );
154         return NULL;
155     }
156     else
157         return poDS;
158 }
159 </pre>
160
161 Some interesting things to note are that:<p>
162
163 <ul>
164 <li> We open the SFCEnumerator the same as in the previous example, but
165 use the Find() method to find the record with a particular m_pszName.  We
166 could have read through record by record and stopped on the record we wanted
167 instead.<p>
168
169 <li> The SFCDataSource::Open() method takes in an enumerator.  The data
170 source is created based on the provider of the currently selected row in
171 the passed enumerator.  The other argument is the filename to open.<p>
172
173 <li> The SFCEnumerator isn't needed after the SFCDataSource has been
174 created, so we let it fall out of scope and be destroyed at the end of
175 the function.<p>
176
177 <li> The provider and data source strings are all passed as simple C
178 strings.  The classes take care of internally translating to unicode when
179 needed.<p>
180
181 </ul>
182
183 \subsection sfc_tutorial_access Accessing an SFCTable
184
185 The SFCDataSource that we opened could have a number of spatial, and non
186 spatial tables in it.  Eventually the SFCDataSource will include methods for
187 identifying these.  For the time being it is necessary to know apriori what
188 the table (layer) to access is called.  The following code shows how to
189 instantiate an SFCTable from within a data store.<p>
190
191 <pre>
192     SFCDataSource      *poDS;
193
194     poDS = SFCOpenDataSource( pszProvider, pszDataSource );
195     if( poDS == NULL )
196         goto CleanupAndExit;
197
198     SFCTable      *poTable;
199
200     poTable = poDS->CreateSFCTable( pszTable );
201
202     delete poDS;
203
204     if( poTable == NULL )
205     {
206         printf( "Failed to open table %s.\n",  pszTable );
207         goto CleanupAndExit;
208     }
209 </pre>
210
211 Things to note are:
212
213 <ul>
214 <li> After creating the SFCTable we no longer need the SFCDataSource, so
215 we delete it.  The underlying data source/file remains open because the
216 SFCTable is using it, but the SFCDataSource object no longer exists holding
217 a reference on the data source.<p>
218
219 <li> There is little information provided about what error occured if
220 things go wrong within the CreateSFCTable() method or others.  Eventually the
221 SFC classes may through exceptions with more information when things go
222 wrong. <p>
223
224 </ul>
225
226 \subsection sfc_tutorial_read Reading the Features
227
228 The following example shows reading through all the records in a
229 simple features table, and reading back just the geometry column.
230 It is instantiated into a geometry object, which is then dumped
231 to stdout. <p>
232
233 <pre>
234 static void SFCDumpTableGeometry( SFCTable * poTable )
235
236 {
237     HRESULT      hr;
238
239     while( !FAILED((hr = poTable->MoveNext())) )
240     {
241         OGRGeometry * poGeom;
242
243         poGeom = poTable->GetOGRGeometry();
244         poTable->ReleaseIUnknowns();
245
246         if( poGeom == NULL )
247         {
248             printf( "Failed to reconstitute geometry!\n" );
249             break;
250         }
251         else
252         {
253             poGeom->dumpReadable( stdout );
254             delete poGeom;
255         }
256     }
257 }
258 </pre>
259
260 Things to note:
261
262 <ul>
263 <li> The MoveNext() method is used to read records.
264 <li> The SFCTable keeps track of which column contains the geometry.
265 <li> It is necessary to call SFCTable::ReleaseIUnknowns() for every
266 record read in an SFCTable!  Failure to do so may cause serious
267 problems.  Calling it twice for the same record is likely to
268 result in a crash.
269 <li> The OGRGeometry object created by GetOGRGeometry() is now the
270 responsibility of the caller which must delete it.<p>
271 <li> While note shown here, there is also a GetWKBGeometry() method on
272 the SFCTable for applications that want the binary form of the
273 geometry for their own purposes. <p>
274 <li> All the other fields in this table are also available; however, this
275 example doesn't show how to access them.<p>
276 </ul>
277
278 <hr>
279
280 Items to add:
281
282 <ol>
283 <li> Information on getting the schema.<p>
284 <li> Information on accessing other attribute fields.<p>
285 <li> Rewrite error handling when error handling semantics worked out.<p>
286 <li> Rewrite table selection when table selection semantics are available.<p>
287 </ol>
288
289 \htmlonly
290 <p>
291 $Id$
292 </p>
293 \endhtmlonly
294
295 */
Note: See TracBrowser for help on using the browser.