1 : /******************************************************************************
2 : * $Id: ogrogdidatasource.cpp 19711 2010-05-14 21:26:42Z rouault $
3 : *
4 : * Project: OGDI Bridge
5 : * Purpose: Implements OGROGDIDataSource class.
6 : * Author: Daniel Morissette, danmo@videotron.ca
7 : * (Based on some code contributed by Frank Warmerdam :)
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 2000, Daniel Morissette
11 : *
12 : * Permission is hereby granted, free of charge, to any person obtaining a
13 : * copy of this software and associated documentation files (the "Software"),
14 : * to deal in the Software without restriction, including without limitation
15 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 : * and/or sell copies of the Software, and to permit persons to whom the
17 : * Software is furnished to do so, subject to the following conditions:
18 : *
19 : * The above copyright notice and this permission notice shall be included
20 : * in all copies or substantial portions of the Software.
21 : *
22 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 : * DEALINGS IN THE SOFTWARE.
29 : ****************************************************************************/
30 :
31 : #include "ogrogdi.h"
32 : #include "cpl_conv.h"
33 : #include "cpl_string.h"
34 :
35 : CPL_CVSID("$Id: ogrogdidatasource.cpp 19711 2010-05-14 21:26:42Z rouault $");
36 :
37 : /************************************************************************/
38 : /* OGROGDIDataSource() */
39 : /************************************************************************/
40 :
41 586 : OGROGDIDataSource::OGROGDIDataSource()
42 :
43 : {
44 586 : m_pszFullName = NULL;
45 586 : m_papoLayers = NULL;
46 586 : m_nLayers = 0;
47 586 : m_nClientID = -1;
48 586 : m_poSpatialRef = NULL;
49 586 : m_poCurrentLayer = NULL;
50 : m_bLaunderLayerNames =
51 586 : CSLTestBoolean(CPLGetConfigOption("OGR_OGDI_LAUNDER_LAYER_NAMES", "NO"));
52 586 : }
53 :
54 : /************************************************************************/
55 : /* ~OGROGDIDataSource() */
56 : /************************************************************************/
57 :
58 586 : OGROGDIDataSource::~OGROGDIDataSource()
59 :
60 : {
61 586 : CPLFree(m_pszFullName );
62 :
63 1156 : for( int i = 0; i < m_nLayers; i++ )
64 570 : delete m_papoLayers[i];
65 586 : CPLFree( m_papoLayers );
66 :
67 586 : if (m_nClientID != -1)
68 : {
69 : ecs_Result *psResult;
70 :
71 10 : psResult = cln_DestroyClient( m_nClientID );
72 10 : ecs_CleanUp( psResult );
73 : }
74 :
75 586 : if (m_poSpatialRef)
76 10 : m_poSpatialRef->Release();
77 586 : }
78 :
79 : /************************************************************************/
80 : /* Open() */
81 : /************************************************************************/
82 :
83 586 : int OGROGDIDataSource::Open( const char * pszNewName, int bTestOpen )
84 :
85 : {
86 : ecs_Result *psResult;
87 586 : char *pszFamily=NULL, *pszLyrName=NULL;
88 : char *pszWorkingName;
89 :
90 586 : CPLAssert( m_nLayers == 0 );
91 :
92 : /* -------------------------------------------------------------------- */
93 : /* Parse the dataset name. */
94 : /* i.e. */
95 : /* gltp://<hostname>/<format>/<path_to_dataset>[:<layer_name>:<Family>] */
96 : /* */
97 : /* Where <Family> is one of: Line, Area, Point, and Text */
98 : /* -------------------------------------------------------------------- */
99 586 : if( !EQUALN(pszNewName,"gltp:",5) )
100 576 : return FALSE;
101 :
102 10 : pszWorkingName = CPLStrdup( pszNewName );
103 :
104 10 : pszFamily = strrchr(pszWorkingName, ':');
105 :
106 : // Don't treat drive name colon as family separator. It is assumed
107 : // that drive names are on character long, and preceeded by a
108 : // forward or backward slash.
109 30 : if( pszFamily < pszWorkingName+2
110 10 : || pszFamily[-2] == '/'
111 10 : || pszFamily[-2] == '\\' )
112 0 : pszFamily = NULL;
113 :
114 10 : if (pszFamily && pszFamily != pszWorkingName + 4)
115 : {
116 0 : *pszFamily = '\0';
117 0 : pszFamily++;
118 :
119 0 : pszLyrName = strrchr(pszWorkingName, ':');
120 0 : if (pszLyrName == pszWorkingName + 4)
121 0 : pszLyrName = NULL;
122 :
123 0 : if( pszLyrName != NULL )
124 : {
125 0 : *pszLyrName = '\0';
126 0 : pszLyrName++;
127 : }
128 : }
129 :
130 : /* -------------------------------------------------------------------- */
131 : /* Open the client interface. */
132 : /* -------------------------------------------------------------------- */
133 10 : psResult = cln_CreateClient(&m_nClientID, pszWorkingName);
134 10 : CPLFree( pszWorkingName );
135 :
136 10 : if( ECSERROR( psResult ) )
137 : {
138 0 : if (!bTestOpen)
139 : {
140 : CPLError( CE_Failure, CPLE_AppDefined,
141 : "OGDI DataSource Open Failed: %s\n",
142 0 : psResult->message );
143 : }
144 0 : return FALSE;
145 : }
146 :
147 10 : m_pszFullName = CPLStrdup(pszNewName);
148 :
149 : /* -------------------------------------------------------------------- */
150 : /* Capture some information from the file. */
151 : /* -------------------------------------------------------------------- */
152 10 : psResult = cln_GetGlobalBound( m_nClientID );
153 10 : if( ECSERROR(psResult) )
154 : {
155 : CPLError( CE_Failure, CPLE_AppDefined,
156 0 : "%s", psResult->message );
157 0 : return FALSE;
158 : }
159 :
160 10 : m_sGlobalBounds = ECSREGION(psResult);
161 :
162 10 : psResult = cln_GetServerProjection(m_nClientID);
163 10 : if( ECSERROR(psResult) )
164 : {
165 : CPLError( CE_Failure, CPLE_AppDefined,
166 0 : "%s", psResult->message );
167 0 : return FALSE;
168 : }
169 :
170 10 : m_poSpatialRef = new OGRSpatialReference;
171 :
172 10 : if( m_poSpatialRef->importFromProj4( ECSTEXT(psResult) ) != OGRERR_NONE )
173 : {
174 : CPLError( CE_Warning, CPLE_NotSupported,
175 : "untranslatable PROJ.4 projection: %s\n",
176 0 : ECSTEXT(psResult) );
177 0 : delete m_poSpatialRef;
178 0 : m_poSpatialRef = NULL;
179 : }
180 :
181 : /* -------------------------------------------------------------------- */
182 : /* Select the global region. */
183 : /* -------------------------------------------------------------------- */
184 10 : psResult = cln_SelectRegion( m_nClientID, &m_sGlobalBounds );
185 10 : if( ECSERROR(psResult) )
186 : {
187 : CPLError( CE_Failure, CPLE_AppDefined,
188 0 : "%s", psResult->message );
189 0 : return FALSE;
190 : }
191 :
192 : /* -------------------------------------------------------------------- */
193 : /* If an explicit layer was selected, just create that layer. */
194 : /* -------------------------------------------------------------------- */
195 10 : m_poCurrentLayer = NULL;
196 :
197 10 : if( pszLyrName != NULL )
198 : {
199 : ecs_Family eFamily;
200 :
201 0 : if (EQUAL(pszFamily, "Line"))
202 0 : eFamily = Line;
203 0 : else if (EQUAL(pszFamily, "Area"))
204 0 : eFamily = Area;
205 0 : else if (EQUAL(pszFamily, "Point"))
206 0 : eFamily = Point;
207 0 : else if (EQUAL(pszFamily, "Text"))
208 0 : eFamily = Text;
209 : else
210 : {
211 0 : if (!bTestOpen)
212 : {
213 : CPLError( CE_Failure, CPLE_AppDefined,
214 : "Invalid or unsupported family name (%s) in URL %s\n",
215 0 : pszFamily, m_pszFullName);
216 : }
217 0 : return FALSE;
218 : }
219 :
220 0 : IAddLayer( pszLyrName, eFamily );
221 : }
222 :
223 : /* -------------------------------------------------------------------- */
224 : /* Otherwise create a layer for every layer in the capabilities. */
225 : /* -------------------------------------------------------------------- */
226 : else
227 : {
228 : int i;
229 : const ecs_LayerCapabilities *psLayerCap;
230 :
231 580 : for( i = 0;
232 : (psLayerCap = cln_GetLayerCapabilities(m_nClientID,i)) != NULL;
233 : i++ )
234 : {
235 570 : if( psLayerCap->families[Point] )
236 130 : IAddLayer( psLayerCap->name, Point );
237 570 : if( psLayerCap->families[Line] )
238 160 : IAddLayer( psLayerCap->name, Line );
239 570 : if( psLayerCap->families[Area] )
240 200 : IAddLayer( psLayerCap->name, Area );
241 570 : if( psLayerCap->families[Text] )
242 80 : IAddLayer( psLayerCap->name, Text );
243 : }
244 : }
245 :
246 10 : return TRUE;
247 : }
248 :
249 : /************************************************************************/
250 : /* IAddLayer() */
251 : /* */
252 : /* Internal helper function for adding one existing layer to */
253 : /* the datasource. */
254 : /************************************************************************/
255 :
256 570 : void OGROGDIDataSource::IAddLayer( const char *pszLayerName,
257 : ecs_Family eFamily )
258 :
259 : {
260 : m_papoLayers = (OGROGDILayer**)
261 570 : CPLRealloc( m_papoLayers, (m_nLayers+1) * sizeof(OGROGDILayer*));
262 :
263 570 : m_papoLayers[m_nLayers++] = new OGROGDILayer(this, pszLayerName, eFamily);
264 570 : }
265 :
266 : /************************************************************************/
267 : /* TestCapability() */
268 : /************************************************************************/
269 :
270 2 : int OGROGDIDataSource::TestCapability( const char * pszCap )
271 :
272 : {
273 2 : return FALSE;
274 : }
275 :
276 : /************************************************************************/
277 : /* GetLayer() */
278 : /************************************************************************/
279 :
280 712 : OGRLayer *OGROGDIDataSource::GetLayer( int iLayer )
281 :
282 : {
283 712 : if( iLayer < 0 || iLayer >= m_nLayers )
284 4 : return NULL;
285 : else
286 708 : return m_papoLayers[iLayer];
287 : }
|