1 : /******************************************************************************
2 : * $Id: ogrili2datasource.cpp 24408 2012-05-11 21:31:45Z pka $
3 : *
4 : * Project: Interlis 2 Translator
5 : * Purpose: Implements OGRILI2DataSource 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 "ili2reader.h"
35 : #include "iomhelper.h"
36 :
37 : using namespace std;
38 :
39 :
40 : CPL_CVSID("$Id: ogrili2datasource.cpp 24408 2012-05-11 21:31:45Z pka $");
41 :
42 : /************************************************************************/
43 : /* OGRILI2DataSource() */
44 : /************************************************************************/
45 :
46 276 : OGRILI2DataSource::OGRILI2DataSource()
47 :
48 : {
49 276 : pszName = NULL;
50 276 : poReader = NULL;
51 276 : fpTransfer = NULL;
52 276 : basket = NULL;
53 276 : nLayers = 0;
54 276 : papoLayers = NULL;
55 276 : }
56 :
57 : /************************************************************************/
58 : /* ~OGRILI2DataSource() */
59 : /************************************************************************/
60 :
61 276 : OGRILI2DataSource::~OGRILI2DataSource()
62 :
63 : {
64 : int i;
65 :
66 276 : for(i=0;i<nLayers;i++)
67 : {
68 0 : delete papoLayers[i];
69 : }
70 276 : CPLFree( papoLayers );
71 :
72 276 : if (basket) iom_releasebasket(basket);
73 276 : if (fpTransfer)
74 : {
75 : // write file
76 0 : iom_save(fpTransfer);
77 :
78 : // clean up
79 0 : iom_close(fpTransfer);
80 :
81 0 : iom_end();
82 :
83 : }
84 276 : DestroyILI2Reader( poReader );
85 276 : CPLFree( pszName );
86 276 : }
87 :
88 : /************************************************************************/
89 : /* Open() */
90 : /************************************************************************/
91 :
92 276 : int OGRILI2DataSource::Open( const char * pszNewName, int bTestOpen )
93 :
94 : {
95 : FILE *fp;
96 : char szHeader[1000];
97 :
98 276 : char **modelFilenames = NULL;
99 276 : char **filenames = CSLTokenizeString2( pszNewName, ",", 0 );
100 :
101 276 : pszName = CPLStrdup( filenames[0] );
102 :
103 276 : if( CSLCount(filenames) > 1 )
104 3 : modelFilenames = &filenames[1];
105 :
106 : /* -------------------------------------------------------------------- */
107 : /* Open the source file. */
108 : /* -------------------------------------------------------------------- */
109 276 : fp = VSIFOpen( pszName, "r" );
110 276 : if( fp == NULL )
111 : {
112 89 : if( !bTestOpen )
113 : CPLError( CE_Failure, CPLE_OpenFailed,
114 : "Failed to open ILI2 file `%s'.",
115 0 : pszNewName );
116 :
117 89 : CSLDestroy( filenames );
118 89 : return FALSE;
119 : }
120 :
121 : /* -------------------------------------------------------------------- */
122 : /* If we aren't sure it is ILI2, load a header chunk and check */
123 : /* for signs it is ILI2 */
124 : /* -------------------------------------------------------------------- */
125 187 : if( bTestOpen )
126 : {
127 187 : int nLen = (int)VSIFRead( szHeader, 1, sizeof(szHeader), fp );
128 187 : if (nLen == sizeof(szHeader))
129 127 : szHeader[sizeof(szHeader)-1] = '\0';
130 : else
131 60 : szHeader[nLen] = '\0';
132 :
133 187 : if( szHeader[0] != '<'
134 : || strstr(szHeader,"interlis.ch/INTERLIS2") == NULL )
135 : { // "www.interlis.ch/INTERLIS2.2"
136 185 : VSIFClose( fp );
137 185 : CSLDestroy( filenames );
138 185 : return FALSE;
139 : }
140 : }
141 :
142 : /* -------------------------------------------------------------------- */
143 : /* We assume now that it is ILI2. Close and instantiate a */
144 : /* ILI2Reader on it. */
145 : /* -------------------------------------------------------------------- */
146 2 : VSIFClose( fp );
147 :
148 2 : poReader = CreateILI2Reader();
149 2 : if( poReader == NULL )
150 : {
151 : CPLError( CE_Failure, CPLE_AppDefined,
152 : "File %s appears to be ILI2 but the ILI2 reader can't\n"
153 : "be instantiated, likely because Xerces support wasn't\n"
154 : "configured in.",
155 0 : pszNewName );
156 0 : CSLDestroy( filenames );
157 0 : return FALSE;
158 : }
159 :
160 2 : if (modelFilenames)
161 1 : poReader->ReadModel( modelFilenames );
162 :
163 2 : if( getenv( "ARC_DEGREES" ) != NULL ) {
164 : //No better way to pass arguments to the reader (it could even be an -lco arg)
165 0 : poReader->SetArcDegrees( atof( getenv("ARC_DEGREES") ) );
166 : }
167 :
168 2 : poReader->SetSourceFile( pszName );
169 :
170 2 : poReader->SaveClasses( pszName );
171 :
172 2 : listLayer = poReader->GetLayers();
173 2 : list<OGRLayer *>::const_iterator layerIt;
174 15 : for (layerIt = listLayer.begin(); layerIt != listLayer.end(); ++layerIt) {
175 13 : (*layerIt)->ResetReading();
176 : }
177 :
178 2 : CSLDestroy( filenames );
179 :
180 2 : return TRUE;
181 : }
182 :
183 :
184 : /************************************************************************/
185 : /* Create() */
186 : /************************************************************************/
187 :
188 0 : int OGRILI2DataSource::Create( const char *pszFilename,
189 : char **papszOptions )
190 :
191 : {
192 0 : char **filenames = CSLTokenizeString2( pszFilename, ",", 0 );
193 0 : pszName = CPLStrdup(filenames[0]);
194 0 : const char *pszModelFilename = (CSLCount(filenames)>1) ? filenames[1] : NULL;
195 :
196 0 : if( pszModelFilename == NULL )
197 : {
198 : CPLError( CE_Warning, CPLE_OpenFailed,
199 : "Model file '%s' (%s) not found : %s.",
200 0 : pszModelFilename, pszFilename, VSIStrerror( errno ) );
201 0 : CSLDestroy(filenames);
202 0 : return FALSE;
203 : }
204 :
205 0 : iom_init();
206 :
207 : // set error listener to a iom provided one, that just
208 : // dumps all errors to stderr
209 0 : iom_seterrlistener(iom_stderrlistener);
210 :
211 : // compile ili model
212 0 : char *iliFiles[1] = {(char *)pszModelFilename};
213 0 : IOM_BASKET model=iom_compileIli(1,iliFiles);
214 0 : if(!model){
215 : CPLError( CE_Warning, CPLE_OpenFailed,
216 : "iom_compileIli %s, %s.",
217 0 : pszName, VSIStrerror( errno ) );
218 0 : iom_end();
219 0 : CSLDestroy(filenames);
220 0 : return FALSE;
221 : }
222 :
223 : // open new file
224 0 : fpTransfer=iom_open(pszName,IOM_CREATE | IOM_DONTREAD,0);
225 0 : if(!fpTransfer){
226 : CPLError( CE_Warning, CPLE_OpenFailed,
227 : "Failed to open %s.",
228 0 : pszName );
229 0 : CSLDestroy(filenames);
230 0 : return FALSE;
231 : }
232 :
233 : // set model of new file
234 0 : iom_setmodel(fpTransfer,model);
235 :
236 0 : iom_setheadsender(fpTransfer, pszModelFilename);
237 :
238 0 : iom_setheadcomment(fpTransfer,"Created by OGR");
239 :
240 : // create new basket
241 : static char basketname[512];
242 0 : basketname[0] = '\0';
243 0 : const char* val = GetAttrObjName(model, "iom04.metamodel.DataModel");
244 0 : if (val)
245 : {
246 0 : strcat(basketname, val);
247 0 : strcat(basketname, ".");
248 0 : val = GetAttrObjName(model, "iom04.metamodel.Topic");
249 0 : if (val) strcat(basketname, val);
250 : }
251 : else
252 : {
253 0 : strcat(basketname, "Basket");
254 : }
255 :
256 0 : CSLDestroy(filenames);
257 :
258 0 : basket=iom_newbasket(fpTransfer);
259 0 : iom_setbaskettag(basket, basketname);
260 0 : iom_setbasketoid(basket, "0");
261 0 : return TRUE;
262 : }
263 :
264 : /************************************************************************/
265 : /* CreateLayer() */
266 : /************************************************************************/
267 :
268 : OGRLayer *
269 0 : OGRILI2DataSource::CreateLayer( const char * pszLayerName,
270 : OGRSpatialReference *poSRS,
271 : OGRwkbGeometryType eType,
272 : char ** papszOptions )
273 :
274 : {
275 0 : OGRILI2Layer *poLayer = new OGRILI2Layer(pszLayerName, poSRS, TRUE, eType, this);
276 :
277 0 : nLayers ++;
278 0 : papoLayers = (OGRILI2Layer**)CPLRealloc(papoLayers, sizeof(OGRILI2Layer*) * nLayers);
279 0 : papoLayers[nLayers-1] = poLayer;
280 :
281 0 : return poLayer;
282 : }
283 :
284 : /************************************************************************/
285 : /* TestCapability() */
286 : /************************************************************************/
287 :
288 0 : int OGRILI2DataSource::TestCapability( const char * pszCap )
289 :
290 : {
291 0 : if( EQUAL(pszCap,ODsCCreateLayer) )
292 0 : return TRUE;
293 : else
294 0 : return FALSE;
295 : }
296 :
297 : /************************************************************************/
298 : /* GetLayer() */
299 : /************************************************************************/
300 :
301 20 : OGRLayer *OGRILI2DataSource::GetLayer( int iLayer )
302 :
303 : {
304 20 : list<OGRLayer *>::const_iterator layerIt = listLayer.begin();
305 20 : int i = 0;
306 99 : while (i < iLayer && layerIt != listLayer.end()) {
307 59 : i++;
308 59 : layerIt++;
309 : }
310 :
311 20 : if (i == iLayer) {
312 20 : OGRILI2Layer *tmpLayer = (OGRILI2Layer *)*layerIt;
313 20 : return tmpLayer;
314 : } else
315 0 : return NULL;
316 : }
|