/src/gdal/ogr/ogrsf_frmts/jml/ogrjmldataset.cpp
Line | Count | Source |
1 | | /****************************************************************************** |
2 | | * |
3 | | * Project: JML Translator |
4 | | * Purpose: Implements OGRJMLDataset class |
5 | | * Author: Even Rouault, even dot rouault at spatialys dot com |
6 | | * |
7 | | ****************************************************************************** |
8 | | * Copyright (c) 2014, Even Rouault <even dot rouault at spatialys dot com> |
9 | | * |
10 | | * SPDX-License-Identifier: MIT |
11 | | ****************************************************************************/ |
12 | | |
13 | | #include "cpl_conv.h" |
14 | | #include "cpl_string.h" |
15 | | #include "ogr_jml.h" |
16 | | #include "ogrsf_frmts.h" |
17 | | |
18 | | // g++ -DHAVE_EXPAT -fPIC -shared -Wall -g -DDEBUG ogr/ogrsf_frmts/jml/*.cpp -o |
19 | | // ogr_JML.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/jml -L. |
20 | | // -lgdal |
21 | | |
22 | | /************************************************************************/ |
23 | | /* OGRJMLDataset() */ |
24 | | /************************************************************************/ |
25 | | |
26 | | OGRJMLDataset::OGRJMLDataset() |
27 | 1.09k | : poLayer(nullptr), fp(nullptr), bWriteMode(false) |
28 | 1.09k | { |
29 | 1.09k | } |
30 | | |
31 | | /************************************************************************/ |
32 | | /* ~OGRJMLDataset() */ |
33 | | /************************************************************************/ |
34 | | |
35 | | OGRJMLDataset::~OGRJMLDataset() |
36 | | |
37 | 1.09k | { |
38 | 1.09k | delete poLayer; |
39 | | |
40 | 1.09k | if (fp != nullptr) |
41 | 1.09k | VSIFCloseL(fp); |
42 | 1.09k | } |
43 | | |
44 | | /************************************************************************/ |
45 | | /* TestCapability() */ |
46 | | /************************************************************************/ |
47 | | |
48 | | int OGRJMLDataset::TestCapability(const char *pszCap) const |
49 | | |
50 | 168 | { |
51 | 168 | if (EQUAL(pszCap, ODsCCreateLayer)) |
52 | 56 | return bWriteMode && poLayer == nullptr; |
53 | 112 | if (EQUAL(pszCap, ODsCZGeometries)) |
54 | 0 | return true; |
55 | | |
56 | 112 | return false; |
57 | 112 | } |
58 | | |
59 | | /************************************************************************/ |
60 | | /* GetLayer() */ |
61 | | /************************************************************************/ |
62 | | |
63 | | const OGRLayer *OGRJMLDataset::GetLayer(int iLayer) const |
64 | | |
65 | 1.56k | { |
66 | 1.56k | if (iLayer != 0) |
67 | 0 | return nullptr; |
68 | | |
69 | 1.56k | return poLayer; |
70 | 1.56k | } |
71 | | |
72 | | /************************************************************************/ |
73 | | /* Identify() */ |
74 | | /************************************************************************/ |
75 | | |
76 | | int OGRJMLDataset::Identify(GDALOpenInfo *poOpenInfo) |
77 | 77.1k | { |
78 | 77.1k | return poOpenInfo->nHeaderBytes != 0 && |
79 | 44.5k | strstr(reinterpret_cast<char *>(poOpenInfo->pabyHeader), |
80 | 44.5k | "<JCSDataFile") != nullptr; |
81 | 77.1k | } |
82 | | |
83 | | /************************************************************************/ |
84 | | /* Open() */ |
85 | | /************************************************************************/ |
86 | | |
87 | | GDALDataset *OGRJMLDataset::Open(GDALOpenInfo *poOpenInfo) |
88 | | |
89 | 1.03k | { |
90 | 1.03k | if (!Identify(poOpenInfo) || poOpenInfo->fpL == nullptr || |
91 | 1.03k | poOpenInfo->eAccess == GA_Update) |
92 | 0 | return nullptr; |
93 | | |
94 | | #ifndef HAVE_EXPAT |
95 | | CPLError(CE_Failure, CPLE_NotSupported, |
96 | | "OGR/JML driver has not been built with read support. " |
97 | | "Expat library required"); |
98 | | return nullptr; |
99 | | #else |
100 | 1.03k | OGRJMLDataset *poDS = new OGRJMLDataset(); |
101 | 1.03k | poDS->SetDescription(poOpenInfo->pszFilename); |
102 | | |
103 | 1.03k | poDS->fp = poOpenInfo->fpL; |
104 | 1.03k | poOpenInfo->fpL = nullptr; |
105 | | |
106 | 1.03k | poDS->poLayer = new OGRJMLLayer( |
107 | 1.03k | CPLGetBasenameSafe(poOpenInfo->pszFilename).c_str(), poDS, poDS->fp); |
108 | | |
109 | 1.03k | return poDS; |
110 | 1.03k | #endif |
111 | 1.03k | } |
112 | | |
113 | | /************************************************************************/ |
114 | | /* Create() */ |
115 | | /************************************************************************/ |
116 | | |
117 | | GDALDataset *OGRJMLDataset::Create(const char *pszFilename, int /* nXSize */, |
118 | | int /* nYSize */, int /* nBands */, |
119 | | GDALDataType /* eDT */, |
120 | | char ** /* papszOptions */) |
121 | 56 | { |
122 | 56 | if (strcmp(pszFilename, "/dev/stdout") == 0) |
123 | 0 | pszFilename = "/vsistdout/"; |
124 | | |
125 | | /* -------------------------------------------------------------------- */ |
126 | | /* Do not override exiting file. */ |
127 | | /* -------------------------------------------------------------------- */ |
128 | 56 | VSIStatBufL sStatBuf; |
129 | | |
130 | 56 | if (VSIStatL(pszFilename, &sStatBuf) == 0) |
131 | 0 | { |
132 | 0 | CPLError(CE_Failure, CPLE_NotSupported, |
133 | 0 | "You have to delete %s before being able to create it " |
134 | 0 | "with the JML driver", |
135 | 0 | pszFilename); |
136 | 0 | return nullptr; |
137 | 0 | } |
138 | | |
139 | 56 | OGRJMLDataset *poDS = new OGRJMLDataset(); |
140 | | |
141 | | /* -------------------------------------------------------------------- */ |
142 | | /* Create the output file. */ |
143 | | /* -------------------------------------------------------------------- */ |
144 | 56 | poDS->bWriteMode = true; |
145 | 56 | poDS->SetDescription(pszFilename); |
146 | | |
147 | 56 | poDS->fp = VSIFOpenL(pszFilename, "w"); |
148 | 56 | if (poDS->fp == nullptr) |
149 | 0 | { |
150 | 0 | CPLError(CE_Failure, CPLE_OpenFailed, "Failed to create JML file %s.", |
151 | 0 | pszFilename); |
152 | 0 | delete poDS; |
153 | 0 | return nullptr; |
154 | 0 | } |
155 | | |
156 | 56 | return poDS; |
157 | 56 | } |
158 | | |
159 | | /************************************************************************/ |
160 | | /* ICreateLayer() */ |
161 | | /************************************************************************/ |
162 | | |
163 | | OGRLayer *OGRJMLDataset::ICreateLayer(const char *pszLayerName, |
164 | | const OGRGeomFieldDefn *poGeomFieldDefn, |
165 | | CSLConstList papszOptions) |
166 | 56 | { |
167 | 56 | if (!bWriteMode || poLayer != nullptr) |
168 | 0 | return nullptr; |
169 | | |
170 | 56 | bool bAddRGBField = CPLTestBool( |
171 | 56 | CSLFetchNameValueDef(papszOptions, "CREATE_R_G_B_FIELD", "YES")); |
172 | 56 | bool bAddOGRStyleField = CPLTestBool( |
173 | 56 | CSLFetchNameValueDef(papszOptions, "CREATE_OGR_STYLE_FIELD", "NO")); |
174 | 56 | bool bClassicGML = |
175 | 56 | CPLTestBool(CSLFetchNameValueDef(papszOptions, "CLASSIC_GML", "NO")); |
176 | 56 | OGRSpatialReference *poSRSClone = nullptr; |
177 | 56 | const auto poSRS = |
178 | 56 | poGeomFieldDefn ? poGeomFieldDefn->GetSpatialRef() : nullptr; |
179 | 56 | if (poSRS) |
180 | 0 | { |
181 | 0 | poSRSClone = poSRS->Clone(); |
182 | 0 | poSRSClone->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); |
183 | 0 | } |
184 | 56 | poLayer = |
185 | 56 | new OGRJMLWriterLayer(pszLayerName, poSRSClone, this, fp, bAddRGBField, |
186 | 56 | bAddOGRStyleField, bClassicGML); |
187 | 56 | if (poSRSClone) |
188 | 0 | poSRSClone->Release(); |
189 | | |
190 | 56 | return poLayer; |
191 | 56 | } |
192 | | |
193 | | /************************************************************************/ |
194 | | /* RegisterOGRJML() */ |
195 | | /************************************************************************/ |
196 | | |
197 | | void RegisterOGRJML() |
198 | 22 | { |
199 | 22 | if (GDALGetDriverByName("JML") != nullptr) |
200 | 0 | return; |
201 | | |
202 | 22 | GDALDriver *poDriver = new GDALDriver(); |
203 | | |
204 | 22 | poDriver->SetDescription("JML"); |
205 | 22 | poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES"); |
206 | 22 | poDriver->SetMetadataItem(GDAL_DCAP_CREATE_LAYER, "YES"); |
207 | 22 | poDriver->SetMetadataItem(GDAL_DCAP_CREATE_FIELD, "YES"); |
208 | 22 | poDriver->SetMetadataItem(GDAL_DCAP_Z_GEOMETRIES, "YES"); |
209 | 22 | poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "OpenJUMP JML"); |
210 | 22 | poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "jml"); |
211 | 22 | poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/vector/jml.html"); |
212 | | |
213 | 22 | poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); |
214 | 22 | poDriver->SetMetadataItem(GDAL_DCAP_FEATURE_STYLES, "YES"); |
215 | 22 | poDriver->SetMetadataItem(GDAL_DCAP_FEATURE_STYLES_READ, "YES"); |
216 | 22 | poDriver->SetMetadataItem(GDAL_DCAP_FEATURE_STYLES_WRITE, "YES"); |
217 | 22 | poDriver->SetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS, "OGRSQL SQLITE"); |
218 | | |
219 | 22 | poDriver->SetMetadataItem( |
220 | 22 | GDAL_DS_LAYER_CREATIONOPTIONLIST, |
221 | 22 | "<LayerCreationOptionList>" |
222 | 22 | " <Option name='CREATE_R_G_B_FIELD' type='boolean' " |
223 | 22 | "description='Whether to create a R_G_B field' default='YES'/>" |
224 | 22 | " <Option name='CREATE_OGR_STYLE_FIELD' type='boolean' " |
225 | 22 | "description='Whether to create a OGR_STYLE field' default='NO'/>" |
226 | 22 | "</LayerCreationOptionList>"); |
227 | | |
228 | 22 | poDriver->SetMetadataItem(GDAL_DMD_CREATIONOPTIONLIST, |
229 | 22 | "<CreationOptionList/>"); |
230 | | |
231 | 22 | poDriver->SetMetadataItem(GDAL_DMD_CREATIONFIELDDATATYPES, |
232 | 22 | "Integer Integer64 Real String Date DateTime"); |
233 | | |
234 | 22 | poDriver->pfnOpen = OGRJMLDataset::Open; |
235 | 22 | poDriver->pfnIdentify = OGRJMLDataset::Identify; |
236 | 22 | poDriver->pfnCreate = OGRJMLDataset::Create; |
237 | | |
238 | 22 | GetGDALDriverManager()->RegisterDriver(poDriver); |
239 | 22 | } |