1 : /******************************************************************************
2 : * $Id: ili2reader.cpp 23895 2012-02-04 11:21:18Z rouault $
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 23895 2012-02-04 11:21:18Z rouault $");
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 0 : int cmpStr(string s1, string s2) {
69 :
70 0 : string::const_iterator p1 = s1.begin();
71 0 : string::const_iterator p2 = s2.begin();
72 :
73 0 : while (p1 != s1.end() && p2 != s2.end()) {
74 0 : if (toupper(*p1) != toupper(*p2))
75 0 : return (toupper(*p1) < toupper(*p2)) ? -1 : 1;
76 0 : ++p1;
77 0 : ++p2;
78 : }
79 :
80 : return (s2.size() == s1.size()) ? 0 :
81 0 : (s1.size() < s2.size()) ? -1 : 1;
82 : }
83 :
84 0 : string ltrim(string tmpstr) {
85 0 : unsigned int i = 0;
86 0 : while (i < tmpstr.length() && (tmpstr[i] == ' ' || tmpstr[i] == '\t' || tmpstr[i] == '\r' || tmpstr[i] == '\n')) ++i;
87 0 : return i > 0 ? tmpstr.substr(i, tmpstr.length()-i) : tmpstr;
88 : }
89 :
90 0 : string rtrim(string tmpstr) {
91 0 : if (tmpstr.length() == 0) return tmpstr;
92 0 : unsigned int i = tmpstr.length() - 1;
93 0 : while (i >= 0 && (tmpstr[i] == ' ' || tmpstr[i] == '\t' || tmpstr[i] == '\r' || tmpstr[i] == '\n')) --i;
94 0 : return i < tmpstr.length() - 1 ? tmpstr.substr(0, i+1) : tmpstr;
95 : }
96 :
97 0 : string trim(string tmpstr) {
98 0 : tmpstr = ltrim(tmpstr);
99 0 : tmpstr = rtrim(tmpstr);
100 0 : return tmpstr;
101 : }
102 :
103 0 : int getGeometryTypeOfElem(DOMElement* elem) {
104 0 : int type = ILI2_STRING_TYPE;
105 0 : char* pszTagName = XMLString::transcode(elem->getTagName());
106 :
107 0 : if (elem && elem->getNodeType() == DOMNode::ELEMENT_NODE) {
108 0 : if (cmpStr(ILI2_COORD, pszTagName) == 0) {
109 0 : type = ILI2_COORD_TYPE;
110 0 : } else if (cmpStr(ILI2_ARC, pszTagName) == 0) {
111 0 : type = ILI2_ARC_TYPE;
112 0 : } else if (cmpStr(ILI2_POLYLINE, pszTagName) == 0) {
113 0 : type = ILI2_POLYLINE_TYPE;
114 0 : } else if (cmpStr(ILI2_BOUNDARY, pszTagName) == 0) {
115 0 : type = ILI2_BOUNDARY_TYPE;
116 0 : } else if (cmpStr(ILI2_AREA, pszTagName) == 0) {
117 0 : type = ILI2_AREA_TYPE;
118 0 : } else if (cmpStr(ILI2_SURFACE, pszTagName) == 0) {
119 0 : type = ILI2_AREA_TYPE;
120 : }
121 : }
122 0 : XMLString::release(&pszTagName);
123 0 : return type;
124 : }
125 :
126 0 : char *getObjValue(DOMElement *elem) {
127 0 : DOMElement *textElem = (DOMElement *)elem->getFirstChild();
128 :
129 0 : if ((textElem != NULL) && (textElem->getNodeType() == DOMNode::TEXT_NODE))
130 : {
131 0 : char* pszNodeValue = XMLString::transcode(textElem->getNodeValue());
132 0 : char* pszRet = CPLStrdup(pszNodeValue);
133 0 : XMLString::release(&pszNodeValue);
134 0 : return pszRet;
135 : }
136 :
137 0 : return NULL;
138 : }
139 :
140 0 : char *getREFValue(DOMElement *elem) {
141 0 : XMLCh* pszIli2_ref = XMLString::transcode(ILI2_REF);
142 0 : char* pszREFValue = XMLString::transcode(elem->getAttribute(pszIli2_ref));
143 0 : char* pszRet = CPLStrdup(pszREFValue);
144 0 : XMLString::release(&pszIli2_ref);
145 0 : XMLString::release(&pszREFValue);
146 0 : return pszRet;
147 : }
148 :
149 0 : OGRPoint *getPoint(DOMElement *elem) {
150 : // elem -> COORD (or ARC)
151 0 : OGRPoint *pt = new OGRPoint();
152 :
153 0 : DOMElement *coordElem = (DOMElement *)elem->getFirstChild();
154 0 : while (coordElem != NULL) {
155 0 : char* pszTagName = XMLString::transcode(coordElem->getTagName());
156 0 : char* pszObjValue = getObjValue(coordElem);
157 0 : if (cmpStr("C1", pszTagName) == 0)
158 0 : pt->setX(atof(pszObjValue));
159 0 : else if (cmpStr("C2", pszTagName) == 0)
160 0 : pt->setY(atof(pszObjValue));
161 0 : else if (cmpStr("C3", pszTagName) == 0)
162 0 : pt->setZ(atof(pszObjValue));
163 0 : CPLFree(pszObjValue);
164 0 : XMLString::release(&pszTagName);
165 0 : coordElem = (DOMElement *)coordElem->getNextSibling();
166 : }
167 0 : pt->flattenTo2D();
168 0 : 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 0 : OGRLineString *getLineString(DOMElement *elem, int bAsLinearRing) {
214 : // elem -> POLYLINE
215 : OGRLineString *ls;
216 0 : if (bAsLinearRing)
217 0 : ls = new OGRLinearRing();
218 : else
219 0 : ls = new OGRLineString();
220 :
221 0 : DOMElement *lineElem = (DOMElement *)elem->getFirstChild();
222 0 : while (lineElem != NULL) {
223 0 : char* pszTagName = XMLString::transcode(lineElem->getTagName());
224 0 : if (cmpStr(ILI2_COORD, pszTagName) == 0)
225 : {
226 0 : OGRPoint* poPoint = getPoint(lineElem);
227 0 : ls->addPoint(poPoint);
228 0 : delete poPoint;
229 : }
230 0 : 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 0 : XMLString::release(&pszTagName);
273 :
274 0 : lineElem = (DOMElement *)lineElem->getNextSibling();
275 : }
276 :
277 0 : return ls;
278 : }
279 :
280 0 : OGRLinearRing *getBoundary(DOMElement *elem) {
281 :
282 0 : DOMElement *lineElem = (DOMElement *)elem->getFirstChild();
283 0 : if (lineElem != NULL)
284 : {
285 0 : char* pszTagName = XMLString::transcode(lineElem->getTagName());
286 0 : if (cmpStr(ILI2_POLYLINE, pszTagName) == 0)
287 : {
288 0 : XMLString::release(&pszTagName);
289 0 : return (OGRLinearRing*) getLineString(lineElem, TRUE);
290 : }
291 0 : XMLString::release(&pszTagName);
292 : }
293 :
294 0 : return new OGRLinearRing();
295 : }
296 :
297 0 : OGRPolygon *getPolygon(DOMElement *elem) {
298 0 : OGRPolygon *pg = new OGRPolygon();
299 :
300 0 : DOMElement *boundaryElem = (DOMElement *)elem->getFirstChild(); // outer boundary
301 0 : while (boundaryElem != NULL) {
302 0 : char* pszTagName = XMLString::transcode(boundaryElem->getTagName());
303 0 : if (cmpStr(ILI2_BOUNDARY, pszTagName) == 0)
304 0 : pg->addRingDirectly(getBoundary(boundaryElem));
305 0 : XMLString::release(&pszTagName);
306 0 : boundaryElem = (DOMElement *)boundaryElem->getNextSibling(); // inner boundaries
307 : }
308 :
309 0 : return pg;
310 : }
311 :
312 0 : OGRGeometry *ILI2Reader::getGeometry(DOMElement *elem, int type) {
313 0 : OGRGeometryCollection *gm = new OGRGeometryCollection();
314 :
315 0 : DOMElement *childElem = elem;
316 0 : while (childElem != NULL) {
317 0 : char* pszTagName = XMLString::transcode(childElem->getTagName());
318 0 : switch (type) {
319 : case ILI2_COORD_TYPE :
320 0 : if (cmpStr(ILI2_COORD, pszTagName) == 0)
321 : {
322 0 : delete gm;
323 0 : XMLString::release(&pszTagName);
324 0 : 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 0 : if (cmpStr(ILI2_POLYLINE, pszTagName) == 0)
338 : {
339 0 : delete gm;
340 0 : XMLString::release(&pszTagName);
341 0 : 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 0 : if ((cmpStr(ILI2_AREA, pszTagName) == 0) ||
354 : (cmpStr(ILI2_SURFACE, pszTagName) == 0))
355 : {
356 0 : delete gm;
357 0 : XMLString::release(&pszTagName);
358 0 : 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 0 : const char* ILI2Reader::GetLayerName(IOM_BASKET model, IOM_OBJECT table) {
378 : static char layername[512];
379 0 : IOM_OBJECT topic = GetAttrObj(model, table, "container");
380 0 : layername[0] = '\0';
381 0 : strcat(layername, iom_getattrvalue(GetAttrObj(model, topic, "container"), "name"));
382 0 : strcat(layername, ".");
383 0 : strcat(layername, iom_getattrvalue(topic, "name"));
384 0 : strcat(layername, ".");
385 0 : strcat(layername, iom_getattrvalue(table, "name"));
386 0 : return layername;
387 : }
388 :
389 0 : void ILI2Reader::AddField(OGRLayer* layer, IOM_BASKET model, IOM_OBJECT obj) {
390 0 : const char* typenam = "Reference";
391 0 : if (EQUAL(iom_getobjecttag(obj),"iom04.metamodel.LocalAttribute")) typenam = GetTypeName(model, obj);
392 0 : if (EQUAL(typenam, "iom04.metamodel.SurfaceType")) {
393 0 : } else if (EQUAL(typenam, "iom04.metamodel.AreaType")) {
394 0 : } else if (EQUAL(typenam, "iom04.metamodel.PolylineType") ) {
395 0 : } else if (EQUAL(typenam, "iom04.metamodel.CoordType")) {
396 : } else {
397 0 : OGRFieldDefn fieldDef(iom_getattrvalue(obj, "name"), OFTString);
398 0 : layer->GetLayerDefn()->AddFieldDefn(&fieldDef);
399 0 : CPLDebug( "OGR_ILI", "Field %s: %s", fieldDef.GetNameRef(), typenam);
400 : }
401 0 : }
402 :
403 0 : int ILI2Reader::ReadModel(char **modelFilenames) {
404 :
405 : IOM_BASKET model;
406 : IOM_ITERATOR modelelei;
407 : IOM_OBJECT modelele;
408 :
409 0 : iom_init();
410 :
411 : // set error listener to a iom provided one, that just
412 : // dumps all errors to stderr
413 0 : iom_seterrlistener(iom_stderrlistener);
414 :
415 : // compile ili models
416 0 : model=iom_compileIli(CSLCount(modelFilenames), modelFilenames);
417 0 : 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 0 : modelelei=iom_iteratorobject(model);
425 0 : modelele=iom_nextobject(modelelei);
426 0 : while(modelele){
427 0 : const char *tag=iom_getobjecttag(modelele);
428 0 : if (tag && EQUAL(tag,"iom04.metamodel.Table")) {
429 0 : const char* topic = iom_getattrvalue(GetAttrObj(model, modelele, "container"), "name");
430 0 : if (!EQUAL(topic, "INTERLIS")) {
431 0 : const char* layername = GetLayerName(model, modelele);
432 0 : OGRLayer* layer = new OGRILI2Layer(layername, NULL, 0, wkbUnknown, NULL);
433 0 : m_listLayer.push_back(layer);
434 0 : CPLDebug( "OGR_ILI", "Reading table model '%s'", layername );
435 :
436 : // read fields
437 : IOM_OBJECT fields[255];
438 : IOM_OBJECT roledefs[255];
439 0 : memset(fields, 0, 255);
440 0 : memset(roledefs, 0, 255);
441 0 : int maxIdx = -1;
442 0 : IOM_ITERATOR fieldit=iom_iteratorobject(model);
443 0 : for (IOM_OBJECT fieldele=iom_nextobject(fieldit); fieldele; fieldele=iom_nextobject(fieldit)){
444 0 : const char *etag=iom_getobjecttag(fieldele);
445 0 : if (etag && (EQUAL(etag,"iom04.metamodel.ViewableAttributesAndRoles"))) {
446 0 : IOM_OBJECT table = GetAttrObj(model, fieldele, "viewable");
447 0 : if (table == modelele) {
448 0 : IOM_OBJECT obj = GetAttrObj(model, fieldele, "attributesAndRoles");
449 0 : int ili1AttrIdx = GetAttrObjPos(fieldele, "attributesAndRoles")-1;
450 0 : if (EQUAL(iom_getobjecttag(obj),"iom04.metamodel.RoleDef")) {
451 : //??ili1AttrIdx = atoi(iom_getattrvalue(GetAttrObj(model, obj, "oppend"), "ili1AttrIdx"));
452 0 : roledefs[ili1AttrIdx] = obj;
453 : } else {
454 0 : fields[ili1AttrIdx] = obj;
455 : }
456 0 : if (ili1AttrIdx > maxIdx) maxIdx = ili1AttrIdx;
457 : //CPLDebug( "OGR_ILI", "Field %s Pos: %d", iom_getattrvalue(obj, "name"), ili1AttrIdx);
458 : }
459 : }
460 0 : iom_releaseobject(fieldele);
461 : }
462 0 : iom_releaseiterator(fieldit);
463 :
464 0 : for (int i=0; i<=maxIdx; i++) {
465 0 : IOM_OBJECT obj = fields[i];
466 0 : IOM_OBJECT roleobj = roledefs[i];
467 0 : if (roleobj) AddField(layer, model, roleobj);
468 0 : if (obj) AddField(layer, model, obj);
469 : }
470 : }
471 : }
472 0 : iom_releaseobject(modelele);
473 :
474 0 : modelele=iom_nextobject(modelelei);
475 : }
476 :
477 0 : iom_releaseiterator(modelelei);
478 :
479 0 : iom_releasebasket(model);
480 :
481 0 : iom_end();
482 :
483 0 : return 0;
484 : }
485 :
486 0 : char* fieldName(DOMElement* elem) {
487 0 : string fullname;
488 0 : int depth = 0;
489 : DOMNode *node;
490 0 : for (node = elem; node; node = node->getParentNode()) ++depth;
491 0 : 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 0 : CPLAssert( depth < (int)(sizeof(elements) / sizeof(DOMNode*)) );
497 :
498 0 : int d=0;
499 0 : for (node = elem; d<depth; node = node->getParentNode()) elements[d++] = node;
500 0 : for (d=depth-1; d>=0; --d) {
501 0 : if (d < depth-1) fullname += "_";
502 0 : char* pszNodeName = XMLString::transcode(elements[d]->getNodeName());
503 0 : fullname += pszNodeName;
504 0 : XMLString::release(&pszNodeName);
505 : }
506 0 : return CPLStrdup(fullname.c_str());
507 : }
508 :
509 0 : void ILI2Reader::setFieldDefn(OGRFeatureDefn *featureDef, DOMElement* elem) {
510 0 : int type = 0;
511 : //recursively search children
512 0 : for (DOMElement *childElem = (DOMElement *)elem->getFirstChild();
513 0 : type == 0 && childElem && childElem->getNodeType() == DOMNode::ELEMENT_NODE;
514 0 : childElem = (DOMElement*)childElem->getNextSibling()) {
515 0 : type = getGeometryTypeOfElem(childElem);
516 0 : if (type == 0) {
517 0 : if (childElem->getFirstChild() && childElem->getFirstChild()->getNodeType() == DOMNode::ELEMENT_NODE) {
518 0 : setFieldDefn(featureDef, childElem);
519 : } else {
520 0 : char *fName = fieldName(childElem);
521 0 : if (featureDef->GetFieldIndex(fName) == -1) {
522 0 : CPLDebug( "OGR_ILI", "AddFieldDefn: %s",fName );
523 0 : OGRFieldDefn oFieldDefn(fName, OFTString);
524 0 : featureDef->AddFieldDefn(&oFieldDefn);
525 : }
526 0 : CPLFree(fName);
527 : }
528 : }
529 : }
530 0 : }
531 :
532 0 : void ILI2Reader::SetFieldValues(OGRFeature *feature, DOMElement* elem) {
533 0 : int type = 0;
534 : //recursively search children
535 0 : for (DOMElement *childElem = (DOMElement *)elem->getFirstChild();
536 0 : type == 0 && childElem && childElem->getNodeType() == DOMNode::ELEMENT_NODE;
537 0 : childElem = (DOMElement*)childElem->getNextSibling()) {
538 0 : type = getGeometryTypeOfElem(childElem);
539 0 : if (type == 0) {
540 0 : if (childElem->getFirstChild() && childElem->getFirstChild()->getNodeType() == DOMNode::ELEMENT_NODE) {
541 0 : SetFieldValues(feature, childElem);
542 : } else {
543 0 : char *fName = fieldName(childElem);
544 0 : int fIndex = feature->GetFieldIndex(fName);
545 0 : if (fIndex != -1) {
546 0 : char * objVal = getObjValue(childElem);
547 0 : if (objVal == NULL)
548 0 : objVal = getREFValue(childElem); // only to try
549 0 : feature->SetField(fIndex, objVal);
550 0 : CPLFree(objVal);
551 : } else {
552 0 : m_missAttrs.push_back(fName);
553 : }
554 0 : CPLFree(fName);
555 : }
556 : } else {
557 0 : feature->SetGeometryDirectly(getGeometry(childElem, type));
558 : }
559 : }
560 0 : }
561 :
562 :
563 : //
564 : // ILI2Reader
565 : //
566 0 : IILI2Reader::~IILI2Reader() {
567 0 : }
568 :
569 0 : ILI2Reader::ILI2Reader() {
570 0 : m_poILI2Handler = NULL;
571 0 : m_poSAXReader = NULL;
572 0 : m_bReadStarted = FALSE;
573 :
574 0 : m_pszFilename = NULL;
575 :
576 0 : SetupParser();
577 0 : }
578 :
579 0 : ILI2Reader::~ILI2Reader() {
580 0 : CPLFree( m_pszFilename );
581 :
582 0 : CleanupParser();
583 :
584 0 : list<OGRLayer *>::const_iterator layerIt = m_listLayer.begin();
585 0 : while (layerIt != m_listLayer.end()) {
586 0 : OGRILI2Layer *tmpLayer = (OGRILI2Layer *)*layerIt;
587 0 : delete tmpLayer;
588 0 : layerIt++;
589 : }
590 0 : }
591 :
592 0 : void ILI2Reader::SetArcDegrees(double arcDegrees) {
593 0 : arcIncr = arcDegrees*PI/180;
594 0 : }
595 :
596 0 : void ILI2Reader::SetSourceFile( const char *pszFilename ) {
597 0 : CPLFree( m_pszFilename );
598 0 : m_pszFilename = CPLStrdup( pszFilename );
599 0 : }
600 :
601 0 : int ILI2Reader::SetupParser() {
602 :
603 : static int bXercesInitialized = FALSE;
604 :
605 0 : if( !bXercesInitialized )
606 : {
607 : try
608 : {
609 0 : XMLPlatformUtils::Initialize();
610 : }
611 :
612 0 : catch (const XMLException& toCatch)
613 : {
614 0 : char* msg = XMLString::transcode(toCatch.getMessage());
615 : CPLError( CE_Failure, CPLE_AppDefined,
616 : "Unable to initalize Xerces C++ based ILI2 reader. "
617 0 : "Error message:\n%s\n", msg );
618 0 : XMLString::release(&msg);
619 :
620 0 : return FALSE;
621 : }
622 0 : bXercesInitialized = TRUE;
623 : }
624 :
625 : // Cleanup any old parser.
626 0 : if( m_poSAXReader != NULL )
627 0 : CleanupParser();
628 :
629 : // Create and initialize parser.
630 0 : m_poSAXReader = XMLReaderFactory::createXMLReader();
631 :
632 0 : m_poILI2Handler = new ILI2Handler( this );
633 :
634 0 : m_poSAXReader->setContentHandler( m_poILI2Handler );
635 0 : m_poSAXReader->setErrorHandler( m_poILI2Handler );
636 0 : m_poSAXReader->setLexicalHandler( m_poILI2Handler );
637 0 : m_poSAXReader->setEntityResolver( m_poILI2Handler );
638 0 : m_poSAXReader->setDTDHandler( m_poILI2Handler );
639 :
640 : /* No Validation
641 : #if (OGR_ILI2_VALIDATION)
642 : m_poSAXReader->setFeature(
643 : XMLString::transcode("http://xml.org/sax/features/validation"), true);
644 : m_poSAXReader->setFeature(
645 : XMLString::transcode("http://xml.org/sax/features/namespaces"), true);
646 :
647 : m_poSAXReader->setFeature( XMLUni::fgSAX2CoreNameSpaces, true );
648 : m_poSAXReader->setFeature( XMLUni::fgXercesSchema, true );
649 :
650 : // m_poSAXReader->setDoSchema(true);
651 : // m_poSAXReader->setValidationSchemaFullChecking(true);
652 : #else
653 : */
654 0 : XMLCh *tmpCh = XMLString::transcode("http://xml.org/sax/features/validation");
655 0 : m_poSAXReader->setFeature(tmpCh, false);
656 0 : XMLString::release(&tmpCh);
657 0 : tmpCh = XMLString::transcode("http://xml.org/sax/features/namespaces");
658 0 : m_poSAXReader->setFeature(tmpCh, false);
659 0 : XMLString::release(&tmpCh);
660 : //#endif
661 :
662 0 : m_bReadStarted = FALSE;
663 :
664 0 : return TRUE;
665 : }
666 :
667 0 : void ILI2Reader::CleanupParser() {
668 0 : if( m_poSAXReader == NULL )
669 0 : return;
670 :
671 0 : delete m_poSAXReader;
672 0 : m_poSAXReader = NULL;
673 :
674 0 : delete m_poILI2Handler;
675 0 : m_poILI2Handler = NULL;
676 :
677 0 : m_bReadStarted = FALSE;
678 : }
679 :
680 0 : int ILI2Reader::SaveClasses( const char *pszFile = NULL ) {
681 :
682 : // Add logic later to determine reasonable default schema file.
683 0 : if( pszFile == NULL )
684 0 : return FALSE;
685 :
686 : // parse and create layers and features
687 : try
688 : {
689 0 : m_poSAXReader->parse(pszFile);
690 : }
691 0 : catch (const SAXException& toCatch)
692 : {
693 0 : char* msg = XMLString::transcode(toCatch.getMessage());
694 : CPLError( CE_Failure, CPLE_AppDefined,
695 0 : "Parsing failed: %s\n", msg );
696 0 : XMLString::release(&msg);
697 :
698 0 : return FALSE;
699 : }
700 :
701 0 : if (m_missAttrs.size() != 0) {
702 0 : m_missAttrs.sort();
703 0 : m_missAttrs.unique();
704 0 : string attrs = "";
705 0 : list<string>::const_iterator it = m_missAttrs.begin();
706 0 : for (it = m_missAttrs.begin(); it != m_missAttrs.end(); ++it)
707 0 : attrs += *it + ", ";
708 :
709 : CPLError( CE_Warning, CPLE_NotSupported,
710 0 : "Failed to add new definition to existing layers, attributes not saved: %s", attrs.c_str() );
711 : }
712 :
713 0 : return TRUE;
714 : }
715 :
716 0 : list<OGRLayer *> ILI2Reader::GetLayers() {
717 0 : return m_listLayer;
718 : }
719 :
720 0 : int ILI2Reader::GetLayerCount() {
721 0 : return m_listLayer.size();
722 : }
723 :
724 :
725 0 : int ILI2Reader::AddFeature(DOMElement *elem) {
726 0 : bool newLayer = true;
727 0 : OGRLayer *curLayer = 0;
728 0 : char *pszName = XMLString::transcode(elem->getTagName());
729 :
730 : // test if this layer exist
731 0 : for (list<OGRLayer *>::reverse_iterator layerIt = m_listLayer.rbegin();
732 : layerIt != m_listLayer.rend();
733 : ++layerIt) {
734 0 : OGRFeatureDefn *fDef = (*layerIt)->GetLayerDefn();
735 0 : if (cmpStr(fDef->GetName(), pszName) == 0) {
736 0 : newLayer = false;
737 0 : curLayer = *layerIt;
738 0 : break;
739 : }
740 : }
741 :
742 : // add a layer
743 0 : if (newLayer) { // FIXME in Layer: SRS Writer Type datasource
744 0 : CPLDebug( "OGR_ILI", "Adding layer: %s", pszName );
745 : // new layer data
746 0 : OGRSpatialReference *poSRSIn = NULL; // FIXME fix values for initial layer
747 0 : int bWriterIn = 0;
748 0 : OGRwkbGeometryType eReqType = wkbUnknown;
749 0 : OGRILI2DataSource *poDSIn = NULL;
750 0 : curLayer = new OGRILI2Layer(pszName, poSRSIn, bWriterIn, eReqType, poDSIn);
751 0 : m_listLayer.push_back(curLayer);
752 : }
753 :
754 : // the feature and field definition
755 0 : OGRFeatureDefn *featureDef = curLayer->GetLayerDefn();
756 0 : if (newLayer) {
757 : // the TID feature
758 0 : OGRFieldDefn ofieldDefn (ILI2_TID, OFTString);
759 0 : featureDef->AddFieldDefn(&ofieldDefn);
760 :
761 0 : setFieldDefn(featureDef, elem);
762 : }
763 :
764 : // add the features
765 0 : OGRFeature *feature = new OGRFeature(featureDef);
766 :
767 : // the TID feature
768 0 : int fIndex = feature->GetFieldIndex(ILI2_TID);
769 0 : XMLCh *pszIli2_tid = XMLString::transcode(ILI2_TID);
770 0 : char *fChVal = XMLString::transcode(elem->getAttribute(pszIli2_tid));
771 0 : feature->SetField(fIndex, fChVal);
772 0 : XMLString::release (&pszIli2_tid);
773 0 : XMLString::release (&fChVal);
774 :
775 0 : SetFieldValues(feature, elem);
776 0 : curLayer->SetFeature(feature);
777 :
778 0 : XMLString::release (&pszName);
779 :
780 0 : return 0;
781 : }
782 :
783 0 : IILI2Reader *CreateILI2Reader() {
784 0 : return new ILI2Reader();
785 : }
786 :
787 436 : void DestroyILI2Reader(IILI2Reader* reader)
788 : {
789 436 : if (reader)
790 0 : delete reader;
791 436 : }
|