LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/ili - ili2reader.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 447 3 0.7 %
Date: 2012-04-28 Functions: 37 1 2.7 %

       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 : }

Generated by: LCOV version 1.7