Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: Interlis 2 Translator
4 : * Purpose: Implements OGRILI2DataSource class.
5 : * Author: Markus Schnider, Sourcepole AG
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2004, Pirmin Kalberer, Sourcepole AG
9 : * Copyright (c) 2007-2008, Even Rouault <even dot rouault at spatialys.com>
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 "cpl_conv.h"
31 : #include "cpl_string.h"
32 :
33 : #include "ili2reader.h"
34 :
35 : #include "ogr_ili2.h"
36 :
37 : using namespace std;
38 :
39 : /************************************************************************/
40 : /* OGRILI2DataSource() */
41 : /************************************************************************/
42 :
43 81 : OGRILI2DataSource::OGRILI2DataSource()
44 81 : : pszName(nullptr), poImdReader(new ImdReader(2)), poReader(nullptr),
45 81 : fpOutput(nullptr), nLayers(0), papoLayers(nullptr)
46 : {
47 81 : }
48 :
49 : /************************************************************************/
50 : /* ~OGRILI2DataSource() */
51 : /************************************************************************/
52 :
53 162 : OGRILI2DataSource::~OGRILI2DataSource()
54 :
55 : {
56 83 : for (int i = 0; i < nLayers; i++)
57 : {
58 2 : delete papoLayers[i];
59 : }
60 81 : CPLFree(papoLayers);
61 :
62 81 : if (fpOutput != nullptr)
63 : {
64 1 : VSIFPrintfL(fpOutput, "</%s>\n", poImdReader->mainBasketName.c_str());
65 1 : VSIFPrintfL(fpOutput, "</DATASECTION>\n");
66 1 : VSIFPrintfL(fpOutput, "</TRANSFER>\n");
67 1 : VSIFCloseL(fpOutput);
68 : }
69 :
70 81 : DestroyILI2Reader(poReader);
71 81 : delete poImdReader;
72 81 : CPLFree(pszName);
73 162 : }
74 :
75 : /************************************************************************/
76 : /* Open() */
77 : /************************************************************************/
78 :
79 61 : int OGRILI2DataSource::Open(const char *pszNewName, char **papszOpenOptionsIn,
80 : int bTestOpen)
81 :
82 : {
83 122 : CPLString osBasename;
84 122 : CPLString osModelFilename;
85 :
86 61 : if (CSLFetchNameValue(papszOpenOptionsIn, "MODEL") != nullptr)
87 : {
88 0 : osBasename = pszNewName;
89 0 : osModelFilename = CSLFetchNameValue(papszOpenOptionsIn, "MODEL");
90 : }
91 : else
92 : {
93 61 : char **filenames = CSLTokenizeString2(pszNewName, ",", 0);
94 61 : int nCount = CSLCount(filenames);
95 61 : if (nCount == 0)
96 : {
97 0 : CSLDestroy(filenames);
98 0 : return FALSE;
99 : }
100 61 : osBasename = filenames[0];
101 :
102 61 : if (nCount > 1)
103 57 : osModelFilename = filenames[1];
104 :
105 61 : CSLDestroy(filenames);
106 : }
107 :
108 61 : pszName = CPLStrdup(osBasename);
109 :
110 : /* -------------------------------------------------------------------- */
111 : /* Open the source file. */
112 : /* -------------------------------------------------------------------- */
113 61 : VSILFILE *fp = VSIFOpenL(pszName, "r");
114 61 : if (fp == nullptr)
115 : {
116 57 : if (!bTestOpen)
117 0 : CPLError(CE_Failure, CPLE_OpenFailed,
118 : "Failed to open ILI2 file `%s'.", pszNewName);
119 :
120 57 : return FALSE;
121 : }
122 :
123 : /* -------------------------------------------------------------------- */
124 : /* If we aren't sure it is ILI2, load a header chunk and check */
125 : /* for signs it is ILI2 */
126 : /* -------------------------------------------------------------------- */
127 : char szHeader[1000];
128 4 : if (bTestOpen)
129 : {
130 : int nLen =
131 4 : static_cast<int>(VSIFReadL(szHeader, 1, sizeof(szHeader), fp));
132 4 : if (nLen == sizeof(szHeader))
133 4 : szHeader[sizeof(szHeader) - 1] = '\0';
134 : else
135 0 : szHeader[nLen] = '\0';
136 :
137 4 : if (szHeader[0] != '<' ||
138 4 : strstr(szHeader, "interlis.ch/INTERLIS2") == nullptr)
139 : {
140 : // "www.interlis.ch/INTERLIS2.3"
141 0 : VSIFCloseL(fp);
142 0 : return FALSE;
143 : }
144 : }
145 :
146 : /* -------------------------------------------------------------------- */
147 : /* We assume now that it is ILI2. Close and instantiate a */
148 : /* ILI2Reader on it. */
149 : /* -------------------------------------------------------------------- */
150 4 : VSIFCloseL(fp);
151 :
152 4 : poReader = CreateILI2Reader();
153 4 : if (poReader == nullptr)
154 : {
155 0 : CPLError(CE_Failure, CPLE_AppDefined,
156 : "File %s appears to be ILI2 but the ILI2 reader cannot\n"
157 : "be instantiated, likely because Xerces support was not\n"
158 : "configured in.",
159 : pszNewName);
160 0 : return FALSE;
161 : }
162 :
163 4 : if (!osModelFilename.empty())
164 3 : poReader->ReadModel(this, poImdReader, osModelFilename);
165 :
166 4 : poReader->SetSourceFile(pszName);
167 :
168 4 : poReader->SaveClasses(pszName);
169 :
170 4 : listLayer = poReader->GetLayers();
171 4 : list<OGRLayer *>::const_iterator layerIt;
172 48 : for (layerIt = listLayer.begin(); layerIt != listLayer.end(); ++layerIt)
173 : {
174 44 : (*layerIt)->ResetReading();
175 : }
176 :
177 4 : return TRUE;
178 : }
179 :
180 : /************************************************************************/
181 : /* Create() */
182 : /************************************************************************/
183 :
184 20 : int OGRILI2DataSource::Create(const char *pszFilename,
185 : CPL_UNUSED char **papszOptions)
186 :
187 : {
188 20 : char **filenames = CSLTokenizeString2(pszFilename, ",", 0);
189 20 : pszName = CPLStrdup(filenames[0]);
190 : const char *pszModelFilename =
191 20 : (CSLCount(filenames) > 1) ? filenames[1] : nullptr;
192 :
193 20 : if (pszModelFilename == nullptr)
194 : {
195 18 : CPLError(
196 : CE_Failure, CPLE_AppDefined,
197 : "ILI2 Create(): model file not specified in destination filename.");
198 18 : CSLDestroy(filenames);
199 18 : return FALSE;
200 : }
201 :
202 : /* -------------------------------------------------------------------- */
203 : /* Create the output file. */
204 : /* -------------------------------------------------------------------- */
205 :
206 2 : if (strcmp(pszName, "/vsistdout/") == 0 ||
207 2 : STARTS_WITH(pszName, "/vsigzip/"))
208 : {
209 0 : fpOutput = VSIFOpenL(pszName, "wb");
210 : }
211 2 : else if (STARTS_WITH(pszName, "/vsizip/"))
212 : {
213 0 : if (EQUAL(CPLGetExtension(pszName), "zip"))
214 : {
215 : char *pszNewName =
216 0 : CPLStrdup(CPLFormFilename(pszName, "out.xtf", nullptr));
217 0 : CPLFree(pszName);
218 0 : pszName = pszNewName;
219 : }
220 :
221 0 : fpOutput = VSIFOpenL(pszName, "wb");
222 : }
223 : else
224 2 : fpOutput = VSIFOpenL(pszName, "wb+");
225 2 : if (fpOutput == nullptr)
226 : {
227 1 : CPLError(CE_Failure, CPLE_OpenFailed, "Failed to create XTF file %s.",
228 : pszName);
229 1 : CSLDestroy(filenames);
230 1 : return FALSE;
231 : }
232 :
233 : /* -------------------------------------------------------------------- */
234 : /* Parse model */
235 : /* -------------------------------------------------------------------- */
236 1 : poImdReader->ReadModel(pszModelFilename);
237 :
238 : /* -------------------------------------------------------------------- */
239 : /* Write headers */
240 : /* -------------------------------------------------------------------- */
241 1 : VSIFPrintfL(fpOutput, "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n");
242 1 : VSIFPrintfL(fpOutput,
243 : "<TRANSFER xmlns=\"http://www.interlis.ch/INTERLIS2.3\">\n");
244 1 : VSIFPrintfL(fpOutput,
245 : "<HEADERSECTION SENDER=\"OGR/GDAL %s\" VERSION=\"2.3\">\n",
246 : GDALVersionInfo("RELEASE_NAME"));
247 1 : VSIFPrintfL(fpOutput, "<MODELS>\n");
248 3 : for (IliModelInfos::const_iterator it = poImdReader->modelInfos.begin();
249 5 : it != poImdReader->modelInfos.end(); ++it)
250 : {
251 6 : VSIFPrintfL(fpOutput,
252 : "<MODEL NAME=\"%s\" URI=\"%s\" VERSION=\"%s\"/>\n",
253 6 : it->name.c_str(), it->uri.c_str(), it->version.c_str());
254 : }
255 1 : VSIFPrintfL(fpOutput, "</MODELS>\n");
256 1 : VSIFPrintfL(fpOutput, "</HEADERSECTION>\n");
257 1 : VSIFPrintfL(fpOutput, "<DATASECTION>\n");
258 1 : const char *basketName = poImdReader->mainBasketName.c_str();
259 1 : VSIFPrintfL(fpOutput, "<%s BID=\"%s\">\n", basketName, basketName);
260 :
261 1 : CSLDestroy(filenames);
262 1 : return TRUE;
263 : }
264 :
265 : /************************************************************************/
266 : /* ICreateLayer() */
267 : /************************************************************************/
268 :
269 : OGRLayer *
270 2 : OGRILI2DataSource::ICreateLayer(const char *pszLayerName,
271 : const OGRGeomFieldDefn *poGeomFieldDefn,
272 : CSLConstList /*papszOptions*/)
273 : {
274 2 : if (fpOutput == nullptr)
275 0 : return nullptr;
276 :
277 2 : const auto eType = poGeomFieldDefn ? poGeomFieldDefn->GetType() : wkbNone;
278 :
279 : FeatureDefnInfo featureDefnInfo =
280 2 : poImdReader->GetFeatureDefnInfo(pszLayerName);
281 2 : OGRFeatureDefn *poFeatureDefn = featureDefnInfo.GetTableDefnRef();
282 2 : if (poFeatureDefn == nullptr)
283 : {
284 0 : CPLError(CE_Warning, CPLE_AppDefined,
285 : "Layer '%s' not found in model definition. "
286 : "Creating adhoc layer",
287 : pszLayerName);
288 0 : poFeatureDefn = new OGRFeatureDefn(pszLayerName);
289 0 : poFeatureDefn->SetGeomType(eType);
290 : }
291 : OGRILI2Layer *poLayer =
292 2 : new OGRILI2Layer(poFeatureDefn, featureDefnInfo.poGeomFieldInfos, this);
293 :
294 2 : nLayers++;
295 2 : papoLayers = static_cast<OGRILI2Layer **>(
296 2 : CPLRealloc(papoLayers, sizeof(OGRILI2Layer *) * nLayers));
297 2 : papoLayers[nLayers - 1] = poLayer;
298 :
299 2 : return poLayer;
300 : }
301 :
302 : /************************************************************************/
303 : /* TestCapability() */
304 : /************************************************************************/
305 :
306 0 : int OGRILI2DataSource::TestCapability(const char *pszCap)
307 :
308 : {
309 0 : if (EQUAL(pszCap, ODsCCreateLayer))
310 0 : return TRUE;
311 0 : else if (EQUAL(pszCap, ODsCCurveGeometries))
312 0 : return TRUE;
313 0 : else if (EQUAL(pszCap, ODsCZGeometries))
314 0 : return TRUE;
315 :
316 0 : return FALSE;
317 : }
318 :
319 : /************************************************************************/
320 : /* GetLayer() */
321 : /************************************************************************/
322 :
323 81 : OGRLayer *OGRILI2DataSource::GetLayer(int iLayer)
324 :
325 : {
326 81 : list<OGRLayer *>::const_iterator layerIt = listLayer.begin();
327 81 : int i = 0;
328 730 : while (i < iLayer && layerIt != listLayer.end())
329 : {
330 649 : ++i;
331 649 : ++layerIt;
332 : }
333 :
334 81 : if (i == iLayer && layerIt != listLayer.end())
335 : {
336 81 : OGRILI2Layer *tmpLayer = reinterpret_cast<OGRILI2Layer *>(*layerIt);
337 81 : return tmpLayer;
338 : }
339 :
340 0 : return nullptr;
341 : }
|