1 : /******************************************************************************
2 : * $Id: ili2reader.cpp 24408 2012-05-11 21:31:45Z pka $
3 : *
4 : * Project: Interlis 2 Reader
5 : * Purpose: Implementation of ILI2Reader class.
6 : * Author: Markus Schnider, Sourcepole AG
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2004, Pirmin Kalberer, Sourcepole AG
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
22 : * OR 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 "ogr_ili2.h"
31 : #include "cpl_conv.h"
32 : #include "cpl_string.h"
33 :
34 : #include "ilihelper.h"
35 : #include "iomhelper.h"
36 : #include "ili2reader.h"
37 : #include "ili2readerp.h"
38 :
39 : using namespace std;
40 :
41 : CPL_CVSID("$Id: ili2reader.cpp 24408 2012-05-11 21:31:45Z pka $");
42 :
43 : //
44 : // constants
45 : //
46 : static const char *ILI2_TID = "TID";
47 : static const char *ILI2_REF = "REF";
48 :
49 : static const int ILI2_STRING_TYPE = 0;
50 : static const int ILI2_COORD_TYPE = 1;
51 : static const int ILI2_ARC_TYPE = 2;
52 : static const int ILI2_POLYLINE_TYPE = 4;
53 : static const int ILI2_BOUNDARY_TYPE = 8;
54 : static const int ILI2_AREA_TYPE = 16; // also SURFACE
55 : static const int ILI2_GEOMCOLL_TYPE = 32;
56 :
57 : static const char *ILI2_COORD = "COORD";
58 : static const char *ILI2_ARC = "ARC";
59 : static const char *ILI2_POLYLINE = "POLYLINE";
60 : static const char *ILI2_BOUNDARY = "BOUNDARY";
61 : static const char *ILI2_AREA = "AREA";
62 : static const char *ILI2_SURFACE = "SURFACE";
63 :
64 :
65 : //
66 : // helper functions
67 : //
68 2772 : int cmpStr(string s1, string s2) {
69 :
70 2772 : string::const_iterator p1 = s1.begin();
71 2772 : string::const_iterator p2 = s2.begin();
72 :
73 13827 : while (p1 != s1.end() && p2 != s2.end()) {
74 9925 : if (toupper(*p1) != toupper(*p2))
75 1642 : return (toupper(*p1) < toupper(*p2)) ? -1 : 1;
76 8283 : ++p1;
77 8283 : ++p2;
78 : }
79 :
80 : return (s2.size() == s1.size()) ? 0 :
81 1130 : (s1.size() < s2.size()) ? -1 : 1;
82 : }
83 :
84 1398 : string ltrim(string tmpstr) {
85 1398 : unsigned int i = 0;
86 1398 : while (i < tmpstr.length() && (tmpstr[i] == ' ' || tmpstr[i] == '\t' || tmpstr[i] == '\r' || tmpstr[i] == '\n')) ++i;
87 1398 : return i > 0 ? tmpstr.substr(i, tmpstr.length()-i) : tmpstr;
88 : }
89 :
90 1398 : string rtrim(string tmpstr) {
91 1398 : if (tmpstr.length() == 0) return tmpstr;
92 696 : unsigned int i = tmpstr.length() - 1;
93 696 : while (i >= 0 && (tmpstr[i] == ' ' || tmpstr[i] == '\t' || tmpstr[i] == '\r' || tmpstr[i] == '\n')) --i;
94 696 : return i < tmpstr.length() - 1 ? tmpstr.substr(0, i+1) : tmpstr;
95 : }
96 :
97 1398 : string trim(string tmpstr) {
98 1398 : tmpstr = ltrim(tmpstr);
99 2796 : tmpstr = rtrim(tmpstr);
100 1398 : return tmpstr;
101 : }
102 :
103 207 : int getGeometryTypeOfElem(DOMElement* elem) {
104 207 : int type = ILI2_STRING_TYPE;
105 207 : char* pszTagName = XMLString::transcode(elem->getTagName());
106 :
107 207 : if (elem && elem->getNodeType() == DOMNode::ELEMENT_NODE) {
108 207 : if (cmpStr(ILI2_COORD, pszTagName) == 0) {
109 18 : type = ILI2_COORD_TYPE;
110 189 : } else if (cmpStr(ILI2_ARC, pszTagName) == 0) {
111 0 : type = ILI2_ARC_TYPE;
112 189 : } else if (cmpStr(ILI2_POLYLINE, pszTagName) == 0) {
113 15 : type = ILI2_POLYLINE_TYPE;
114 174 : } else if (cmpStr(ILI2_BOUNDARY, pszTagName) == 0) {
115 0 : type = ILI2_BOUNDARY_TYPE;
116 174 : } else if (cmpStr(ILI2_AREA, pszTagName) == 0) {
117 0 : type = ILI2_AREA_TYPE;
118 174 : } else if (cmpStr(ILI2_SURFACE, pszTagName) == 0) {
119 25 : type = ILI2_AREA_TYPE;
120 : }
121 : }
122 207 : XMLString::release(&pszTagName);
123 207 : return type;
124 : }
125 :
126 688 : char *getObjValue(DOMElement *elem) {
127 688 : DOMElement *textElem = (DOMElement *)elem->getFirstChild();
128 :
129 688 : if ((textElem != NULL) && (textElem->getNodeType() == DOMNode::TEXT_NODE))
130 : {
131 666 : char* pszNodeValue = XMLString::transcode(textElem->getNodeValue());
132 666 : char* pszRet = CPLStrdup(pszNodeValue);
133 666 : XMLString::release(&pszNodeValue);
134 666 : return pszRet;
135 : }
136 :
137 22 : return NULL;
138 : }
139 :
140 22 : char *getREFValue(DOMElement *elem) {
141 22 : XMLCh* pszIli2_ref = XMLString::transcode(ILI2_REF);
142 22 : char* pszREFValue = XMLString::transcode(elem->getAttribute(pszIli2_ref));
143 22 : char* pszRet = CPLStrdup(pszREFValue);
144 22 : XMLString::release(&pszIli2_ref);
145 22 : XMLString::release(&pszREFValue);
146 22 : return pszRet;
147 : }
148 :
149 302 : OGRPoint *getPoint(DOMElement *elem) {
150 : // elem -> COORD (or ARC)
151 302 : OGRPoint *pt = new OGRPoint();
152 :
153 302 : DOMElement *coordElem = (DOMElement *)elem->getFirstChild();
154 1208 : while (coordElem != NULL) {
155 604 : char* pszTagName = XMLString::transcode(coordElem->getTagName());
156 604 : char* pszObjValue = getObjValue(coordElem);
157 604 : if (cmpStr("C1", pszTagName) == 0)
158 302 : pt->setX(atof(pszObjValue));
159 302 : else if (cmpStr("C2", pszTagName) == 0)
160 302 : pt->setY(atof(pszObjValue));
161 0 : else if (cmpStr("C3", pszTagName) == 0)
162 0 : pt->setZ(atof(pszObjValue));
163 604 : CPLFree(pszObjValue);
164 604 : XMLString::release(&pszTagName);
165 604 : coordElem = (DOMElement *)coordElem->getNextSibling();
166 : }
167 302 : pt->flattenTo2D();
168 302 : return pt;
169 : }
170 :
171 0 : OGRLineString *ILI2Reader::getArc(DOMElement *elem) {
172 : // elem -> ARC
173 0 : OGRLineString *ls = new OGRLineString();
174 : // previous point -> start point
175 0 : OGRPoint *ptStart = getPoint((DOMElement *)elem->getPreviousSibling()); // COORD or ARC
176 : // end point
177 0 : OGRPoint *ptEnd = new OGRPoint();
178 : // point on the arc
179 0 : OGRPoint *ptOnArc = new OGRPoint();
180 0 : double radius = 0; // radius
181 :
182 0 : DOMElement *arcElem = (DOMElement *)elem->getFirstChild();
183 0 : while (arcElem != NULL) {
184 0 : char* pszTagName = XMLString::transcode(arcElem->getTagName());
185 0 : char* pszObjValue = getObjValue(arcElem);
186 0 : if (cmpStr("C1", pszTagName) == 0)
187 0 : ptEnd->setX(atof(pszObjValue));
188 0 : else if (cmpStr("C2", pszTagName) == 0)
189 0 : ptEnd->setY(atof(pszObjValue));
190 0 : else if (cmpStr("C3", pszTagName) == 0)
191 0 : ptEnd->setZ(atof(pszObjValue));
192 0 : else if (cmpStr("A1", pszTagName) == 0)
193 0 : ptOnArc->setX(atof(pszObjValue));
194 0 : else if (cmpStr("A2", pszTagName) == 0)
195 0 : ptOnArc->setY(atof(pszObjValue));
196 0 : else if (cmpStr("A3", pszTagName) == 0)
197 0 : ptOnArc->setZ(atof(pszObjValue));
198 0 : else if (cmpStr("R", pszTagName) == 0)
199 0 : radius = atof(pszObjValue);
200 0 : CPLFree(pszObjValue);
201 0 : XMLString::release(&pszTagName);
202 0 : arcElem = (DOMElement *)arcElem->getNextSibling();
203 : }
204 0 : ptEnd->flattenTo2D();
205 0 : ptOnArc->flattenTo2D();
206 0 : interpolateArc(ls, ptStart, ptOnArc, ptEnd, arcIncr);
207 0 : delete ptStart;
208 0 : delete ptOnArc;
209 0 : delete ptEnd;
210 0 : return ls;
211 : }
212 :
213 44 : OGRLineString *getLineString(DOMElement *elem, int bAsLinearRing) {
214 : // elem -> POLYLINE
215 : OGRLineString *ls;
216 44 : if (bAsLinearRing)
217 30 : ls = new OGRLinearRing();
218 : else
219 14 : ls = new OGRLineString();
220 :
221 44 : DOMElement *lineElem = (DOMElement *)elem->getFirstChild();
222 404 : while (lineElem != NULL) {
223 316 : char* pszTagName = XMLString::transcode(lineElem->getTagName());
224 316 : if (cmpStr(ILI2_COORD, pszTagName) == 0)
225 : {
226 286 : OGRPoint* poPoint = getPoint(lineElem);
227 286 : ls->addPoint(poPoint);
228 286 : delete poPoint;
229 : }
230 30 : else if (cmpStr(ILI2_ARC, pszTagName) == 0) {
231 : // end point
232 0 : OGRPoint *ptEnd = new OGRPoint();
233 : // point on the arc
234 0 : OGRPoint *ptOnArc = new OGRPoint();
235 : // radius
236 0 : double radius = 0;
237 :
238 0 : DOMElement *arcElem = (DOMElement *)lineElem->getFirstChild();
239 0 : while (arcElem != NULL) {
240 0 : char* pszTagName = XMLString::transcode(arcElem->getTagName());
241 0 : char* pszObjValue = getObjValue(arcElem);
242 0 : if (cmpStr("C1", pszTagName) == 0)
243 0 : ptEnd->setX(atof(pszObjValue));
244 0 : else if (cmpStr("C2", pszTagName) == 0)
245 0 : ptEnd->setY(atof(pszObjValue));
246 0 : else if (cmpStr("C3", pszTagName) == 0)
247 0 : ptEnd->setZ(atof(pszObjValue));
248 0 : else if (cmpStr("A1", pszTagName) == 0)
249 0 : ptOnArc->setX(atof(pszObjValue));
250 0 : else if (cmpStr("A2", pszTagName) == 0)
251 0 : ptOnArc->setY(atof(pszObjValue));
252 0 : else if (cmpStr("A3", pszTagName) == 0)
253 0 : ptOnArc->setZ(atof(pszObjValue));
254 0 : else if (cmpStr("R", pszTagName) == 0)
255 0 : radius = atof(pszObjValue);
256 0 : CPLFree(pszObjValue);
257 0 : XMLString::release(&pszTagName);
258 :
259 0 : arcElem = (DOMElement *)arcElem->getNextSibling();
260 : }
261 :
262 0 : ptEnd->flattenTo2D();
263 0 : ptOnArc->flattenTo2D();
264 0 : OGRPoint *ptStart = getPoint((DOMElement *)lineElem->getPreviousSibling()); // COORD or ARC
265 0 : interpolateArc(ls, ptStart, ptOnArc, ptEnd, PI/180);
266 :
267 0 : delete ptStart;
268 0 : delete ptEnd;
269 0 : delete ptOnArc;
270 : } /* else { // FIXME StructureValue in Polyline not yet supported
271 : } */
272 316 : XMLString::release(&pszTagName);
273 :
274 316 : lineElem = (DOMElement *)lineElem->getNextSibling();
275 : }
276 :
277 44 : return ls;
278 : }
279 :
280 30 : OGRLinearRing *getBoundary(DOMElement *elem) {
281 :
282 30 : DOMElement *lineElem = (DOMElement *)elem->getFirstChild();
283 30 : if (lineElem != NULL)
284 : {
285 30 : char* pszTagName = XMLString::transcode(lineElem->getTagName());
286 30 : if (cmpStr(ILI2_POLYLINE, pszTagName) == 0)
287 : {
288 30 : XMLString::release(&pszTagName);
289 30 : return (OGRLinearRing*) getLineString(lineElem, TRUE);
290 : }
291 0 : XMLString::release(&pszTagName);
292 : }
293 :
294 0 : return new OGRLinearRing();
295 : }
296 :
297 24 : OGRPolygon *getPolygon(DOMElement *elem) {
298 24 : OGRPolygon *pg = new OGRPolygon();
299 :
300 24 : DOMElement *boundaryElem = (DOMElement *)elem->getFirstChild(); // outer boundary
301 78 : while (boundaryElem != NULL) {
302 30 : char* pszTagName = XMLString::transcode(boundaryElem->getTagName());
303 30 : if (cmpStr(ILI2_BOUNDARY, pszTagName) == 0)
304 30 : pg->addRingDirectly(getBoundary(boundaryElem));
305 30 : XMLString::release(&pszTagName);
306 30 : boundaryElem = (DOMElement *)boundaryElem->getNextSibling(); // inner boundaries
307 : }
308 :
309 24 : return pg;
310 : }
311 :
312 54 : OGRGeometry *ILI2Reader::getGeometry(DOMElement *elem, int type) {
313 54 : OGRGeometryCollection *gm = new OGRGeometryCollection();
314 :
315 54 : DOMElement *childElem = elem;
316 108 : while (childElem != NULL) {
317 54 : char* pszTagName = XMLString::transcode(childElem->getTagName());
318 54 : switch (type) {
319 : case ILI2_COORD_TYPE :
320 16 : if (cmpStr(ILI2_COORD, pszTagName) == 0)
321 : {
322 16 : delete gm;
323 16 : XMLString::release(&pszTagName);
324 16 : return getPoint(childElem);
325 : }
326 0 : break;
327 : case ILI2_ARC_TYPE :
328 : // is it possible here? It have to be a ARC or COORD before (getPreviousSibling)
329 0 : if (cmpStr(ILI2_ARC, pszTagName) == 0)
330 : {
331 0 : delete gm;
332 0 : XMLString::release(&pszTagName);
333 0 : return getArc(childElem);
334 : }
335 0 : break;
336 : case ILI2_POLYLINE_TYPE :
337 14 : if (cmpStr(ILI2_POLYLINE, pszTagName) == 0)
338 : {
339 14 : delete gm;
340 14 : XMLString::release(&pszTagName);
341 14 : return getLineString(childElem, FALSE);
342 : }
343 0 : break;
344 : case ILI2_BOUNDARY_TYPE :
345 0 : if (cmpStr(ILI2_BOUNDARY, pszTagName) == 0)
346 : {
347 0 : delete gm;
348 0 : XMLString::release(&pszTagName);
349 0 : return getLineString(childElem, FALSE);
350 : }
351 0 : break;
352 : case ILI2_AREA_TYPE :
353 24 : if ((cmpStr(ILI2_AREA, pszTagName) == 0) ||
354 : (cmpStr(ILI2_SURFACE, pszTagName) == 0))
355 : {
356 24 : delete gm;
357 24 : XMLString::release(&pszTagName);
358 24 : return getPolygon(childElem);
359 : }
360 0 : break;
361 : default :
362 0 : if (type >= ILI2_GEOMCOLL_TYPE) {
363 0 : int subType = getGeometryTypeOfElem(childElem); //????
364 0 : gm->addGeometryDirectly(getGeometry(childElem, subType));
365 : }
366 : break;
367 : }
368 0 : XMLString::release(&pszTagName);
369 :
370 : // GEOMCOLL
371 0 : childElem = (DOMElement *)childElem->getNextSibling();
372 : }
373 :
374 0 : return gm;
375 : }
376 :
377 8 : const char* ILI2Reader::GetLayerName(IOM_BASKET model, IOM_OBJECT table) {
378 : static char layername[512];
379 8 : IOM_OBJECT topic = GetAttrObj(model, table, "container");
380 8 : layername[0] = '\0';
381 8 : strcat(layername, iom_getattrvalue(GetAttrObj(model, topic, "container"), "name"));
382 8 : strcat(layername, ".");
383 8 : strcat(layername, iom_getattrvalue(topic, "name"));
384 8 : strcat(layername, ".");
385 8 : strcat(layername, iom_getattrvalue(table, "name"));
386 8 : return layername;
387 : }
388 :
389 16 : void ILI2Reader::AddField(OGRLayer* layer, IOM_BASKET model, IOM_OBJECT obj) {
390 16 : const char* typenam = "Reference";
391 16 : if (EQUAL(iom_getobjecttag(obj),"iom04.metamodel.LocalAttribute")) typenam = GetTypeName(model, obj);
392 16 : if (EQUAL(typenam, "iom04.metamodel.SurfaceType")) {
393 15 : } else if (EQUAL(typenam, "iom04.metamodel.AreaType")) {
394 15 : } else if (EQUAL(typenam, "iom04.metamodel.PolylineType") ) {
395 13 : } else if (EQUAL(typenam, "iom04.metamodel.CoordType")) {
396 : } else {
397 10 : OGRFieldDefn fieldDef(iom_getattrvalue(obj, "name"), OFTString);
398 10 : layer->GetLayerDefn()->AddFieldDefn(&fieldDef);
399 10 : CPLDebug( "OGR_ILI", "Field %s: %s", fieldDef.GetNameRef(), typenam);
400 : }
401 16 : }
402 :
403 1 : int ILI2Reader::ReadModel(char **modelFilenames) {
404 :
405 : IOM_BASKET model;
406 : IOM_ITERATOR modelelei;
407 : IOM_OBJECT modelele;
408 :
409 1 : iom_init();
410 :
411 : // set error listener to a iom provided one, that just
412 : // dumps all errors to stderr
413 1 : iom_seterrlistener(iom_stderrlistener);
414 :
415 : // compile ili models
416 1 : model=iom_compileIli(CSLCount(modelFilenames), modelFilenames);
417 1 : if(!model){
418 0 : CPLError( CE_Failure, CPLE_FileIO, "iom_compileIli failed." );
419 0 : iom_end();
420 0 : return FALSE;
421 : }
422 :
423 : // read tables
424 1 : modelelei=iom_iteratorobject(model);
425 1 : modelele=iom_nextobject(modelelei);
426 326 : while(modelele){
427 324 : const char *tag=iom_getobjecttag(modelele);
428 324 : if (tag && EQUAL(tag,"iom04.metamodel.Table")) {
429 28 : const char* topic = iom_getattrvalue(GetAttrObj(model, modelele, "container"), "name");
430 28 : if (!EQUAL(topic, "INTERLIS")) {
431 8 : const char* layername = GetLayerName(model, modelele);
432 8 : OGRLayer* layer = new OGRILI2Layer(layername, NULL, 0, wkbUnknown, NULL);
433 8 : m_listLayer.push_back(layer);
434 8 : CPLDebug( "OGR_ILI", "Reading table model '%s'", layername );
435 :
436 : // read fields
437 : IOM_OBJECT fields[255];
438 : IOM_OBJECT roledefs[255];
439 8 : memset(fields, 0, 255);
440 8 : memset(roledefs, 0, 255);
441 8 : int maxIdx = -1;
442 8 : IOM_ITERATOR fieldit=iom_iteratorobject(model);
443 2600 : for (IOM_OBJECT fieldele=iom_nextobject(fieldit); fieldele; fieldele=iom_nextobject(fieldit)){
444 2592 : const char *etag=iom_getobjecttag(fieldele);
445 2592 : if (etag && (EQUAL(etag,"iom04.metamodel.ViewableAttributesAndRoles"))) {
446 408 : IOM_OBJECT table = GetAttrObj(model, fieldele, "viewable");
447 408 : if (table == modelele) {
448 16 : IOM_OBJECT obj = GetAttrObj(model, fieldele, "attributesAndRoles");
449 16 : int ili1AttrIdx = GetAttrObjPos(fieldele, "attributesAndRoles")-1;
450 16 : if (EQUAL(iom_getobjecttag(obj),"iom04.metamodel.RoleDef")) {
451 : //??ili1AttrIdx = atoi(iom_getattrvalue(GetAttrObj(model, obj, "oppend"), "ili1AttrIdx"));
452 3 : roledefs[ili1AttrIdx] = obj;
453 : } else {
454 13 : fields[ili1AttrIdx] = obj;
455 : }
456 16 : if (ili1AttrIdx > maxIdx) maxIdx = ili1AttrIdx;
457 : //CPLDebug( "OGR_ILI", "Field %s Pos: %d", iom_getattrvalue(obj, "name"), ili1AttrIdx);
458 : }
459 : }
460 2592 : iom_releaseobject(fieldele);
461 : }
462 8 : iom_releaseiterator(fieldit);
463 :
464 24 : for (int i=0; i<=maxIdx; i++) {
465 16 : IOM_OBJECT obj = fields[i];
466 16 : IOM_OBJECT roleobj = roledefs[i];
467 16 : if (roleobj) AddField(layer, model, roleobj);
468 16 : if (obj) AddField(layer, model, obj);
469 : }
470 : }
471 : }
472 324 : iom_releaseobject(modelele);
473 :
474 324 : modelele=iom_nextobject(modelelei);
475 : }
476 :
477 1 : iom_releaseiterator(modelelei);
478 :
479 1 : iom_releasebasket(model);
480 :
481 1 : iom_end();
482 :
483 1 : return 0;
484 : }
485 :
486 91 : char* fieldName(DOMElement* elem) {
487 91 : string fullname;
488 91 : int depth = 0;
489 : DOMNode *node;
490 91 : for (node = elem; node; node = node->getParentNode()) ++depth;
491 91 : depth-=3; //ignore root elements
492 :
493 : // We cannot do this sort of dynamic stack alloc on MSVC6.
494 : // DOMNode* elements[depth];
495 : DOMNode* elements[1000];
496 91 : CPLAssert( depth < (int)(sizeof(elements) / sizeof(DOMNode*)) );
497 :
498 91 : int d=0;
499 91 : for (node = elem; d<depth; node = node->getParentNode()) elements[d++] = node;
500 182 : for (d=depth-1; d>=0; --d) {
501 91 : if (d < depth-1) fullname += "_";
502 91 : char* pszNodeName = XMLString::transcode(elements[d]->getNodeName());
503 91 : fullname += pszNodeName;
504 91 : XMLString::release(&pszNodeName);
505 : }
506 91 : return CPLStrdup(fullname.c_str());
507 : }
508 :
509 9 : void ILI2Reader::setFieldDefn(OGRFeatureDefn *featureDef, DOMElement* elem) {
510 9 : int type = 0;
511 : //recursively search children
512 54 : for (DOMElement *childElem = (DOMElement *)elem->getFirstChild();
513 15 : type == 0 && childElem && childElem->getNodeType() == DOMNode::ELEMENT_NODE;
514 15 : childElem = (DOMElement*)childElem->getNextSibling()) {
515 15 : type = getGeometryTypeOfElem(childElem);
516 15 : if (type == 0) {
517 11 : if (childElem->getFirstChild() && childElem->getFirstChild()->getNodeType() == DOMNode::ELEMENT_NODE) {
518 4 : setFieldDefn(featureDef, childElem);
519 : } else {
520 7 : char *fName = fieldName(childElem);
521 7 : if (featureDef->GetFieldIndex(fName) == -1) {
522 7 : CPLDebug( "OGR_ILI", "AddFieldDefn: %s",fName );
523 7 : OGRFieldDefn oFieldDefn(fName, OFTString);
524 7 : featureDef->AddFieldDefn(&oFieldDefn);
525 : }
526 7 : CPLFree(fName);
527 : }
528 : }
529 : }
530 9 : }
531 :
532 116 : void ILI2Reader::SetFieldValues(OGRFeature *feature, DOMElement* elem) {
533 116 : int type = 0;
534 : //recursively search children
535 692 : for (DOMElement *childElem = (DOMElement *)elem->getFirstChild();
536 192 : type == 0 && childElem && childElem->getNodeType() == DOMNode::ELEMENT_NODE;
537 192 : childElem = (DOMElement*)childElem->getNextSibling()) {
538 192 : type = getGeometryTypeOfElem(childElem);
539 192 : if (type == 0) {
540 138 : if (childElem->getFirstChild() && childElem->getFirstChild()->getNodeType() == DOMNode::ELEMENT_NODE) {
541 54 : SetFieldValues(feature, childElem);
542 : } else {
543 84 : char *fName = fieldName(childElem);
544 84 : int fIndex = feature->GetFieldIndex(fName);
545 84 : if (fIndex != -1) {
546 84 : char * objVal = getObjValue(childElem);
547 84 : if (objVal == NULL)
548 22 : objVal = getREFValue(childElem); // only to try
549 84 : feature->SetField(fIndex, objVal);
550 84 : CPLFree(objVal);
551 : } else {
552 0 : CPLDebug( "OGR_ILI","Attribute '%s' not found", fName);
553 0 : m_missAttrs.push_back(fName);
554 : }
555 84 : CPLFree(fName);
556 : }
557 : } else {
558 54 : feature->SetGeometryDirectly(getGeometry(childElem, type));
559 : }
560 : }
561 116 : }
562 :
563 :
564 : //
565 : // ILI2Reader
566 : //
567 2 : IILI2Reader::~IILI2Reader() {
568 2 : }
569 :
570 2 : ILI2Reader::ILI2Reader() {
571 2 : m_poILI2Handler = NULL;
572 2 : m_poSAXReader = NULL;
573 2 : m_bReadStarted = FALSE;
574 :
575 2 : m_pszFilename = NULL;
576 :
577 2 : SetupParser();
578 2 : }
579 :
580 2 : ILI2Reader::~ILI2Reader() {
581 2 : CPLFree( m_pszFilename );
582 :
583 2 : CleanupParser();
584 :
585 2 : list<OGRLayer *>::const_iterator layerIt = m_listLayer.begin();
586 17 : while (layerIt != m_listLayer.end()) {
587 13 : OGRILI2Layer *tmpLayer = (OGRILI2Layer *)*layerIt;
588 13 : delete tmpLayer;
589 13 : layerIt++;
590 : }
591 2 : }
592 :
593 0 : void ILI2Reader::SetArcDegrees(double arcDegrees) {
594 0 : arcIncr = arcDegrees*PI/180;
595 0 : }
596 :
597 2 : void ILI2Reader::SetSourceFile( const char *pszFilename ) {
598 2 : CPLFree( m_pszFilename );
599 2 : m_pszFilename = CPLStrdup( pszFilename );
600 2 : }
601 :
602 2 : int ILI2Reader::SetupParser() {
603 :
604 : static int bXercesInitialized = FALSE;
605 :
606 2 : if( !bXercesInitialized )
607 : {
608 : try
609 : {
610 1 : XMLPlatformUtils::Initialize();
611 : }
612 :
613 0 : catch (const XMLException& toCatch)
614 : {
615 0 : char* msg = XMLString::transcode(toCatch.getMessage());
616 : CPLError( CE_Failure, CPLE_AppDefined,
617 : "Unable to initalize Xerces C++ based ILI2 reader. "
618 0 : "Error message:\n%s\n", msg );
619 0 : XMLString::release(&msg);
620 :
621 0 : return FALSE;
622 : }
623 1 : bXercesInitialized = TRUE;
624 : }
625 :
626 : // Cleanup any old parser.
627 2 : if( m_poSAXReader != NULL )
628 0 : CleanupParser();
629 :
630 : // Create and initialize parser.
631 2 : m_poSAXReader = XMLReaderFactory::createXMLReader();
632 :
633 2 : m_poILI2Handler = new ILI2Handler( this );
634 :
635 4 : m_poSAXReader->setContentHandler( m_poILI2Handler );
636 2 : m_poSAXReader->setErrorHandler( m_poILI2Handler );
637 2 : m_poSAXReader->setLexicalHandler( m_poILI2Handler );
638 2 : m_poSAXReader->setEntityResolver( m_poILI2Handler );
639 2 : m_poSAXReader->setDTDHandler( m_poILI2Handler );
640 :
641 : /* No Validation
642 : #if (OGR_ILI2_VALIDATION)
643 : m_poSAXReader->setFeature(
644 : XMLString::transcode("http://xml.org/sax/features/validation"), true);
645 : m_poSAXReader->setFeature(
646 : XMLString::transcode("http://xml.org/sax/features/namespaces"), true);
647 :
648 : m_poSAXReader->setFeature( XMLUni::fgSAX2CoreNameSpaces, true );
649 : m_poSAXReader->setFeature( XMLUni::fgXercesSchema, true );
650 :
651 : // m_poSAXReader->setDoSchema(true);
652 : // m_poSAXReader->setValidationSchemaFullChecking(true);
653 : #else
654 : */
655 2 : XMLCh *tmpCh = XMLString::transcode("http://xml.org/sax/features/validation");
656 2 : m_poSAXReader->setFeature(tmpCh, false);
657 2 : XMLString::release(&tmpCh);
658 2 : tmpCh = XMLString::transcode("http://xml.org/sax/features/namespaces");
659 2 : m_poSAXReader->setFeature(tmpCh, false);
660 2 : XMLString::release(&tmpCh);
661 : //#endif
662 :
663 2 : m_bReadStarted = FALSE;
664 :
665 2 : return TRUE;
666 : }
667 :
668 2 : void ILI2Reader::CleanupParser() {
669 2 : if( m_poSAXReader == NULL )
670 0 : return;
671 :
672 2 : delete m_poSAXReader;
673 2 : m_poSAXReader = NULL;
674 :
675 2 : delete m_poILI2Handler;
676 2 : m_poILI2Handler = NULL;
677 :
678 2 : m_bReadStarted = FALSE;
679 : }
680 :
681 2 : int ILI2Reader::SaveClasses( const char *pszFile = NULL ) {
682 :
683 : // Add logic later to determine reasonable default schema file.
684 2 : if( pszFile == NULL )
685 0 : return FALSE;
686 :
687 : // parse and create layers and features
688 : try
689 : {
690 2 : CPLDebug( "OGR_ILI", "Parsing %s", pszFile);
691 2 : m_poSAXReader->parse(pszFile);
692 : }
693 0 : catch (const SAXException& toCatch)
694 : {
695 0 : char* msg = XMLString::transcode(toCatch.getMessage());
696 : CPLError( CE_Failure, CPLE_AppDefined,
697 0 : "Parsing failed: %s\n", msg );
698 0 : XMLString::release(&msg);
699 :
700 0 : return FALSE;
701 : }
702 :
703 2 : if (m_missAttrs.size() != 0) {
704 0 : m_missAttrs.sort();
705 0 : m_missAttrs.unique();
706 0 : string attrs = "";
707 0 : list<string>::const_iterator it;
708 0 : for (it = m_missAttrs.begin(); it != m_missAttrs.end(); ++it)
709 0 : attrs += *it + ", ";
710 :
711 : CPLError( CE_Warning, CPLE_NotSupported,
712 0 : "Failed to add new definition to existing layers, attributes not saved: %s", attrs.c_str() );
713 : }
714 :
715 2 : return TRUE;
716 : }
717 :
718 2 : list<OGRLayer *> ILI2Reader::GetLayers() {
719 2 : return m_listLayer;
720 : }
721 :
722 0 : int ILI2Reader::GetLayerCount() {
723 0 : return m_listLayer.size();
724 : }
725 :
726 :
727 62 : int ILI2Reader::AddFeature(DOMElement *elem) {
728 62 : bool newLayer = true;
729 62 : OGRLayer *curLayer = 0;
730 62 : char *pszName = XMLString::transcode(elem->getTagName());
731 :
732 : // test if this layer exist
733 192 : for (list<OGRLayer *>::reverse_iterator layerIt = m_listLayer.rbegin();
734 : layerIt != m_listLayer.rend();
735 : ++layerIt) {
736 187 : OGRFeatureDefn *fDef = (*layerIt)->GetLayerDefn();
737 187 : if (cmpStr(fDef->GetName(), pszName) == 0) {
738 57 : newLayer = false;
739 57 : curLayer = *layerIt;
740 57 : break;
741 : }
742 : }
743 :
744 : // add a layer
745 62 : if (newLayer) { // FIXME in Layer: SRS Writer Type datasource
746 5 : CPLDebug( "OGR_ILI", "Adding layer: %s", pszName );
747 : // new layer data
748 5 : OGRSpatialReference *poSRSIn = NULL; // FIXME fix values for initial layer
749 5 : int bWriterIn = 0;
750 5 : OGRwkbGeometryType eReqType = wkbUnknown;
751 5 : OGRILI2DataSource *poDSIn = NULL;
752 5 : curLayer = new OGRILI2Layer(pszName, poSRSIn, bWriterIn, eReqType, poDSIn);
753 5 : m_listLayer.push_back(curLayer);
754 : }
755 :
756 : // the feature and field definition
757 62 : OGRFeatureDefn *featureDef = curLayer->GetLayerDefn();
758 62 : if (newLayer) {
759 : // add TID field
760 5 : OGRFieldDefn ofieldDefn (ILI2_TID, OFTString);
761 5 : featureDef->AddFieldDefn(&ofieldDefn);
762 :
763 5 : setFieldDefn(featureDef, elem);
764 : }
765 :
766 : // add the features
767 62 : OGRFeature *feature = new OGRFeature(featureDef);
768 :
769 : // assign TID
770 62 : int fIndex = feature->GetFieldIndex(ILI2_TID);
771 62 : if (fIndex != -1) {
772 31 : XMLCh *pszIli2_tid = XMLString::transcode(ILI2_TID);
773 31 : char *fChVal = XMLString::transcode(elem->getAttribute(pszIli2_tid));
774 31 : feature->SetField(fIndex, fChVal);
775 31 : XMLString::release (&pszIli2_tid);
776 31 : XMLString::release (&fChVal);
777 : } else {
778 31 : CPLDebug( "OGR_ILI","'%s' not found", ILI2_TID);
779 : }
780 :
781 62 : SetFieldValues(feature, elem);
782 62 : curLayer->SetFeature(feature);
783 :
784 62 : XMLString::release (&pszName);
785 :
786 62 : return 0;
787 : }
788 :
789 2 : IILI2Reader *CreateILI2Reader() {
790 2 : return new ILI2Reader();
791 : }
792 :
793 276 : void DestroyILI2Reader(IILI2Reader* reader)
794 : {
795 276 : if (reader)
796 2 : delete reader;
797 276 : }
|