1 : /******************************************************************************
2 : * $Id: ogrogdidatasource.cpp 16861 2009-04-26 19:22:29Z 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 16861 2009-04-26 19:22:29Z rouault $");
36 :
37 : /************************************************************************/
38 : /* OGROGDIDataSource() */
39 : /************************************************************************/
40 :
41 89 : OGROGDIDataSource::OGROGDIDataSource()
42 :
43 : {
44 89 : m_pszFullName = NULL;
45 89 : m_papoLayers = NULL;
46 89 : m_nLayers = 0;
47 89 : m_nClientID = -1;
48 89 : m_poSpatialRef = NULL;
49 89 : m_poCurrentLayer = NULL;
50 89 : }
51 :
52 : /************************************************************************/
53 : /* ~OGROGDIDataSource() */
54 : /************************************************************************/
55 :
56 178 : OGROGDIDataSource::~OGROGDIDataSource()
57 :
58 : {
59 89 : CPLFree(m_pszFullName );
60 :
61 146 : for( int i = 0; i < m_nLayers; i++ )
62 57 : delete m_papoLayers[i];
63 89 : CPLFree( m_papoLayers );
64 :
65 89 : if (m_nClientID != -1)
66 : {
67 : ecs_Result *psResult;
68 :
69 1 : psResult = cln_DestroyClient( m_nClientID );
70 1 : ecs_CleanUp( psResult );
71 : }
72 :
73 89 : if (m_poSpatialRef)
74 1 : m_poSpatialRef->Release();
75 178 : }
76 :
77 : /************************************************************************/
78 : /* Open() */
79 : /************************************************************************/
80 :
81 89 : int OGROGDIDataSource::Open( const char * pszNewName, int bTestOpen )
82 :
83 : {
84 : ecs_Result *psResult;
85 89 : char *pszFamily=NULL, *pszLyrName=NULL;
86 : char *pszWorkingName;
87 :
88 : CPLAssert( m_nLayers == 0 );
89 :
90 : /* -------------------------------------------------------------------- */
91 : /* Parse the dataset name. */
92 : /* i.e. */
93 : /* gltp://<hostname>/<format>/<path_to_dataset>[:<layer_name>:<Family>] */
94 : /* */
95 : /* Where <Family> is one of: Line, Area, Point, and Text */
96 : /* -------------------------------------------------------------------- */
97 89 : if( !EQUALN(pszNewName,"gltp:",5) )
98 88 : return FALSE;
99 :
100 1 : pszWorkingName = CPLStrdup( pszNewName );
101 :
102 1 : pszFamily = strrchr(pszWorkingName, ':');
103 :
104 : // Don't treat drive name colon as family separator. It is assumed
105 : // that drive names are on character long, and preceeded by a
106 : // forward or backward slash.
107 3 : if( pszFamily < pszWorkingName+2
108 1 : || pszFamily[-2] == '/'
109 1 : || pszFamily[-2] == '\\' )
110 0 : pszFamily = NULL;
111 :
112 1 : if (pszFamily && pszFamily != pszWorkingName + 4)
113 : {
114 0 : *pszFamily = '\0';
115 0 : pszFamily++;
116 :
117 0 : pszLyrName = strrchr(pszWorkingName, ':');
118 0 : if (pszLyrName == pszWorkingName + 4)
119 0 : pszLyrName = NULL;
120 :
121 0 : if( pszLyrName != NULL )
122 : {
123 0 : *pszLyrName = '\0';
124 0 : pszLyrName++;
125 : }
126 : }
127 :
128 : /* -------------------------------------------------------------------- */
129 : /* Open the client interface. */
130 : /* -------------------------------------------------------------------- */
131 1 : psResult = cln_CreateClient(&m_nClientID, pszWorkingName);
132 1 : CPLFree( pszWorkingName );
133 :
134 1 : if( ECSERROR( psResult ) )
135 : {
136 0 : if (!bTestOpen)
137 : {
138 : CPLError( CE_Failure, CPLE_AppDefined,
139 : "OGDI DataSource Open Failed: %s\n",
140 0 : psResult->message );
141 : }
142 0 : return FALSE;
143 : }
144 :
145 1 : m_pszFullName = CPLStrdup(pszNewName);
146 :
147 : /* -------------------------------------------------------------------- */
148 : /* Capture some information from the file. */
149 : /* -------------------------------------------------------------------- */
150 1 : psResult = cln_GetGlobalBound( m_nClientID );
151 1 : if( ECSERROR(psResult) )
152 : {
153 : CPLError( CE_Failure, CPLE_AppDefined,
154 0 : "%s", psResult->message );
155 0 : return FALSE;
156 : }
157 :
158 1 : m_sGlobalBounds = ECSREGION(psResult);
159 :
160 1 : psResult = cln_GetServerProjection(m_nClientID);
161 1 : if( ECSERROR(psResult) )
162 : {
163 : CPLError( CE_Failure, CPLE_AppDefined,
164 0 : "%s", psResult->message );
165 0 : return FALSE;
166 : }
167 :
168 1 : m_poSpatialRef = new OGRSpatialReference;
169 :
170 1 : if( m_poSpatialRef->importFromProj4( ECSTEXT(psResult) ) != OGRERR_NONE )
171 : {
172 : CPLError( CE_Warning, CPLE_NotSupported,
173 : "untranslatable PROJ.4 projection: %s\n",
174 0 : ECSTEXT(psResult) );
175 0 : delete m_poSpatialRef;
176 0 : m_poSpatialRef = NULL;
177 : }
178 :
179 : /* -------------------------------------------------------------------- */
180 : /* Select the global region. */
181 : /* -------------------------------------------------------------------- */
182 1 : psResult = cln_SelectRegion( m_nClientID, &m_sGlobalBounds );
183 1 : if( ECSERROR(psResult) )
184 : {
185 : CPLError( CE_Failure, CPLE_AppDefined,
186 0 : "%s", psResult->message );
187 0 : return FALSE;
188 : }
189 :
190 : /* -------------------------------------------------------------------- */
191 : /* If an explicit layer was selected, just create that layer. */
192 : /* -------------------------------------------------------------------- */
193 1 : m_poCurrentLayer = NULL;
194 :
195 1 : if( pszLyrName != NULL )
196 : {
197 : ecs_Family eFamily;
198 :
199 0 : if (EQUAL(pszFamily, "Line"))
200 0 : eFamily = Line;
201 0 : else if (EQUAL(pszFamily, "Area"))
202 0 : eFamily = Area;
203 0 : else if (EQUAL(pszFamily, "Point"))
204 0 : eFamily = Point;
205 0 : else if (EQUAL(pszFamily, "Text"))
206 0 : eFamily = Text;
207 : else
208 : {
209 0 : if (!bTestOpen)
210 : {
211 : CPLError( CE_Failure, CPLE_AppDefined,
212 : "Invalid or unsupported family name (%s) in URL %s\n",
213 0 : pszFamily, m_pszFullName);
214 : }
215 0 : return FALSE;
216 : }
217 :
218 0 : IAddLayer( pszLyrName, eFamily );
219 : }
220 :
221 : /* -------------------------------------------------------------------- */
222 : /* Otherwise create a layer for every layer in the capabilities. */
223 : /* -------------------------------------------------------------------- */
224 : else
225 : {
226 : int i;
227 : const ecs_LayerCapabilities *psLayerCap;
228 :
229 58 : for( i = 0;
230 : (psLayerCap = cln_GetLayerCapabilities(m_nClientID,i)) != NULL;
231 : i++ )
232 : {
233 57 : if( psLayerCap->families[Point] )
234 13 : IAddLayer( psLayerCap->name, Point );
235 57 : if( psLayerCap->families[Line] )
236 16 : IAddLayer( psLayerCap->name, Line );
237 57 : if( psLayerCap->families[Area] )
238 20 : IAddLayer( psLayerCap->name, Area );
239 57 : if( psLayerCap->families[Text] )
240 8 : IAddLayer( psLayerCap->name, Text );
241 : }
242 : }
243 :
244 1 : return TRUE;
245 : }
246 :
247 : /************************************************************************/
248 : /* IAddLayer() */
249 : /* */
250 : /* Internal helper function for adding one existing layer to */
251 : /* the datasource. */
252 : /************************************************************************/
253 :
254 57 : void OGROGDIDataSource::IAddLayer( const char *pszLayerName,
255 : ecs_Family eFamily )
256 :
257 : {
258 : m_papoLayers = (OGROGDILayer**)
259 57 : CPLRealloc( m_papoLayers, (m_nLayers+1) * sizeof(OGROGDILayer*));
260 :
261 57 : m_papoLayers[m_nLayers++] = new OGROGDILayer(this, pszLayerName, eFamily);
262 57 : }
263 :
264 : /************************************************************************/
265 : /* TestCapability() */
266 : /************************************************************************/
267 :
268 0 : int OGROGDIDataSource::TestCapability( const char * pszCap )
269 :
270 : {
271 0 : return FALSE;
272 : }
273 :
274 : /************************************************************************/
275 : /* GetLayer() */
276 : /************************************************************************/
277 :
278 16 : OGRLayer *OGROGDIDataSource::GetLayer( int iLayer )
279 :
280 : {
281 16 : if( iLayer < 0 || iLayer >= m_nLayers )
282 0 : return NULL;
283 : else
284 16 : return m_papoLayers[iLayer];
285 : }
|