1 : /******************************************************************************
2 : * $Id: gfstemplate.cpp 23547 2011-12-12 16:29:27Z rouault $
3 : *
4 : * Project: GML Reader
5 : * Purpose: Implementation of GML GFS template management
6 : * Author: Alessandro Furieri, a.furitier@lqt.it
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2011, Alessandro Furieri
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 : * Contributor: Alessandro Furieri, a.furieri@lqt.it
31 : * Developed for Faunalia ( http://www.faunalia.it) with funding from
32 : * Regione Toscana - Settore SISTEMA INFORMATIVO TERRITORIALE ED AMBIENTALE
33 : *
34 : ****************************************************************************/
35 :
36 : #include "gmlreaderp.h"
37 : #include "ogr_gml.h"
38 :
39 : CPL_CVSID("$Id: gfstemplate.cpp 23547 2011-12-12 16:29:27Z rouault $");
40 :
41 : /************************************************************************/
42 : /* GFSTemplateItem */
43 : /************************************************************************/
44 :
45 : class GFSTemplateItem
46 : {
47 : private:
48 : char *m_pszName;
49 : int n_nItemCount;
50 : int n_nGeomCount;
51 : GFSTemplateItem *pNext;
52 : public:
53 : GFSTemplateItem( const char *pszName );
54 : ~GFSTemplateItem();
55 72 : const char *GetName() { return m_pszName; }
56 : void Update( int b_has_geom );
57 2 : int GetCount() { return n_nItemCount; }
58 2 : int GetGeomCount() { return n_nGeomCount; }
59 2 : void SetNext( GFSTemplateItem *pN ) { pNext = pN; }
60 12 : GFSTemplateItem *GetNext() { return pNext; }
61 : };
62 :
63 : /***************************************************/
64 : /* gmlUpdateFeatureClasses() */
65 : /***************************************************/
66 :
67 1 : void gmlUpdateFeatureClasses ( GFSTemplateList *pCC,
68 : GMLReader *pReader,
69 : int *pbSequentialLayers )
70 : {
71 : /* updating the FeatureClass list */
72 : int clIdx;
73 3 : for (clIdx = 0; clIdx < pReader->GetClassCount(); clIdx++)
74 : {
75 2 : GMLFeatureClass* poClass = pReader->GetClass( clIdx );
76 2 : if (poClass != NULL)
77 2 : poClass->SetFeatureCount( 0 );
78 : }
79 1 : int m_bValid = FALSE;
80 1 : GFSTemplateItem *pItem = pCC->GetFirst();
81 5 : while ( pItem != NULL )
82 : {
83 : /* updating Classes */
84 3 : GMLFeatureClass* poClass = pReader->GetClass( pItem->GetName() );
85 3 : if (poClass != NULL)
86 : {
87 2 : poClass->SetFeatureCount( pItem->GetCount() );
88 2 : if ( pItem->GetGeomCount() == 0)
89 0 : poClass->SetGeometryType( wkbNone );
90 2 : m_bValid = TRUE;
91 : }
92 3 : pItem = pItem->GetNext();
93 : }
94 1 : if ( m_bValid == TRUE && pCC->HaveSequentialLayers() == TRUE )
95 1 : *pbSequentialLayers = TRUE;
96 1 : }
97 :
98 : /***************************************************/
99 : /* GMLReader::ReArrangeTemplateClasses() */
100 : /***************************************************/
101 :
102 1 : int GMLReader::ReArrangeTemplateClasses ( GFSTemplateList *pCC )
103 : {
104 : /* rearranging the final FeatureClass list [SEQUENTIAL] */
105 1 : int m_nSavedClassCount = GetClassCount();
106 :
107 : /* saving the previous FeatureClass list */
108 : GMLFeatureClass **m_papoSavedClass = (GMLFeatureClass **)
109 1 : CPLMalloc( sizeof(void*) * m_nSavedClassCount );
110 : int clIdx;
111 3 : for (clIdx = 0; clIdx < GetClassCount(); clIdx++)
112 : {
113 : /* tranferring any previous FeatureClass */
114 2 : m_papoSavedClass[clIdx] = m_papoClass[clIdx];
115 : }
116 :
117 : /* cleaning the previous FeatureClass list */
118 1 : SetClassListLocked( FALSE );
119 1 : CPLFree( m_papoClass );
120 1 : m_nClassCount = 0;
121 1 : m_papoClass = NULL;
122 :
123 1 : GFSTemplateItem *pItem = pCC->GetFirst();
124 5 : while ( pItem != NULL )
125 : {
126 : /*
127 : * re-inserting any required FeatureClassup
128 : * accordingly to actual SEQUENTIAL layout
129 : */
130 3 : GMLFeatureClass* poClass = NULL;
131 6 : for( int iClass = 0; iClass < m_nSavedClassCount; iClass++ )
132 : {
133 5 : GMLFeatureClass* poItem = m_papoSavedClass[iClass];
134 5 : if( EQUAL(poItem->GetName(), pItem->GetName() ))
135 : {
136 2 : poClass = poItem;
137 2 : break;
138 : }
139 : }
140 3 : if (poClass != NULL)
141 : {
142 2 : if (poClass->GetFeatureCount() > 0)
143 2 : AddClass( poClass );
144 : }
145 3 : pItem = pItem->GetNext();
146 : }
147 1 : SetClassListLocked( TRUE );
148 :
149 : /* destroying the saved List and any unused FeatureClass */
150 3 : for( int iClass = 0; iClass < m_nSavedClassCount; iClass++ )
151 : {
152 2 : int bUnused = TRUE;
153 2 : GMLFeatureClass* poClass = m_papoSavedClass[iClass];
154 3 : for( int iClass2 = 0; iClass2 < m_nClassCount; iClass2++ )
155 : {
156 3 : if (m_papoClass[iClass2] == poClass)
157 : {
158 2 : bUnused = FALSE;
159 2 : break;
160 : }
161 : }
162 2 : if ( bUnused == TRUE )
163 0 : delete poClass;
164 : }
165 1 : CPLFree( m_papoSavedClass );
166 1 : return 1;
167 : }
168 :
169 : /***************************************************/
170 : /* GMLReader::PrescanForTemplate() */
171 : /***************************************************/
172 :
173 0 : int GMLReader::PrescanForTemplate ()
174 : {
175 0 : int iCount = 0;
176 : GMLFeature *poFeature;
177 : //int bSequentialLayers = TRUE;
178 0 : GFSTemplateList *pCC = new GFSTemplateList();
179 :
180 : /* processing GML features */
181 0 : while( (poFeature = NextFeature()) != NULL )
182 : {
183 0 : GMLFeatureClass *poClass = poFeature->GetClass();
184 0 : const CPLXMLNode* const * papsGeomList = poFeature->GetGeometryList();
185 0 : int b_has_geom = FALSE;
186 :
187 0 : if( papsGeomList != NULL )
188 : {
189 0 : int i = 0;
190 0 : const CPLXMLNode *psNode = papsGeomList[i];
191 0 : while( psNode != NULL )
192 : {
193 0 : b_has_geom = TRUE;
194 0 : i++;
195 0 : psNode = papsGeomList[i];
196 : }
197 : }
198 0 : pCC->Update( poClass->GetElementName(), b_has_geom );
199 :
200 0 : delete poFeature;
201 : }
202 :
203 0 : gmlUpdateFeatureClasses( pCC, this, &m_bSequentialLayers );
204 0 : if ( m_bSequentialLayers == TRUE )
205 0 : ReArrangeTemplateClasses( pCC );
206 0 : iCount = pCC->GetClassCount();
207 0 : delete pCC;
208 0 : CleanupParser();
209 0 : return iCount > 0;
210 : }
211 :
212 :
213 : /***************************************************/
214 : /* GFSTemplateList() */
215 : /***************************************************/
216 :
217 1 : GFSTemplateList::GFSTemplateList( void )
218 : {
219 1 : m_bSequentialLayers = TRUE;
220 1 : pFirst = NULL;
221 1 : pLast = NULL;
222 1 : }
223 :
224 : /***************************************************/
225 : /* GFSTemplateList() */
226 : /***************************************************/
227 :
228 1 : GFSTemplateList::~GFSTemplateList()
229 : {
230 : GFSTemplateItem *pNext;
231 1 : GFSTemplateItem *pItem = pFirst;
232 5 : while ( pItem != NULL )
233 : {
234 3 : pNext = pItem->GetNext();
235 3 : delete pItem;
236 3 : pItem = pNext;
237 : }
238 1 : }
239 :
240 : /***************************************************/
241 : /* GFSTemplateList::Insert() */
242 : /***************************************************/
243 :
244 3 : GFSTemplateItem *GFSTemplateList::Insert( const char *pszName )
245 : {
246 : GFSTemplateItem *pItem;
247 3 : pItem = new GFSTemplateItem( pszName );
248 :
249 : /* inserting into the linked list */
250 3 : if( pFirst == NULL )
251 1 : pFirst = pItem;
252 3 : if( pLast != NULL )
253 2 : pLast->SetNext( pItem );
254 3 : pLast = pItem;
255 3 : return pItem;
256 : }
257 :
258 : /***************************************************/
259 : /* GFSTemplateList::Update() */
260 : /***************************************************/
261 :
262 62 : void GFSTemplateList::Update( const char *pszName, int bHasGeom )
263 : {
264 : GFSTemplateItem *pItem;
265 :
266 62 : if( pFirst == NULL )
267 : {
268 : /* empty List: first item */
269 1 : pItem = Insert( pszName );
270 1 : pItem->Update( bHasGeom );
271 1 : return;
272 : }
273 61 : if( EQUAL(pszName, pLast->GetName() ) )
274 : {
275 : /* continuing with the current Class Item */
276 59 : pLast->Update( bHasGeom );
277 59 : return;
278 : }
279 :
280 2 : pItem = pFirst;
281 7 : while( pItem != NULL )
282 : {
283 3 : if( EQUAL(pszName, pItem->GetName() ))
284 : {
285 : /* Class Item previously declared: NOT SEQUENTIAL */
286 0 : m_bSequentialLayers = FALSE;
287 0 : pItem->Update( bHasGeom );
288 0 : return;
289 : }
290 3 : pItem = pItem->GetNext();
291 : }
292 :
293 : /* inserting a new Class Item */
294 2 : pItem = Insert( pszName );
295 2 : pItem->Update( bHasGeom );
296 : }
297 :
298 :
299 : /***************************************************/
300 : /* GFSTemplateList::GetClassCount() */
301 : /***************************************************/
302 :
303 0 : int GFSTemplateList::GetClassCount( )
304 : {
305 0 : int iCount = 0;
306 : GFSTemplateItem *pItem;
307 :
308 0 : pItem = pFirst;
309 0 : while( pItem != NULL )
310 : {
311 0 : iCount++;
312 0 : pItem = pItem->GetNext();
313 : }
314 :
315 0 : return iCount;
316 : }
317 :
318 : /***************************************************/
319 : /* GFSTemplateItem() */
320 : /***************************************************/
321 :
322 3 : GFSTemplateItem::GFSTemplateItem( const char *pszName )
323 : {
324 3 : m_pszName = CPLStrdup( pszName );
325 3 : n_nItemCount = 0;
326 3 : n_nGeomCount = 0;
327 3 : pNext = NULL;
328 3 : }
329 :
330 : /***************************************************/
331 : /* ~GFSTemplateItem() */
332 : /***************************************************/
333 :
334 3 : GFSTemplateItem::~GFSTemplateItem()
335 : {
336 3 : CPLFree(m_pszName);
337 3 : }
338 :
339 : /***************************************************/
340 : /* GFSTemplateItem::Update() */
341 : /***************************************************/
342 :
343 62 : void GFSTemplateItem::Update( int bHasGeom )
344 : {
345 62 : n_nItemCount++;
346 62 : if( bHasGeom == TRUE )
347 62 : n_nGeomCount++;
348 62 : }
|