1 : /******************************************************************************
2 : * $Id: ogrili2datasource.cpp 15089 2008-07-31 18:56:56Z rouault $
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 15089 2008-07-31 18:56:56Z rouault $");
41 :
42 : /************************************************************************/
43 : /* OGRILI2DataSource() */
44 : /************************************************************************/
45 :
46 174 : OGRILI2DataSource::OGRILI2DataSource()
47 :
48 : {
49 174 : pszName = NULL;
50 174 : poReader = NULL;
51 174 : fpTransfer = NULL;
52 174 : basket = NULL;
53 174 : nLayers = 0;
54 174 : papoLayers = NULL;
55 174 : }
56 :
57 : /************************************************************************/
58 : /* ~OGRILI2DataSource() */
59 : /************************************************************************/
60 :
61 174 : OGRILI2DataSource::~OGRILI2DataSource()
62 :
63 : {
64 : int i;
65 :
66 174 : for(i=0;i<nLayers;i++)
67 : {
68 0 : delete papoLayers[i];
69 : }
70 174 : CPLFree( papoLayers );
71 :
72 174 : if (basket) iom_releasebasket(basket);
73 174 : 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 174 : DestroyILI2Reader( poReader );
85 174 : CPLFree( pszName );
86 174 : }
87 :
88 : /************************************************************************/
89 : /* Open() */
90 : /************************************************************************/
91 :
92 174 : int OGRILI2DataSource::Open( const char * pszNewName, int bTestOpen )
93 :
94 : {
95 : FILE *fp;
96 : char szHeader[1000];
97 :
98 174 : char **modelFilenames = NULL;
99 174 : char **filenames = CSLTokenizeString2( pszNewName, ",", 0 );
100 :
101 174 : pszName = CPLStrdup( filenames[0] );
102 :
103 174 : if( CSLCount(filenames) > 1 )
104 0 : modelFilenames = &filenames[1];
105 :
106 : /* -------------------------------------------------------------------- */
107 : /* Open the source file. */
108 : /* -------------------------------------------------------------------- */
109 174 : fp = VSIFOpen( pszName, "r" );
110 174 : if( fp == NULL )
111 : {
112 65 : if( !bTestOpen )
113 : CPLError( CE_Failure, CPLE_OpenFailed,
114 : "Failed to open ILI2 file `%s'.",
115 0 : pszNewName );
116 :
117 65 : CSLDestroy( filenames );
118 65 : 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 109 : if( bTestOpen )
126 : {
127 109 : int nLen = (int)VSIFRead( szHeader, 1, sizeof(szHeader), fp );
128 109 : if (nLen == sizeof(szHeader))
129 71 : szHeader[sizeof(szHeader)-1] = '\0';
130 : else
131 38 : szHeader[nLen] = '\0';
132 :
133 109 : if( szHeader[0] != '<'
134 : || strstr(szHeader,"interlis.ch/INTERLIS2") == NULL )
135 : { // "www.interlis.ch/INTERLIS2.2"
136 109 : VSIFClose( fp );
137 109 : CSLDestroy( filenames );
138 109 : return FALSE;
139 : }
140 : }
141 :
142 : /* -------------------------------------------------------------------- */
143 : /* We assume now that it is ILI2. Close and instantiate a */
144 : /* ILI2Reader on it. */
145 : /* -------------------------------------------------------------------- */
146 0 : VSIFClose( fp );
147 :
148 0 : poReader = CreateILI2Reader();
149 0 : 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 0 : if (modelFilenames)
161 0 : poReader->ReadModel( modelFilenames );
162 :
163 0 : 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 0 : poReader->SetSourceFile( pszName );
169 :
170 0 : poReader->SaveClasses( pszName );
171 :
172 0 : listLayer = poReader->GetLayers();
173 :
174 0 : CSLDestroy( filenames );
175 :
176 0 : return TRUE;
177 : }
178 :
179 :
180 : /************************************************************************/
181 : /* Create() */
182 : /************************************************************************/
183 :
184 0 : int OGRILI2DataSource::Create( const char *pszFilename,
185 : char **papszOptions )
186 :
187 : {
188 0 : char **filenames = CSLTokenizeString2( pszFilename, ",", 0 );
189 0 : pszName = CPLStrdup(filenames[0]);
190 0 : const char *pszModelFilename = (CSLCount(filenames)>1) ? filenames[1] : NULL;
191 :
192 0 : if( pszModelFilename == NULL )
193 : {
194 : CPLError( CE_Warning, CPLE_OpenFailed,
195 : "Model file '%s' (%s) not found : %s.",
196 0 : pszModelFilename, pszFilename, VSIStrerror( errno ) );
197 0 : CSLDestroy(filenames);
198 0 : return FALSE;
199 : }
200 :
201 0 : iom_init();
202 :
203 : // set error listener to a iom provided one, that just
204 : // dumps all errors to stderr
205 0 : iom_seterrlistener(iom_stderrlistener);
206 :
207 : // compile ili model
208 0 : char *iliFiles[1] = {(char *)pszModelFilename};
209 0 : IOM_BASKET model=iom_compileIli(1,iliFiles);
210 0 : if(!model){
211 : CPLError( CE_Warning, CPLE_OpenFailed,
212 : "iom_compileIli %s, %s.",
213 0 : pszName, VSIStrerror( errno ) );
214 0 : iom_end();
215 0 : CSLDestroy(filenames);
216 0 : return FALSE;
217 : }
218 :
219 : // open new file
220 0 : fpTransfer=iom_open(pszName,IOM_CREATE | IOM_DONTREAD,0);
221 0 : if(!fpTransfer){
222 : CPLError( CE_Warning, CPLE_OpenFailed,
223 : "Failed to open %s.",
224 0 : pszName );
225 0 : CSLDestroy(filenames);
226 0 : return FALSE;
227 : }
228 :
229 : // set model of new file
230 0 : iom_setmodel(fpTransfer,model);
231 :
232 0 : iom_setheadsender(fpTransfer, pszModelFilename);
233 :
234 0 : iom_setheadcomment(fpTransfer,"Created by OGR");
235 :
236 : // create new basket
237 : static char basketname[512];
238 0 : basketname[0] = '\0';
239 0 : const char* val = GetAttrObjName(model, "iom04.metamodel.DataModel");
240 0 : if (val)
241 : {
242 0 : strcat(basketname, val);
243 0 : strcat(basketname, ".");
244 0 : val = GetAttrObjName(model, "iom04.metamodel.Topic");
245 0 : if (val) strcat(basketname, val);
246 : }
247 : else
248 : {
249 0 : strcat(basketname, "Basket");
250 : }
251 :
252 0 : CSLDestroy(filenames);
253 :
254 0 : basket=iom_newbasket(fpTransfer);
255 0 : iom_setbaskettag(basket, basketname);
256 0 : iom_setbasketoid(basket, "0");
257 0 : return TRUE;
258 : }
259 :
260 : /************************************************************************/
261 : /* CreateLayer() */
262 : /************************************************************************/
263 :
264 : OGRLayer *
265 0 : OGRILI2DataSource::CreateLayer( const char * pszLayerName,
266 : OGRSpatialReference *poSRS,
267 : OGRwkbGeometryType eType,
268 : char ** papszOptions )
269 :
270 : {
271 0 : OGRILI2Layer *poLayer = new OGRILI2Layer(pszLayerName, poSRS, TRUE, eType, this);
272 :
273 0 : nLayers ++;
274 0 : papoLayers = (OGRILI2Layer**)CPLRealloc(papoLayers, sizeof(OGRILI2Layer*) * nLayers);
275 0 : papoLayers[nLayers-1] = poLayer;
276 :
277 0 : return poLayer;
278 : }
279 :
280 : /************************************************************************/
281 : /* TestCapability() */
282 : /************************************************************************/
283 :
284 0 : int OGRILI2DataSource::TestCapability( const char * pszCap )
285 :
286 : {
287 0 : if( EQUAL(pszCap,ODsCCreateLayer) )
288 0 : return TRUE;
289 : else
290 0 : return FALSE;
291 : }
292 :
293 : /************************************************************************/
294 : /* GetLayer() */
295 : /************************************************************************/
296 :
297 0 : OGRLayer *OGRILI2DataSource::GetLayer( int iLayer )
298 :
299 : {
300 0 : list<OGRLayer *>::const_iterator layerIt = listLayer.begin();
301 0 : int i = 0;
302 0 : while (i < iLayer && layerIt != listLayer.end()) {
303 0 : i++;
304 0 : layerIt++;
305 : }
306 :
307 0 : if (i == iLayer) {
308 0 : OGRILI2Layer *tmpLayer = (OGRILI2Layer *)*layerIt;
309 0 : return tmpLayer;
310 : } else
311 0 : return NULL;
312 : }
|