1 : /******************************************************************************
2 : * $Id: ogrili1datasource.cpp 15268 2008-08-31 19:03:09Z pka $
3 : *
4 : * Project: Interlis 1 Translator
5 : * Purpose: Implements OGRILI1DataSource class.
6 : * Author: Pirmin Kalberer, 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_ili1.h"
31 : #include "cpl_conv.h"
32 : #include "cpl_string.h"
33 :
34 : #include "ili1reader.h"
35 :
36 : #include "iomhelper.h"
37 : #include "iom/iom.h"
38 :
39 : #include <string>
40 :
41 : CPL_CVSID("$Id: ogrili1datasource.cpp 15268 2008-08-31 19:03:09Z pka $");
42 :
43 : /************************************************************************/
44 : /* OGRILI1DataSource() */
45 : /************************************************************************/
46 :
47 174 : OGRILI1DataSource::OGRILI1DataSource()
48 :
49 : {
50 174 : pszName = NULL;
51 174 : poReader = NULL;
52 174 : fpTransfer = NULL;
53 174 : pszTopic = NULL;
54 174 : nLayers = 0;
55 174 : papoLayers = NULL;
56 174 : }
57 :
58 : /************************************************************************/
59 : /* ~OGRILI1DataSource() */
60 : /************************************************************************/
61 :
62 174 : OGRILI1DataSource::~OGRILI1DataSource()
63 :
64 : {
65 : int i;
66 :
67 174 : for(i=0;i<nLayers;i++)
68 : {
69 0 : delete papoLayers[i];
70 : }
71 174 : CPLFree( papoLayers );
72 :
73 174 : CPLFree( pszName );
74 174 : CPLFree( pszTopic );
75 174 : DestroyILI1Reader( poReader );
76 174 : if( fpTransfer )
77 : {
78 0 : VSIFPrintf( fpTransfer, "ETAB\n" );
79 0 : VSIFPrintf( fpTransfer, "ETOP\n" );
80 0 : VSIFPrintf( fpTransfer, "EMOD\n" );
81 0 : VSIFPrintf( fpTransfer, "ENDE\n" );
82 0 : fclose(fpTransfer);
83 : }
84 174 : }
85 :
86 : /************************************************************************/
87 : /* Open() */
88 : /************************************************************************/
89 :
90 174 : int OGRILI1DataSource::Open( const char * pszNewName, int bTestOpen )
91 :
92 : {
93 : FILE *fp;
94 : char szHeader[1000];
95 174 : std::string osBasename, osModelFilename;
96 :
97 174 : if (strlen(pszNewName) == 0)
98 : {
99 1 : return FALSE;
100 : }
101 :
102 173 : char **filenames = CSLTokenizeString2( pszNewName, ",", 0 );
103 :
104 173 : osBasename = filenames[0];
105 :
106 173 : if( CSLCount(filenames) > 1 )
107 0 : osModelFilename = filenames[1];
108 :
109 173 : CSLDestroy( filenames );
110 :
111 : /* -------------------------------------------------------------------- */
112 : /* Open the source file. */
113 : /* -------------------------------------------------------------------- */
114 173 : fp = VSIFOpen( osBasename.c_str(), "r" );
115 173 : if( fp == NULL )
116 : {
117 64 : if( !bTestOpen )
118 : CPLError( CE_Failure, CPLE_OpenFailed,
119 : "Failed to open ILI1 file `%s'.",
120 0 : pszNewName );
121 :
122 64 : return FALSE;
123 : }
124 :
125 : /* -------------------------------------------------------------------- */
126 : /* If we aren't sure it is ILI1, load a header chunk and check */
127 : /* for signs it is ILI1 */
128 : /* -------------------------------------------------------------------- */
129 109 : if( bTestOpen )
130 : {
131 109 : int nLen = (int)VSIFRead( szHeader, 1, sizeof(szHeader), fp );
132 109 : if (nLen == sizeof(szHeader))
133 71 : szHeader[sizeof(szHeader)-1] = '\0';
134 : else
135 38 : szHeader[nLen] = '\0';
136 :
137 109 : if( strstr(szHeader,"SCNT") == NULL )
138 : {
139 109 : VSIFClose( fp );
140 109 : return FALSE;
141 : }
142 : }
143 :
144 : /* -------------------------------------------------------------------- */
145 : /* We assume now that it is ILI1. Close and instantiate a */
146 : /* ILI1Reader on it. */
147 : /* -------------------------------------------------------------------- */
148 0 : VSIFClose( fp );
149 :
150 0 : poReader = CreateILI1Reader();
151 0 : if( poReader == NULL )
152 : {
153 : CPLError( CE_Failure, CPLE_AppDefined,
154 : "File %s appears to be ILI1 but the ILI1 reader can't\n"
155 : "be instantiated, likely because Xerces support wasn't\n"
156 : "configured in.",
157 0 : pszNewName );
158 0 : return FALSE;
159 : }
160 :
161 0 : poReader->OpenFile( osBasename.c_str() );
162 :
163 0 : pszName = CPLStrdup( osBasename.c_str() );
164 :
165 0 : if (osModelFilename.length() > 0 )
166 0 : poReader->ReadModel( osModelFilename.c_str() );
167 :
168 0 : if( getenv( "ARC_DEGREES" ) != NULL ) {
169 : //No better way to pass arguments to the reader (it could even be an -lco arg)
170 0 : poReader->SetArcDegrees( atof( getenv("ARC_DEGREES") ) );
171 : }
172 :
173 : //Parse model and read data - without surface joing and polygonizing
174 0 : poReader->ReadFeatures();
175 :
176 0 : return TRUE;
177 : }
178 :
179 : /************************************************************************/
180 : /* Create() */
181 : /************************************************************************/
182 :
183 0 : int OGRILI1DataSource::Create( const char *pszFilename,
184 : char **papszOptions )
185 :
186 : {
187 0 : std::string osBasename, osModelFilename;
188 0 : char **filenames = CSLTokenizeString2( pszFilename, ",", 0 );
189 :
190 0 : osBasename = filenames[0];
191 :
192 0 : if( CSLCount(filenames) > 1 )
193 0 : osModelFilename = filenames[1];
194 :
195 0 : CSLDestroy( filenames );
196 :
197 0 : if( osModelFilename.length() == 0 )
198 : {
199 : //TODO: create automatic model
200 : }
201 :
202 : /* -------------------------------------------------------------------- */
203 : /* Create the empty file. */
204 : /* -------------------------------------------------------------------- */
205 0 : fpTransfer = VSIFOpen( osBasename.c_str(), "w+b" );
206 :
207 0 : if( fpTransfer == NULL )
208 : {
209 : CPLError( CE_Failure, CPLE_OpenFailed,
210 : "Failed to create %s:\n%s",
211 0 : osBasename.c_str(), VSIStrerror( errno ) );
212 :
213 0 : return FALSE;
214 : }
215 :
216 :
217 : /* -------------------------------------------------------------------- */
218 : /* Parse model */
219 : /* -------------------------------------------------------------------- */
220 0 : iom_init();
221 :
222 : // set error listener to a iom provided one, that just
223 : // dumps all errors to stderr
224 0 : iom_seterrlistener(iom_stderrlistener);
225 :
226 0 : IOM_BASKET model = 0;
227 0 : if( osModelFilename.length() != 0 ) {
228 : // compile ili model
229 0 : char *iliFiles[1] = {(char *)osModelFilename.c_str()};
230 0 : model=iom_compileIli(1,iliFiles);
231 0 : if(!model){
232 : CPLError( CE_Warning, CPLE_OpenFailed,
233 : "iom_compileIli %s, %s.",
234 0 : pszName, VSIStrerror( errno ) );
235 0 : iom_end();
236 0 : return FALSE;
237 : }
238 : }
239 :
240 : /* -------------------------------------------------------------------- */
241 : /* Write headers */
242 : /* -------------------------------------------------------------------- */
243 0 : VSIFPrintf( fpTransfer, "SCNT\n" );
244 0 : VSIFPrintf( fpTransfer, "OGR/GDAL %s, INTERLIS Driver\n", GDAL_RELEASE_NAME );
245 0 : VSIFPrintf( fpTransfer, "////\n" );
246 0 : VSIFPrintf( fpTransfer, "MTID INTERLIS1\n" );
247 0 : const char* modelname = model ? GetAttrObjName(model, "iom04.metamodel.DataModel") : osBasename.c_str(); //TODO: remove file extension (= table name)
248 0 : VSIFPrintf( fpTransfer, "MODL %s\n", modelname );
249 :
250 0 : return TRUE;
251 : }
252 :
253 0 : static char *ExtractTopic(const char * pszLayerName)
254 : {
255 0 : const char *table = strchr(pszLayerName, '_');
256 0 : while (table && table[1] != '_') table = strchr(table+1, '_');
257 0 : return (table) ? CPLScanString(pszLayerName, table-pszLayerName, FALSE, FALSE) : NULL;
258 : }
259 :
260 : /************************************************************************/
261 : /* CreateLayer() */
262 : /************************************************************************/
263 :
264 : OGRLayer *
265 0 : OGRILI1DataSource::CreateLayer( const char * pszLayerName,
266 : OGRSpatialReference *poSRS,
267 : OGRwkbGeometryType eType,
268 : char ** papszOptions )
269 :
270 : {
271 0 : const char *table = pszLayerName;
272 0 : char * topic = ExtractTopic(pszLayerName);
273 0 : if (pszTopic) VSIFPrintf( fpTransfer, "ETAB\n" );
274 0 : if (topic)
275 : {
276 0 : table = pszLayerName+strlen(topic)+2; //after "__"
277 0 : if (pszTopic == NULL || !EQUAL(topic, pszTopic))
278 : {
279 0 : if (pszTopic)
280 : {
281 0 : VSIFPrintf( fpTransfer, "ETOP\n" );
282 0 : CPLFree(pszTopic);
283 : }
284 0 : pszTopic = topic;
285 0 : VSIFPrintf( fpTransfer, "TOPI %s\n", pszTopic );
286 : }
287 : else
288 : {
289 0 : CPLFree(topic);
290 : }
291 : }
292 0 : else if (pszTopic == NULL)
293 : {
294 0 : pszTopic = CPLStrdup("Topic"); //TODO: From model?
295 0 : VSIFPrintf( fpTransfer, "TOPI %s\n", pszTopic );
296 : }
297 0 : VSIFPrintf( fpTransfer, "TABL %s\n", table );
298 :
299 0 : OGRILI1Layer *poLayer = new OGRILI1Layer(table, poSRS, TRUE, eType, this);
300 :
301 0 : nLayers ++;
302 0 : papoLayers = (OGRILI1Layer**)CPLRealloc(papoLayers, sizeof(OGRILI1Layer*) * nLayers);
303 0 : papoLayers[nLayers-1] = poLayer;
304 :
305 0 : return poLayer;
306 : }
307 :
308 : /************************************************************************/
309 : /* TestCapability() */
310 : /************************************************************************/
311 :
312 0 : int OGRILI1DataSource::TestCapability( const char * pszCap )
313 :
314 : {
315 0 : if( EQUAL(pszCap,ODsCCreateLayer) )
316 0 : return TRUE;
317 : else
318 0 : return FALSE;
319 : }
320 :
321 : /************************************************************************/
322 : /* GetLayer() */
323 : /************************************************************************/
324 :
325 0 : OGRLayer *OGRILI1DataSource::GetLayer( int iLayer )
326 : {
327 0 : return poReader->GetLayer( iLayer );
328 : }
|