@@ -2,9 +2,13 @@ package fi.hsl.jore4.mapmatching.service.matching.test
22
33import fi.hsl.jore4.mapmatching.util.GeoToolsUtils.transformCRS
44import org.geolatte.geom.jts.JTS
5+ import org.geotools.api.data.SimpleFeatureWriter
6+ import org.geotools.api.data.Transaction
57import org.geotools.api.feature.simple.SimpleFeature
68import org.geotools.api.feature.simple.SimpleFeatureType
9+ import org.geotools.data.DefaultTransaction
710import org.geotools.data.collection.ListFeatureCollection
11+ import org.geotools.data.simple.SimpleFeatureIterator
812import org.geotools.feature.simple.SimpleFeatureBuilder
913import org.geotools.feature.simple.SimpleFeatureTypeBuilder
1014import org.geotools.geometry.jts.Geometries
@@ -14,6 +18,7 @@ import org.geotools.referencing.crs.DefaultGeographicCRS
1418import org.locationtech.jts.geom.Geometry
1519import org.locationtech.jts.geom.LineString
1620import java.io.File
21+ import java.io.IOException
1722
1823object GeoPackageUtils {
1924 private const val GEOMETRY_COLUMN_NAME = " geometry"
@@ -32,16 +37,24 @@ object GeoPackageUtils {
3237 val featureType: SimpleFeatureType =
3338 createFeatureTypeForFailedSegment(featureTypeName, isBufferPolygonInsteadOfLineString)
3439
40+ val featureCollection: ListFeatureCollection =
41+ createFeatureCollection(segment, featureType, isBufferPolygonInsteadOfLineString)
42+
3543 val entry = FeatureEntry ()
36- entry.identifier = segment.routeId
44+ // entry.identifier = segment.routeId
45+ entry.geometryColumn = GEOMETRY_COLUMN_NAME
46+ entry.geometryType =
47+ if (isBufferPolygonInsteadOfLineString) Geometries .POLYGON else Geometries .LINESTRING
48+ entry.bounds = featureCollection.bounds
49+
3750 entry.description =
3851 if (isBufferPolygonInsteadOfLineString) {
3952 " Buffered geometry for failed ${segment.routeId} segment within map-matching"
4053 } else {
4154 " LineString for failed ${segment.routeId} segment within map-matching"
4255 }
4356
44- geoPkg.add(entry, createFeatureCollection(segment, featureType, isBufferPolygonInsteadOfLineString) )
57+ writeEntryToGeoPackage(geoPkg, entry, featureCollection )
4558
4659 // Not sure, if this is really needed.
4760 geoPkg.createSpatialIndex(entry)
@@ -114,6 +127,47 @@ object GeoPackageUtils {
114127 builder.add(referencingRoutes.joinToString(separator = " " ))
115128 }
116129
117- return builder.buildFeature(failedSegment.routeId)
130+ // This works because every feature is put into a separate table.
131+ builder.featureUserData(" fid" , " 1" )
132+
133+ return builder.buildFeature(null )
134+ }
135+
136+ private fun writeEntryToGeoPackage (
137+ geoPkg : GeoPackage ,
138+ entry : FeatureEntry ,
139+ featureCollection : ListFeatureCollection
140+ ) {
141+ // Create an SQLite table for FeatureCollection.
142+ geoPkg.create(entry, featureCollection.schema)
143+
144+ val tx: Transaction = DefaultTransaction ()
145+ val it: SimpleFeatureIterator = featureCollection.features()
146+
147+ try {
148+ val writer: SimpleFeatureWriter = geoPkg.writer(entry, true , null , tx)
149+
150+ val source = it.next()
151+ val target: SimpleFeature = writer.next()
152+
153+ target.attributes = source.attributes
154+
155+ // This if-block is the missing piece not done in the GeoPackage.add() method.
156+ if (source.hasUserData()) {
157+ target.userData.putAll(source.userData)
158+ }
159+
160+ writer.write()
161+ writer.close()
162+
163+ tx.commit()
164+ } catch (ex: Exception ) {
165+ tx.rollback()
166+
167+ throw ex as ? IOException ? : IOException (ex)
168+ } finally {
169+ tx.close()
170+ it.close()
171+ }
118172 }
119173}
0 commit comments