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