Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: GML Reader
4 : * Purpose: Implementation of GML GFS template management
5 : * Author: Alessandro Furieri, a.furitier@lqt.it
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2011, Alessandro Furieri
9 : *
10 : * Permission is hereby granted, free of charge, to any person obtaining a
11 : * copy of this software and associated documentation files (the "Software"),
12 : * to deal in the Software without restriction, including without limitation
13 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 : * and/or sell copies of the Software, and to permit persons to whom the
15 : * Software is furnished to do so, subject to the following conditions:
16 : *
17 : * The above copyright notice and this permission notice shall be included
18 : * in all copies or substantial portions of the Software.
19 : *
20 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 : * DEALINGS IN THE SOFTWARE.
27 : *
28 : ******************************************************************************
29 : * Contributor: Alessandro Furieri, a.furieri@lqt.it
30 : * Developed for Faunalia ( http://www.faunalia.it) with funding from
31 : * Regione Toscana - Settore SISTEMA INFORMATIVO TERRITORIALE ED AMBIENTALE
32 : *
33 : ****************************************************************************/
34 :
35 : #include "cpl_port.h"
36 : #include "gmlreaderp.h"
37 : #include "ogr_gml.h"
38 :
39 : #include <cstddef>
40 :
41 : #include "cpl_conv.h"
42 : #include "cpl_minixml.h"
43 : #include "gmlreader.h"
44 : #include "ogr_core.h"
45 :
46 : /************************************************************************/
47 : /* GFSTemplateItem */
48 : /************************************************************************/
49 :
50 : class GFSTemplateItem
51 : {
52 : private:
53 : char *m_pszName;
54 : int n_nItemCount;
55 : int n_nGeomCount;
56 : GFSTemplateItem *pNext;
57 :
58 : public:
59 : explicit GFSTemplateItem(const char *pszName);
60 : ~GFSTemplateItem();
61 :
62 158 : const char *GetName()
63 : {
64 158 : return m_pszName;
65 : }
66 :
67 : void Update(int b_has_geom);
68 :
69 4 : int GetCount()
70 : {
71 4 : return n_nItemCount;
72 : }
73 :
74 4 : int GetGeomCount()
75 : {
76 4 : return n_nGeomCount;
77 : }
78 :
79 4 : void SetNext(GFSTemplateItem *pN)
80 : {
81 4 : pNext = pN;
82 4 : }
83 :
84 24 : GFSTemplateItem *GetNext()
85 : {
86 24 : return pNext;
87 : }
88 : };
89 :
90 : /***************************************************/
91 : /* gmlUpdateFeatureClasses() */
92 : /***************************************************/
93 :
94 2 : void gmlUpdateFeatureClasses(GFSTemplateList *pCC, GMLReader *pReader,
95 : int *pbSequentialLayers)
96 : {
97 : // Updating the FeatureClass list.
98 6 : for (int clIdx = 0; clIdx < pReader->GetClassCount(); clIdx++)
99 : {
100 4 : GMLFeatureClass *poClass = pReader->GetClass(clIdx);
101 4 : if (poClass != nullptr)
102 4 : poClass->SetFeatureCount(0);
103 : }
104 2 : bool bValid = false;
105 2 : GFSTemplateItem *pItem = pCC->GetFirst();
106 8 : while (pItem != nullptr)
107 : {
108 : // Updating Classes.
109 6 : GMLFeatureClass *poClass = pReader->GetClass(pItem->GetName());
110 6 : if (poClass != nullptr)
111 : {
112 4 : poClass->SetFeatureCount(pItem->GetCount());
113 8 : if (pItem->GetGeomCount() != 0 &&
114 4 : poClass->GetGeometryPropertyCount() == 0)
115 8 : poClass->AddGeometryProperty(
116 4 : new GMLGeometryPropertyDefn("", "", wkbUnknown, -1, true));
117 4 : bValid = true;
118 : }
119 6 : pItem = pItem->GetNext();
120 : }
121 2 : if (bValid && pCC->HaveSequentialLayers())
122 2 : *pbSequentialLayers = TRUE;
123 2 : }
124 :
125 : /***************************************************/
126 : /* GMLReader::ReArrangeTemplateClasses() */
127 : /***************************************************/
128 :
129 2 : bool GMLReader::ReArrangeTemplateClasses(GFSTemplateList *pCC)
130 : {
131 : // Rearranging the final FeatureClass list [SEQUENTIAL].
132 : // TODO(schwehr): Why the m_ for m_nSavedClassCount? Not a member.
133 2 : const int m_nSavedClassCount = GetClassCount();
134 :
135 : // Saving the previous FeatureClass list.
136 : GMLFeatureClass **m_papoSavedClass = static_cast<GMLFeatureClass **>(
137 2 : CPLMalloc(sizeof(void *) * m_nSavedClassCount));
138 :
139 6 : for (int clIdx = 0; clIdx < GetClassCount(); clIdx++)
140 : {
141 : // Transferring any previous FeatureClass.
142 4 : m_papoSavedClass[clIdx] = m_papoClass[clIdx];
143 : }
144 :
145 : // Cleaning the previous FeatureClass list.
146 2 : SetClassListLocked(false);
147 2 : CPLFree(m_papoClass);
148 2 : m_nClassCount = 0;
149 2 : m_papoClass = nullptr;
150 :
151 2 : GFSTemplateItem *pItem = pCC->GetFirst();
152 8 : while (pItem != nullptr)
153 : {
154 : // Re-inserting any required FeatureClassup
155 : // accordingly to actual SEQUENTIAL layout.
156 6 : GMLFeatureClass *poClass = nullptr;
157 12 : for (int iClass = 0; iClass < m_nSavedClassCount; iClass++)
158 : {
159 10 : GMLFeatureClass *poItem = m_papoSavedClass[iClass];
160 10 : if (EQUAL(poItem->GetName(), pItem->GetName()))
161 : {
162 4 : poClass = poItem;
163 4 : break;
164 : }
165 : }
166 6 : if (poClass != nullptr)
167 : {
168 4 : if (poClass->GetFeatureCount() > 0)
169 4 : AddClass(poClass);
170 : }
171 6 : pItem = pItem->GetNext();
172 : }
173 2 : SetClassListLocked(true);
174 :
175 : // Destroying the saved List and any unused FeatureClass.
176 6 : for (int iClass = 0; iClass < m_nSavedClassCount; iClass++)
177 : {
178 4 : bool bUnused = true;
179 4 : GMLFeatureClass *poClass = m_papoSavedClass[iClass];
180 6 : for (int iClass2 = 0; iClass2 < m_nClassCount; iClass2++)
181 : {
182 6 : if (m_papoClass[iClass2] == poClass)
183 : {
184 4 : bUnused = false;
185 4 : break;
186 : }
187 : }
188 4 : if (bUnused)
189 0 : delete poClass;
190 : }
191 2 : CPLFree(m_papoSavedClass);
192 2 : return true;
193 : }
194 :
195 : /***************************************************/
196 : /* GMLReader::PrescanForTemplate() */
197 : /***************************************************/
198 :
199 2 : bool GMLReader::PrescanForTemplate()
200 : {
201 : // Below logic is not ready for FeatureProperty/FeaturePropertyList
202 2 : if (ShouldLookForClassAtAnyLevel())
203 2 : return true;
204 :
205 0 : GMLFeature *poFeature = nullptr;
206 0 : GFSTemplateList *pCC = new GFSTemplateList();
207 :
208 : // Processing GML features.
209 0 : while ((poFeature = NextFeature()) != nullptr)
210 : {
211 0 : GMLFeatureClass *poClass = poFeature->GetClass();
212 0 : const CPLXMLNode *const *papsGeomList = poFeature->GetGeometryList();
213 0 : bool b_has_geom = false;
214 :
215 0 : if (papsGeomList != nullptr)
216 : {
217 0 : int i = 0;
218 0 : const CPLXMLNode *psNode = papsGeomList[i];
219 0 : while (psNode != nullptr)
220 : {
221 0 : b_has_geom = true;
222 0 : i++;
223 0 : psNode = papsGeomList[i];
224 : }
225 : }
226 0 : pCC->Update(poClass->GetElementName(), b_has_geom);
227 :
228 0 : delete poFeature;
229 : }
230 :
231 0 : gmlUpdateFeatureClasses(pCC, this, &m_nHasSequentialLayers);
232 0 : if (m_nHasSequentialLayers == TRUE)
233 0 : ReArrangeTemplateClasses(pCC);
234 0 : const int iCount = pCC->GetClassCount();
235 0 : delete pCC;
236 0 : CleanupParser();
237 0 : return iCount > 0;
238 : }
239 :
240 : /***************************************************/
241 : /* GFSTemplateList() */
242 : /***************************************************/
243 :
244 2 : GFSTemplateList::GFSTemplateList()
245 2 : : m_bSequentialLayers(true), pFirst(nullptr), pLast(nullptr)
246 : {
247 2 : }
248 :
249 : /***************************************************/
250 : /* GFSTemplateList() */
251 : /***************************************************/
252 :
253 4 : GFSTemplateList::~GFSTemplateList()
254 : {
255 2 : GFSTemplateItem *pItem = pFirst;
256 8 : while (pItem != nullptr)
257 : {
258 6 : GFSTemplateItem *pNext = pItem->GetNext();
259 6 : delete pItem;
260 6 : pItem = pNext;
261 : }
262 2 : }
263 :
264 : /***************************************************/
265 : /* GFSTemplateList::Insert() */
266 : /***************************************************/
267 :
268 6 : GFSTemplateItem *GFSTemplateList::Insert(const char *pszName)
269 : {
270 6 : GFSTemplateItem *pItem = new GFSTemplateItem(pszName);
271 :
272 : // Inserting into the linked list.
273 6 : if (pFirst == nullptr)
274 2 : pFirst = pItem;
275 6 : if (pLast != nullptr)
276 4 : pLast->SetNext(pItem);
277 6 : pLast = pItem;
278 6 : return pItem;
279 : }
280 :
281 : /***************************************************/
282 : /* GFSTemplateList::Update() */
283 : /***************************************************/
284 :
285 138 : void GFSTemplateList::Update(const char *pszName, int bHasGeom)
286 : {
287 138 : GFSTemplateItem *pItem = nullptr;
288 :
289 138 : if (pFirst == nullptr)
290 : {
291 : // Empty List: first item.
292 2 : pItem = Insert(pszName);
293 2 : pItem->Update(bHasGeom);
294 2 : return;
295 : }
296 136 : if (EQUAL(pszName, pLast->GetName()))
297 : {
298 : // Continuing with the current Class Item.
299 132 : pLast->Update(bHasGeom);
300 132 : return;
301 : }
302 :
303 4 : pItem = pFirst;
304 10 : while (pItem != nullptr)
305 : {
306 6 : if (EQUAL(pszName, pItem->GetName()))
307 : {
308 : // Class Item previously declared: NOT SEQUENTIAL.
309 0 : m_bSequentialLayers = false;
310 0 : pItem->Update(bHasGeom);
311 0 : return;
312 : }
313 6 : pItem = pItem->GetNext();
314 : }
315 :
316 : // Inserting a new Class Item.
317 4 : pItem = Insert(pszName);
318 4 : pItem->Update(bHasGeom);
319 : }
320 :
321 : /***************************************************/
322 : /* GFSTemplateList::GetClassCount() */
323 : /***************************************************/
324 :
325 0 : int GFSTemplateList::GetClassCount()
326 : {
327 0 : int iCount = 0;
328 0 : GFSTemplateItem *pItem = pFirst;
329 0 : while (pItem != nullptr)
330 : {
331 0 : iCount++;
332 0 : pItem = pItem->GetNext();
333 : }
334 :
335 0 : return iCount;
336 : }
337 :
338 : /***************************************************/
339 : /* GFSTemplateItem() */
340 : /***************************************************/
341 :
342 6 : GFSTemplateItem::GFSTemplateItem(const char *pszName)
343 6 : : m_pszName(CPLStrdup(pszName)), n_nItemCount(0), n_nGeomCount(0),
344 6 : pNext(nullptr)
345 : {
346 6 : }
347 :
348 : /***************************************************/
349 : /* ~GFSTemplateItem() */
350 : /***************************************************/
351 :
352 12 : GFSTemplateItem::~GFSTemplateItem()
353 : {
354 6 : CPLFree(m_pszName);
355 6 : }
356 :
357 : /***************************************************/
358 : /* GFSTemplateItem::Update() */
359 : /***************************************************/
360 :
361 138 : void GFSTemplateItem::Update(int bHasGeom)
362 : {
363 138 : n_nItemCount++;
364 138 : if (bHasGeom == TRUE)
365 138 : n_nGeomCount++;
366 138 : }
|