LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/ili - ili2reader.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 451 330 73.2 %
Date: 2012-12-26 Functions: 37 29 78.4 %

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

Generated by: LCOV version 1.7