1 : /******************************************************************************
2 : * $Id: ogrvfkdatasource.cpp 25340 2012-12-21 20:30:21Z rouault $
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Purpose: Implements OGRVFKDatasource class.
6 : * Author: Martin Landa, landa.martin gmail.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2009-2010, Martin Landa <landa.martin gmail.com>
10 : *
11 : * Permission is hereby granted, free of charge, to any person
12 : * obtaining a copy of this software and associated documentation
13 : * files (the "Software"), to deal in the Software without
14 : * restriction, including without limitation the rights to use, copy,
15 : * modify, merge, publish, distribute, sublicense, and/or sell copies
16 : * of the Software, and to permit persons to whom the Software is
17 : * furnished to do so, subject to the following conditions:
18 : *
19 : * The above copyright notice and this permission notice shall be
20 : * included in all copies or substantial portions of the Software.
21 : *
22 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 : * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 : * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 : * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
26 : * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
27 : * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
28 : * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 : * SOFTWARE.
30 : ****************************************************************************/
31 :
32 : #include "ogr_vfk.h"
33 : #include "cpl_conv.h"
34 : #include "cpl_string.h"
35 :
36 : CPL_CVSID("$Id: ogrvfkdatasource.cpp 25340 2012-12-21 20:30:21Z rouault $");
37 :
38 : /*!
39 : \brief OGRVFKDataSource constructor
40 : */
41 136 : OGRVFKDataSource::OGRVFKDataSource()
42 : {
43 136 : pszName = NULL;
44 :
45 136 : poReader = NULL;
46 :
47 136 : papoLayers = NULL;
48 136 : nLayers = 0;
49 136 : }
50 :
51 : /*!
52 : \brief OGRVFKDataSource destructor
53 : */
54 136 : OGRVFKDataSource::~OGRVFKDataSource()
55 : {
56 136 : CPLFree(pszName);
57 :
58 136 : if (poReader)
59 2 : delete poReader;
60 :
61 258 : for(int i = 0; i < nLayers; i++)
62 122 : delete papoLayers[i];
63 :
64 136 : CPLFree(papoLayers);
65 136 : }
66 :
67 : /*!
68 : \brief Open VFK datasource
69 :
70 : \param pszNewName datasource name
71 : \param bTestOpen True to test if datasource is possible to open
72 :
73 : \return TRUE on success or FALSE on failure
74 : */
75 136 : int OGRVFKDataSource::Open(const char *pszNewName, int bTestOpen)
76 : {
77 : FILE * fp;
78 : char szHeader[1000];
79 :
80 : /* open the source file */
81 136 : fp = VSIFOpen(pszNewName, "r");
82 136 : if (fp == NULL) {
83 52 : if (!bTestOpen)
84 : CPLError(CE_Failure, CPLE_OpenFailed,
85 : "Failed to open VFK file `%s'.",
86 0 : pszNewName);
87 :
88 52 : return FALSE;
89 : }
90 :
91 : /* If we aren't sure it is VFK, load a header chunk and check
92 : for signs it is VFK */
93 84 : if (bTestOpen) {
94 84 : size_t nRead = VSIFRead(szHeader, 1, sizeof(szHeader), fp);
95 84 : if (nRead <= 0) {
96 0 : VSIFClose(fp);
97 0 : return FALSE;
98 : }
99 84 : szHeader[MIN(nRead, sizeof(szHeader))-1] = '\0';
100 :
101 : // TODO: improve check
102 84 : if (strncmp(szHeader, "&HVERZE;", 8) != 0) {
103 82 : VSIFClose(fp);
104 82 : return FALSE;
105 : }
106 : }
107 :
108 : /* We assume now that it is VFK. Close and instantiate a
109 : VFKReader on it. */
110 2 : VSIFClose(fp);
111 :
112 2 : pszName = CPLStrdup(pszNewName);
113 :
114 2 : poReader = CreateVFKReader(pszNewName);
115 2 : if (poReader == NULL) {
116 : CPLError(CE_Failure, CPLE_AppDefined,
117 : "File %s appears to be VFK but the VFK reader can't"
118 : "be instantiated.",
119 0 : pszNewName);
120 0 : return FALSE;
121 : }
122 :
123 : #ifndef HAVE_SQLITE
124 : CPLError(CE_Warning, CPLE_AppDefined,
125 : "OGR is not compiled with SQLite support. "
126 : "VFK driver will not work properly.");
127 : #endif
128 :
129 : /* read data blocks, i.e. &B */
130 2 : poReader->ReadDataBlocks();
131 :
132 : /* get list of layers */
133 2 : papoLayers = (OGRVFKLayer **) CPLCalloc(sizeof(OGRVFKLayer *), poReader->GetDataBlockCount());
134 :
135 124 : for (int iLayer = 0; iLayer < poReader->GetDataBlockCount(); iLayer++) {
136 122 : papoLayers[iLayer] = CreateLayerFromBlock(poReader->GetDataBlock(iLayer));
137 122 : nLayers++;
138 : }
139 :
140 2 : return TRUE;
141 : }
142 :
143 : /*!
144 : \brief Get VFK layer
145 :
146 : \param iLayer layer number
147 :
148 : \return pointer to OGRLayer instance or NULL on error
149 : */
150 97 : OGRLayer *OGRVFKDataSource::GetLayer(int iLayer)
151 : {
152 97 : if( iLayer < 0 || iLayer >= nLayers )
153 0 : return NULL;
154 :
155 97 : return papoLayers[iLayer];
156 : }
157 :
158 : /*!
159 : \brief Test datasource capabilies
160 :
161 : \param pszCap capability
162 :
163 : \return TRUE if supported or FALSE if not supported
164 : */
165 0 : int OGRVFKDataSource::TestCapability(const char * pszCap)
166 : {
167 0 : return FALSE;
168 : }
169 :
170 : /*!
171 : \brief Create OGR layer from VFKDataBlock
172 :
173 : \param poDataBlock pointer to VFKDataBlock instance
174 :
175 : \return pointer to OGRVFKLayer instance or NULL on error
176 : */
177 122 : OGRVFKLayer *OGRVFKDataSource::CreateLayerFromBlock(const IVFKDataBlock *poDataBlock)
178 : {
179 : OGRVFKLayer *poLayer;
180 :
181 122 : poLayer = NULL;
182 :
183 : /* create an empty layer */
184 : poLayer = new OGRVFKLayer(poDataBlock->GetName(), NULL,
185 122 : poDataBlock->GetGeometryType(), this);
186 :
187 : /* define attributes (properties) */
188 1272 : for (int iField = 0; iField < poDataBlock->GetPropertyCount(); iField++) {
189 1150 : VFKPropertyDefn *poProperty = poDataBlock->GetProperty(iField);
190 1150 : OGRFieldDefn oField(poProperty->GetName(), poProperty->GetType());
191 :
192 1150 : if(poProperty->GetWidth() > 0)
193 1150 : oField.SetWidth(poProperty->GetWidth());
194 1150 : if(poProperty->GetPrecision() > 0)
195 60 : oField.SetPrecision(poProperty->GetPrecision());
196 :
197 1150 : poLayer->GetLayerDefn()->AddFieldDefn(&oField);
198 : }
199 :
200 122 : return poLayer;
201 : }
|