Line data Source code
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 82 : OGRJMLDataset::OGRJMLDataset()
27 82 : : poLayer(nullptr), fp(nullptr), bWriteMode(false)
28 : {
29 82 : }
30 :
31 : /************************************************************************/
32 : /* ~OGRJMLDataset() */
33 : /************************************************************************/
34 :
35 164 : OGRJMLDataset::~OGRJMLDataset()
36 :
37 : {
38 82 : delete poLayer;
39 :
40 82 : if (fp != nullptr)
41 80 : VSIFCloseL(fp);
42 164 : }
43 :
44 : /************************************************************************/
45 : /* TestCapability() */
46 : /************************************************************************/
47 :
48 57 : int OGRJMLDataset::TestCapability(const char *pszCap)
49 :
50 : {
51 57 : if (EQUAL(pszCap, ODsCCreateLayer))
52 34 : return bWriteMode && poLayer == nullptr;
53 23 : if (EQUAL(pszCap, ODsCZGeometries))
54 2 : return true;
55 :
56 21 : return false;
57 : }
58 :
59 : /************************************************************************/
60 : /* GetLayer() */
61 : /************************************************************************/
62 :
63 33 : OGRLayer *OGRJMLDataset::GetLayer(int iLayer)
64 :
65 : {
66 33 : if (iLayer != 0)
67 3 : return nullptr;
68 :
69 30 : return poLayer;
70 : }
71 :
72 : /************************************************************************/
73 : /* Identify() */
74 : /************************************************************************/
75 :
76 45094 : int OGRJMLDataset::Identify(GDALOpenInfo *poOpenInfo)
77 : {
78 47510 : return poOpenInfo->nHeaderBytes != 0 &&
79 2416 : strstr(reinterpret_cast<char *>(poOpenInfo->pabyHeader),
80 45094 : "<JCSDataFile") != nullptr;
81 : }
82 :
83 : /************************************************************************/
84 : /* Open() */
85 : /************************************************************************/
86 :
87 42 : GDALDataset *OGRJMLDataset::Open(GDALOpenInfo *poOpenInfo)
88 :
89 : {
90 84 : if (!Identify(poOpenInfo) || poOpenInfo->fpL == nullptr ||
91 42 : 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 42 : OGRJMLDataset *poDS = new OGRJMLDataset();
101 42 : poDS->SetDescription(poOpenInfo->pszFilename);
102 :
103 42 : poDS->fp = poOpenInfo->fpL;
104 42 : poOpenInfo->fpL = nullptr;
105 :
106 42 : poDS->poLayer = new OGRJMLLayer(CPLGetBasename(poOpenInfo->pszFilename),
107 42 : poDS, poDS->fp);
108 :
109 42 : return poDS;
110 : #endif
111 : }
112 :
113 : /************************************************************************/
114 : /* Create() */
115 : /************************************************************************/
116 :
117 40 : GDALDataset *OGRJMLDataset::Create(const char *pszFilename, int /* nXSize */,
118 : int /* nYSize */, int /* nBands */,
119 : GDALDataType /* eDT */,
120 : char ** /* papszOptions */)
121 : {
122 40 : if (strcmp(pszFilename, "/dev/stdout") == 0)
123 0 : pszFilename = "/vsistdout/";
124 :
125 : /* -------------------------------------------------------------------- */
126 : /* Do not override exiting file. */
127 : /* -------------------------------------------------------------------- */
128 : VSIStatBufL sStatBuf;
129 :
130 40 : if (VSIStatL(pszFilename, &sStatBuf) == 0)
131 : {
132 0 : CPLError(CE_Failure, CPLE_NotSupported,
133 : "You have to delete %s before being able to create it "
134 : "with the JML driver",
135 : pszFilename);
136 0 : return nullptr;
137 : }
138 :
139 40 : OGRJMLDataset *poDS = new OGRJMLDataset();
140 :
141 : /* -------------------------------------------------------------------- */
142 : /* Create the output file. */
143 : /* -------------------------------------------------------------------- */
144 40 : poDS->bWriteMode = true;
145 40 : poDS->SetDescription(pszFilename);
146 :
147 40 : poDS->fp = VSIFOpenL(pszFilename, "w");
148 40 : if (poDS->fp == nullptr)
149 : {
150 2 : CPLError(CE_Failure, CPLE_OpenFailed, "Failed to create JML file %s.",
151 : pszFilename);
152 2 : delete poDS;
153 2 : return nullptr;
154 : }
155 :
156 38 : return poDS;
157 : }
158 :
159 : /************************************************************************/
160 : /* ICreateLayer() */
161 : /************************************************************************/
162 :
163 54 : OGRLayer *OGRJMLDataset::ICreateLayer(const char *pszLayerName,
164 : const OGRGeomFieldDefn *poGeomFieldDefn,
165 : CSLConstList papszOptions)
166 : {
167 54 : if (!bWriteMode || poLayer != nullptr)
168 16 : return nullptr;
169 :
170 38 : bool bAddRGBField = CPLTestBool(
171 : CSLFetchNameValueDef(papszOptions, "CREATE_R_G_B_FIELD", "YES"));
172 38 : bool bAddOGRStyleField = CPLTestBool(
173 : CSLFetchNameValueDef(papszOptions, "CREATE_OGR_STYLE_FIELD", "NO"));
174 : bool bClassicGML =
175 38 : CPLTestBool(CSLFetchNameValueDef(papszOptions, "CLASSIC_GML", "NO"));
176 38 : OGRSpatialReference *poSRSClone = nullptr;
177 : const auto poSRS =
178 38 : poGeomFieldDefn ? poGeomFieldDefn->GetSpatialRef() : nullptr;
179 38 : if (poSRS)
180 : {
181 1 : poSRSClone = poSRS->Clone();
182 1 : poSRSClone->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
183 : }
184 38 : poLayer =
185 : new OGRJMLWriterLayer(pszLayerName, poSRSClone, this, fp, bAddRGBField,
186 38 : bAddOGRStyleField, bClassicGML);
187 38 : if (poSRSClone)
188 1 : poSRSClone->Release();
189 :
190 38 : return poLayer;
191 : }
192 :
193 : /************************************************************************/
194 : /* RegisterOGRJML() */
195 : /************************************************************************/
196 :
197 1595 : void RegisterOGRJML()
198 : {
199 1595 : if (GDALGetDriverByName("JML") != nullptr)
200 302 : return;
201 :
202 1293 : GDALDriver *poDriver = new GDALDriver();
203 :
204 1293 : poDriver->SetDescription("JML");
205 1293 : poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES");
206 1293 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE_LAYER, "YES");
207 1293 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE_FIELD, "YES");
208 1293 : poDriver->SetMetadataItem(GDAL_DCAP_Z_GEOMETRIES, "YES");
209 1293 : poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "OpenJUMP JML");
210 1293 : poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "jml");
211 1293 : poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/vector/jml.html");
212 :
213 1293 : poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
214 1293 : poDriver->SetMetadataItem(GDAL_DCAP_FEATURE_STYLES, "YES");
215 1293 : poDriver->SetMetadataItem(GDAL_DCAP_FEATURE_STYLES_READ, "YES");
216 1293 : poDriver->SetMetadataItem(GDAL_DCAP_FEATURE_STYLES_WRITE, "YES");
217 1293 : poDriver->SetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS, "OGRSQL SQLITE");
218 :
219 1293 : poDriver->SetMetadataItem(
220 : GDAL_DS_LAYER_CREATIONOPTIONLIST,
221 : "<LayerCreationOptionList>"
222 : " <Option name='CREATE_R_G_B_FIELD' type='boolean' "
223 : "description='Whether to create a R_G_B field' default='YES'/>"
224 : " <Option name='CREATE_OGR_STYLE_FIELD' type='boolean' "
225 : "description='Whether to create a OGR_STYLE field' default='NO'/>"
226 1293 : "</LayerCreationOptionList>");
227 :
228 1293 : poDriver->SetMetadataItem(GDAL_DMD_CREATIONOPTIONLIST,
229 1293 : "<CreationOptionList/>");
230 :
231 1293 : poDriver->SetMetadataItem(GDAL_DMD_CREATIONFIELDDATATYPES,
232 1293 : "Integer Integer64 Real String Date DateTime");
233 :
234 1293 : poDriver->pfnOpen = OGRJMLDataset::Open;
235 1293 : poDriver->pfnIdentify = OGRJMLDataset::Identify;
236 1293 : poDriver->pfnCreate = OGRJMLDataset::Create;
237 :
238 1293 : GetGDALDriverManager()->RegisterDriver(poDriver);
239 : }
|