1 : /**********************************************************************
2 : * $Id: gmlfeatureclass.cpp 20020 2010-07-11 11:02:09Z rouault $
3 : *
4 : * Project: GML Reader
5 : * Purpose: Implementation of GMLFeatureClass.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : **********************************************************************
9 : * Copyright (c) 2002, Frank Warmerdam
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "gmlreader.h"
31 : #include "cpl_conv.h"
32 : #include "ogr_core.h"
33 :
34 : /************************************************************************/
35 : /* GMLFeatureClass() */
36 : /************************************************************************/
37 :
38 57 : GMLFeatureClass::GMLFeatureClass( const char *pszName )
39 :
40 : {
41 57 : m_pszName = CPLStrdup( pszName );
42 57 : m_pszElementName = NULL;
43 57 : m_pszGeometryElement = NULL;
44 57 : m_nPropertyCount = 0;
45 57 : m_papoProperty = NULL;
46 57 : m_bSchemaLocked = FALSE;
47 :
48 57 : m_pszExtraInfo = NULL;
49 57 : m_bHaveExtents = FALSE;
50 57 : m_nFeatureCount = -1; // unknown
51 :
52 57 : m_nGeometryType = 0; // wkbUnknown
53 57 : }
54 :
55 : /************************************************************************/
56 : /* ~GMLFeatureClass() */
57 : /************************************************************************/
58 :
59 57 : GMLFeatureClass::~GMLFeatureClass()
60 :
61 : {
62 57 : CPLFree( m_pszName );
63 57 : CPLFree( m_pszElementName );
64 57 : CPLFree( m_pszGeometryElement );
65 :
66 301 : for( int i = 0; i < m_nPropertyCount; i++ )
67 244 : delete m_papoProperty[i];
68 57 : CPLFree( m_papoProperty );
69 57 : }
70 :
71 : /************************************************************************/
72 : /* GetProperty(int) */
73 : /************************************************************************/
74 :
75 1046702 : GMLPropertyDefn *GMLFeatureClass::GetProperty( int iIndex ) const
76 :
77 : {
78 1046702 : if( iIndex < 0 || iIndex >= m_nPropertyCount )
79 278 : return NULL;
80 : else
81 1046424 : return m_papoProperty[iIndex];
82 : }
83 :
84 : /************************************************************************/
85 : /* GetPropertyIndex() */
86 : /************************************************************************/
87 :
88 2118 : int GMLFeatureClass::GetPropertyIndex( const char *pszName ) const
89 :
90 : {
91 2789 : for( int i = 0; i < m_nPropertyCount; i++ )
92 2507 : if( EQUAL(pszName,m_papoProperty[i]->GetName()) )
93 1836 : return i;
94 :
95 282 : return -1;
96 : }
97 :
98 : /************************************************************************/
99 : /* AddProperty() */
100 : /************************************************************************/
101 :
102 244 : int GMLFeatureClass::AddProperty( GMLPropertyDefn *poDefn )
103 :
104 : {
105 244 : CPLAssert( GetProperty(poDefn->GetName()) == NULL );
106 :
107 244 : m_nPropertyCount++;
108 : m_papoProperty = (GMLPropertyDefn **)
109 244 : CPLRealloc( m_papoProperty, sizeof(void*) * m_nPropertyCount );
110 :
111 244 : m_papoProperty[m_nPropertyCount-1] = poDefn;
112 :
113 244 : return m_nPropertyCount-1;
114 : }
115 :
116 : /************************************************************************/
117 : /* SetElementName() */
118 : /************************************************************************/
119 :
120 45 : void GMLFeatureClass::SetElementName( const char *pszElementName )
121 :
122 : {
123 45 : CPLFree( m_pszElementName );
124 45 : m_pszElementName = CPLStrdup( pszElementName );
125 45 : }
126 :
127 : /************************************************************************/
128 : /* GetElementName() */
129 : /************************************************************************/
130 :
131 1571189 : const char *GMLFeatureClass::GetElementName() const
132 :
133 : {
134 1571189 : if( m_pszElementName == NULL )
135 121 : return m_pszName;
136 : else
137 1571068 : return m_pszElementName;
138 : }
139 :
140 : /************************************************************************/
141 : /* SetGeometryElement() */
142 : /************************************************************************/
143 :
144 2 : void GMLFeatureClass::SetGeometryElement( const char *pszElement )
145 :
146 : {
147 2 : CPLFree( m_pszGeometryElement );
148 2 : m_pszGeometryElement = CPLStrdup( pszElement );
149 2 : }
150 :
151 : /************************************************************************/
152 : /* GetFeatureCount() */
153 : /************************************************************************/
154 :
155 125 : int GMLFeatureClass::GetFeatureCount()
156 :
157 : {
158 125 : return m_nFeatureCount;
159 : }
160 :
161 : /************************************************************************/
162 : /* SetFeatureCount() */
163 : /************************************************************************/
164 :
165 69 : void GMLFeatureClass::SetFeatureCount( int nNewCount )
166 :
167 : {
168 69 : m_nFeatureCount = nNewCount;
169 69 : }
170 :
171 : /************************************************************************/
172 : /* GetExtraInfo() */
173 : /************************************************************************/
174 :
175 0 : const char *GMLFeatureClass::GetExtraInfo()
176 :
177 : {
178 0 : return m_pszExtraInfo;
179 : }
180 :
181 : /************************************************************************/
182 : /* SetExtraInfo() */
183 : /************************************************************************/
184 :
185 0 : void GMLFeatureClass::SetExtraInfo( const char *pszExtraInfo )
186 :
187 : {
188 0 : CPLFree( m_pszExtraInfo );
189 0 : m_pszExtraInfo = NULL;
190 :
191 0 : if( pszExtraInfo != NULL )
192 0 : m_pszExtraInfo = CPLStrdup( pszExtraInfo );
193 0 : }
194 :
195 : /************************************************************************/
196 : /* SetExtents() */
197 : /************************************************************************/
198 :
199 : void GMLFeatureClass::SetExtents( double dfXMin, double dfXMax,
200 65 : double dfYMin, double dfYMax )
201 :
202 : {
203 65 : m_dfXMin = dfXMin;
204 65 : m_dfXMax = dfXMax;
205 65 : m_dfYMin = dfYMin;
206 65 : m_dfYMax = dfYMax;
207 :
208 65 : m_bHaveExtents = TRUE;
209 65 : }
210 :
211 : /************************************************************************/
212 : /* GetExtents() */
213 : /************************************************************************/
214 :
215 : int GMLFeatureClass::GetExtents( double *pdfXMin, double *pdfXMax,
216 25 : double *pdfYMin, double *pdfYMax )
217 :
218 : {
219 25 : if( m_bHaveExtents )
220 : {
221 16 : *pdfXMin = m_dfXMin;
222 16 : *pdfXMax = m_dfXMax;
223 16 : *pdfYMin = m_dfYMin;
224 16 : *pdfYMax = m_dfYMax;
225 : }
226 :
227 25 : return m_bHaveExtents;
228 : }
229 :
230 : /************************************************************************/
231 : /* InitializeFromXML() */
232 : /************************************************************************/
233 :
234 45 : int GMLFeatureClass::InitializeFromXML( CPLXMLNode *psRoot )
235 :
236 : {
237 : /* -------------------------------------------------------------------- */
238 : /* Do some rudimentary checking that this is a well formed */
239 : /* node. */
240 : /* -------------------------------------------------------------------- */
241 45 : if( psRoot == NULL
242 : || psRoot->eType != CXT_Element
243 : || !EQUAL(psRoot->pszValue,"GMLFeatureClass") )
244 : {
245 : CPLError( CE_Failure, CPLE_AppDefined,
246 : "GMLFeatureClass::InitializeFromXML() called on %s node!",
247 0 : psRoot->pszValue );
248 0 : return FALSE;
249 : }
250 :
251 45 : if( CPLGetXMLValue( psRoot, "Name", NULL ) == NULL )
252 : {
253 : CPLError( CE_Failure, CPLE_AppDefined,
254 0 : "GMLFeatureClass has no <Name> element." );
255 0 : return FALSE;
256 : }
257 :
258 : /* -------------------------------------------------------------------- */
259 : /* Collect base info. */
260 : /* -------------------------------------------------------------------- */
261 45 : CPLFree( m_pszName );
262 45 : m_pszName = CPLStrdup( CPLGetXMLValue( psRoot, "Name", NULL ) );
263 :
264 45 : SetElementName( CPLGetXMLValue( psRoot, "ElementPath", m_pszName ) );
265 :
266 45 : const char *pszGPath = CPLGetXMLValue( psRoot, "GeometryElementPath", "" );
267 :
268 45 : if( strlen( pszGPath ) > 0 )
269 2 : SetGeometryElement( pszGPath );
270 :
271 45 : const char* pszGeometryType = CPLGetXMLValue( psRoot, "GeometryType", NULL );
272 45 : if( pszGeometryType != NULL )
273 : {
274 36 : int nGeomType = atoi(pszGeometryType) & (~wkb25DBit);
275 72 : if ((nGeomType >= 0 && nGeomType <= 7) || nGeomType == 100)
276 36 : SetGeometryType( atoi(pszGeometryType) );
277 : else
278 : {
279 : CPLError(CE_Warning, CPLE_AppDefined, "Unrecognised geometry type : %s",
280 0 : pszGeometryType);
281 : }
282 : }
283 :
284 : /* -------------------------------------------------------------------- */
285 : /* Collect dataset specific info. */
286 : /* -------------------------------------------------------------------- */
287 45 : CPLXMLNode *psDSI = CPLGetXMLNode( psRoot, "DatasetSpecificInfo" );
288 45 : if( psDSI != NULL )
289 : {
290 : const char *pszValue;
291 :
292 43 : pszValue = CPLGetXMLValue( psDSI, "FeatureCount", NULL );
293 43 : if( pszValue != NULL )
294 43 : SetFeatureCount( atoi(pszValue) );
295 :
296 : // Eventually we should support XML subtrees.
297 43 : pszValue = CPLGetXMLValue( psDSI, "ExtraInfo", NULL );
298 43 : if( pszValue != NULL )
299 0 : SetExtraInfo( pszValue );
300 :
301 43 : if( CPLGetXMLValue( psDSI, "ExtentXMin", NULL ) != NULL
302 : && CPLGetXMLValue( psDSI, "ExtentXMax", NULL ) != NULL
303 : && CPLGetXMLValue( psDSI, "ExtentYMin", NULL ) != NULL
304 : && CPLGetXMLValue( psDSI, "ExtentYMax", NULL ) != NULL )
305 : {
306 : SetExtents( CPLAtof(CPLGetXMLValue( psDSI, "ExtentXMin", "0.0" )),
307 : CPLAtof(CPLGetXMLValue( psDSI, "ExtentXMax", "0.0" )),
308 : CPLAtof(CPLGetXMLValue( psDSI, "ExtentYMin", "0.0" )),
309 40 : CPLAtof(CPLGetXMLValue( psDSI, "ExtentYMax", "0.0" )) );
310 : }
311 : }
312 :
313 : /* -------------------------------------------------------------------- */
314 : /* Collect property definitions. */
315 : /* -------------------------------------------------------------------- */
316 417 : for( CPLXMLNode *psThis = psRoot->psChild;
317 : psThis != NULL; psThis = psThis->psNext )
318 : {
319 372 : if( EQUAL(psThis->pszValue, "PropertyDefn") )
320 : {
321 201 : const char *pszName = CPLGetXMLValue( psThis, "Name", NULL );
322 201 : const char *pszType = CPLGetXMLValue( psThis, "Type", "Untyped" );
323 : GMLPropertyDefn *poPDefn;
324 :
325 201 : if( pszName == NULL )
326 : {
327 : CPLError( CE_Failure, CPLE_AppDefined,
328 : "GMLFeatureClass %s has a PropertyDefn without a <Name>..",
329 0 : m_pszName );
330 0 : return FALSE;
331 : }
332 :
333 : poPDefn = new GMLPropertyDefn(
334 201 : pszName, CPLGetXMLValue( psThis, "ElementPath", NULL ) );
335 :
336 201 : if( EQUAL(pszType,"Untyped") )
337 7 : poPDefn->SetType( GMLPT_Untyped );
338 194 : else if( EQUAL(pszType,"String") )
339 : {
340 136 : poPDefn->SetType( GMLPT_String );
341 136 : poPDefn->SetWidth( atoi( CPLGetXMLValue( psThis, "Width", "0" ) ) );
342 : }
343 58 : else if( EQUAL(pszType,"Integer") )
344 : {
345 55 : poPDefn->SetType( GMLPT_Integer );
346 55 : poPDefn->SetWidth( atoi( CPLGetXMLValue( psThis, "Width", "0" ) ) );
347 : }
348 3 : else if( EQUAL(pszType,"Real") )
349 : {
350 1 : poPDefn->SetType( GMLPT_Real );
351 1 : poPDefn->SetWidth( atoi( CPLGetXMLValue( psThis, "Width", "0" ) ) );
352 1 : poPDefn->SetPrecision( atoi( CPLGetXMLValue( psThis, "Precision", "0" ) ) );
353 : }
354 2 : else if( EQUAL(pszType,"StringList") )
355 1 : poPDefn->SetType( GMLPT_StringList );
356 1 : else if( EQUAL(pszType,"IntegerList") )
357 1 : poPDefn->SetType( GMLPT_IntegerList );
358 0 : else if( EQUAL(pszType,"RealList") )
359 0 : poPDefn->SetType( GMLPT_RealList );
360 0 : else if( EQUAL(pszType,"Complex") )
361 0 : poPDefn->SetType( GMLPT_Complex );
362 : else
363 : {
364 : CPLError( CE_Failure, CPLE_AppDefined,
365 : "Unrecognised property type %s.",
366 0 : pszType );
367 0 : delete poPDefn;
368 0 : return FALSE;
369 : }
370 :
371 201 : AddProperty( poPDefn );
372 : }
373 : }
374 :
375 45 : return TRUE;
376 : }
377 :
378 : /************************************************************************/
379 : /* SerializeToXML() */
380 : /************************************************************************/
381 :
382 9 : CPLXMLNode *GMLFeatureClass::SerializeToXML()
383 :
384 : {
385 : CPLXMLNode *psRoot;
386 : int iProperty;
387 :
388 : /* -------------------------------------------------------------------- */
389 : /* Set feature class and core information. */
390 : /* -------------------------------------------------------------------- */
391 9 : psRoot = CPLCreateXMLNode( NULL, CXT_Element, "GMLFeatureClass" );
392 :
393 9 : CPLCreateXMLElementAndValue( psRoot, "Name", GetName() );
394 9 : CPLCreateXMLElementAndValue( psRoot, "ElementPath", GetElementName() );
395 9 : if( GetGeometryElement() != NULL && strlen(GetGeometryElement()) > 0 )
396 : CPLCreateXMLElementAndValue( psRoot, "GeometryElementPath",
397 0 : GetGeometryElement() );
398 :
399 9 : if( GetGeometryType() != 0 /* wkbUnknown */ )
400 : {
401 : char szValue[128];
402 :
403 9 : sprintf( szValue, "%d", GetGeometryType() );
404 9 : CPLCreateXMLElementAndValue( psRoot, "GeometryType", szValue );
405 : }
406 :
407 : /* -------------------------------------------------------------------- */
408 : /* Write out dataset specific information. */
409 : /* -------------------------------------------------------------------- */
410 : CPLXMLNode *psDSI;
411 :
412 9 : if( m_bHaveExtents || m_nFeatureCount != -1 || m_pszExtraInfo != NULL )
413 : {
414 9 : psDSI = CPLCreateXMLNode( psRoot, CXT_Element, "DatasetSpecificInfo" );
415 :
416 9 : if( m_nFeatureCount != -1 )
417 : {
418 : char szValue[128];
419 :
420 9 : sprintf( szValue, "%d", m_nFeatureCount );
421 9 : CPLCreateXMLElementAndValue( psDSI, "FeatureCount", szValue );
422 : }
423 :
424 9 : if( m_bHaveExtents )
425 : {
426 : char szValue[128];
427 :
428 9 : sprintf( szValue, "%.5f", m_dfXMin );
429 9 : CPLCreateXMLElementAndValue( psDSI, "ExtentXMin", szValue );
430 :
431 9 : sprintf( szValue, "%.5f", m_dfXMax );
432 9 : CPLCreateXMLElementAndValue( psDSI, "ExtentXMax", szValue );
433 :
434 9 : sprintf( szValue, "%.5f", m_dfYMin );
435 9 : CPLCreateXMLElementAndValue( psDSI, "ExtentYMin", szValue );
436 :
437 9 : sprintf( szValue, "%.5f", m_dfYMax );
438 9 : CPLCreateXMLElementAndValue( psDSI, "ExtentYMax", szValue );
439 : }
440 :
441 9 : if( m_pszExtraInfo )
442 0 : CPLCreateXMLElementAndValue( psDSI, "ExtraInfo", m_pszExtraInfo );
443 : }
444 :
445 : /* -------------------------------------------------------------------- */
446 : /* emit property information. */
447 : /* -------------------------------------------------------------------- */
448 43 : for( iProperty = 0; iProperty < GetPropertyCount(); iProperty++ )
449 : {
450 34 : GMLPropertyDefn *poPDefn = GetProperty( iProperty );
451 : CPLXMLNode *psPDefnNode;
452 34 : const char *pszTypeName = "Unknown";
453 :
454 34 : psPDefnNode = CPLCreateXMLNode( psRoot, CXT_Element, "PropertyDefn" );
455 : CPLCreateXMLElementAndValue( psPDefnNode, "Name",
456 34 : poPDefn->GetName() );
457 : CPLCreateXMLElementAndValue( psPDefnNode, "ElementPath",
458 34 : poPDefn->GetSrcElement() );
459 34 : switch( poPDefn->GetType() )
460 : {
461 : case GMLPT_Untyped:
462 0 : pszTypeName = "Untyped";
463 0 : break;
464 :
465 : case GMLPT_String:
466 11 : pszTypeName = "String";
467 11 : break;
468 :
469 : case GMLPT_Integer:
470 18 : pszTypeName = "Integer";
471 18 : break;
472 :
473 : case GMLPT_Real:
474 5 : pszTypeName = "Real";
475 5 : break;
476 :
477 : case GMLPT_Complex:
478 0 : pszTypeName = "Complex";
479 0 : break;
480 :
481 : case GMLPT_IntegerList:
482 0 : pszTypeName = "IntegerList";
483 0 : break;
484 :
485 : case GMLPT_RealList:
486 0 : pszTypeName = "RealList";
487 0 : break;
488 :
489 : case GMLPT_StringList:
490 0 : pszTypeName = "StringList";
491 : break;
492 : }
493 34 : CPLCreateXMLElementAndValue( psPDefnNode, "Type", pszTypeName );
494 :
495 34 : if( EQUAL(pszTypeName,"String") )
496 : {
497 : char szMaxLength[48];
498 11 : sprintf(szMaxLength, "%d", poPDefn->GetWidth());
499 11 : CPLCreateXMLElementAndValue ( psPDefnNode, "Width", szMaxLength );
500 : }
501 34 : if( poPDefn->GetWidth() > 0 && EQUAL(pszTypeName,"Integer") )
502 : {
503 : char szLength[48];
504 0 : sprintf(szLength, "%d", poPDefn->GetWidth());
505 0 : CPLCreateXMLElementAndValue ( psPDefnNode, "Width", szLength );
506 : }
507 34 : if( poPDefn->GetWidth() > 0 && EQUAL(pszTypeName,"Real") )
508 : {
509 : char szLength[48];
510 0 : sprintf(szLength, "%d", poPDefn->GetWidth());
511 0 : CPLCreateXMLElementAndValue ( psPDefnNode, "Width", szLength );
512 : char szPrecision[48];
513 0 : sprintf(szPrecision, "%d", poPDefn->GetPrecision());
514 0 : CPLCreateXMLElementAndValue ( psPDefnNode, "Precision", szPrecision );
515 : }
516 : }
517 :
518 9 : return psRoot;
519 : }
520 :
|