-
-
Notifications
You must be signed in to change notification settings - Fork 337
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add postgis plugin with support for JTS data types
- Loading branch information
Showing
4 changed files
with
403 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
218 changes: 218 additions & 0 deletions
218
postgres/src/main/java/org/jdbi/v3/postgres/PostgisPlugin.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,218 @@ | ||
/* | ||
* Copyright (C) 2020 The Baremaps Authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except | ||
* in compliance with the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software distributed under the License | ||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express | ||
* or implied. See the License for the specific language governing permissions and limitations under | ||
* the License. | ||
*/ | ||
|
||
package org.jdbi.v3.postgres; | ||
|
||
import static org.locationtech.jts.io.WKBConstants.wkbNDR; | ||
|
||
import java.sql.ResultSet; | ||
import java.sql.SQLException; | ||
import java.sql.Types; | ||
import org.jdbi.v3.core.Jdbi; | ||
import org.jdbi.v3.core.argument.AbstractArgumentFactory; | ||
import org.jdbi.v3.core.argument.Argument; | ||
import org.jdbi.v3.core.config.ConfigRegistry; | ||
import org.jdbi.v3.core.mapper.ColumnMapper; | ||
import org.jdbi.v3.core.spi.JdbiPlugin; | ||
import org.jdbi.v3.core.statement.StatementContext; | ||
import org.locationtech.jts.geom.Geometry; | ||
import org.locationtech.jts.geom.GeometryCollection; | ||
import org.locationtech.jts.geom.GeometryFactory; | ||
import org.locationtech.jts.geom.LineString; | ||
import org.locationtech.jts.geom.LinearRing; | ||
import org.locationtech.jts.geom.MultiLineString; | ||
import org.locationtech.jts.geom.MultiPoint; | ||
import org.locationtech.jts.geom.MultiPolygon; | ||
import org.locationtech.jts.geom.Point; | ||
import org.locationtech.jts.geom.Polygon; | ||
import org.locationtech.jts.io.ParseException; | ||
import org.locationtech.jts.io.WKBReader; | ||
import org.locationtech.jts.io.WKBWriter; | ||
|
||
/** | ||
* Postgis plugin. Adds support for binding and mapping the following data types: | ||
* | ||
* <ul> | ||
* <li>{@link org.locationtech.jts.geom.Point}</li> | ||
* <li>{@link org.locationtech.jts.geom.LineString}</li> | ||
* <li>{@link org.locationtech.jts.geom.LinearRing}</li> | ||
* <li>{@link org.locationtech.jts.geom.Polygon}</li> | ||
* <li>{@link org.locationtech.jts.geom.MultiPoint}</li> | ||
* <li>{@link org.locationtech.jts.geom.MultiLineString}</li> | ||
* <li>{@link org.locationtech.jts.geom.MultiPolygon}</li> | ||
* <li>{@link org.locationtech.jts.geom.GeometryCollection}</li> | ||
* <li>{@link org.locationtech.jts.geom.Geometry}</li> | ||
*/ | ||
public class PostgisPlugin extends JdbiPlugin.Singleton { | ||
|
||
@Override | ||
public void customizeJdbi(Jdbi jdbi) { | ||
// Register argument factories | ||
jdbi.registerArgument(new PointArgumentFactory()); | ||
jdbi.registerArgument(new LineStringArgumentFactory()); | ||
jdbi.registerArgument(new LinearRingArgumentFactory()); | ||
jdbi.registerArgument(new PolygonArgumentFactory()); | ||
jdbi.registerArgument(new MultiPointArgumentFactory()); | ||
jdbi.registerArgument(new MultiLineStringArgumentFactory()); | ||
jdbi.registerArgument(new MultiPolygonArgumentFactory()); | ||
jdbi.registerArgument(new GeometryCollectionArgumentFactory()); | ||
jdbi.registerArgument(new GeometryArgumentFactory()); | ||
|
||
// Register column mappers | ||
jdbi.registerColumnMapper(new PointColumnMapper()); | ||
jdbi.registerColumnMapper(new LineStringColumnMapper()); | ||
jdbi.registerColumnMapper(new LinearRingColumnMapper()); | ||
jdbi.registerColumnMapper(new PolygonColumnMapper()); | ||
jdbi.registerColumnMapper(new MultiPointColumnMapper()); | ||
jdbi.registerColumnMapper(new MultiLineStringColumnMapper()); | ||
jdbi.registerColumnMapper(new MultiPolygonColumnMapper()); | ||
jdbi.registerColumnMapper(new GeometryCollectionColumnMapper()); | ||
jdbi.registerColumnMapper(new GeometryColumnMapper()); | ||
} | ||
|
||
/** | ||
* Serializes a geometry in the WKB format. | ||
* | ||
* @param geometry | ||
* @return | ||
*/ | ||
public static byte[] serialize(Geometry geometry) { | ||
if (geometry == null) { | ||
return null; | ||
} | ||
WKBWriter writer = new WKBWriter(2, wkbNDR, true); | ||
return writer.write(geometry); | ||
} | ||
|
||
/** | ||
* Deserializes a geometry in the WKB format. | ||
* | ||
* @param wkb | ||
* @return | ||
*/ | ||
public static Geometry deserialize(byte[] wkb) { | ||
if (wkb == null) { | ||
return null; | ||
} | ||
try { | ||
WKBReader reader = new WKBReader(new GeometryFactory()); | ||
return reader.read(wkb); | ||
} catch (ParseException e) { | ||
throw new IllegalArgumentException(e); | ||
} | ||
} | ||
|
||
abstract static class BaseArgumentFactory<T extends Geometry> extends AbstractArgumentFactory<T> { | ||
|
||
public BaseArgumentFactory() { | ||
super(Types.OTHER); | ||
} | ||
|
||
@Override | ||
public Argument build(T value, ConfigRegistry config) { | ||
return (position, statement, ctx) -> statement.setBytes(position, serialize(value)); | ||
} | ||
} | ||
|
||
abstract static class BaseColumnMapper<T extends Geometry> implements ColumnMapper<T> { | ||
|
||
@Override | ||
public T map(ResultSet r, int columnNumber, StatementContext ctx) throws SQLException { | ||
byte[] bytes = hexStringToByteArray(r.getString(columnNumber)); | ||
return (T) deserialize(bytes); | ||
} | ||
|
||
private static byte[] hexStringToByteArray(String s) { | ||
int len = s.length(); | ||
byte[] data = new byte[len / 2]; | ||
for (int i = 0; i < len; i += 2) { | ||
data[i / 2] = | ||
(byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16)); | ||
} | ||
return data; | ||
} | ||
} | ||
|
||
static final class GeometryArgumentFactory extends BaseArgumentFactory<Geometry> { | ||
|
||
} | ||
|
||
static final class GeometryCollectionArgumentFactory extends BaseArgumentFactory<GeometryCollection> { | ||
|
||
} | ||
|
||
static final class GeometryCollectionColumnMapper extends BaseColumnMapper<GeometryCollection> { | ||
|
||
} | ||
|
||
static final class GeometryColumnMapper extends BaseColumnMapper<Geometry> { | ||
|
||
} | ||
|
||
static final class LinearRingArgumentFactory extends BaseArgumentFactory<LinearRing> { | ||
|
||
} | ||
|
||
static final class LinearRingColumnMapper extends BaseColumnMapper<LinearRing> { | ||
|
||
} | ||
|
||
static final class LineStringArgumentFactory extends BaseArgumentFactory<LineString> { | ||
|
||
} | ||
|
||
static final class LineStringColumnMapper extends BaseColumnMapper<LineString> { | ||
|
||
} | ||
|
||
static final class MultiLineStringArgumentFactory extends BaseArgumentFactory<MultiLineString> { | ||
|
||
} | ||
|
||
static final class MultiLineStringColumnMapper extends BaseColumnMapper<MultiLineString> { | ||
|
||
} | ||
|
||
static final class MultiPointArgumentFactory extends BaseArgumentFactory<MultiPoint> { | ||
|
||
} | ||
|
||
static final class MultiPointColumnMapper extends BaseColumnMapper<MultiPoint> { | ||
|
||
} | ||
|
||
static final class MultiPolygonArgumentFactory extends BaseArgumentFactory<MultiPolygon> { | ||
|
||
} | ||
|
||
static final class MultiPolygonColumnMapper extends BaseColumnMapper<MultiPolygon> { | ||
|
||
} | ||
|
||
static final class PointArgumentFactory extends BaseArgumentFactory<Point> { | ||
|
||
} | ||
|
||
static final class PointColumnMapper extends BaseColumnMapper<Point> { | ||
|
||
} | ||
|
||
static final class PolygonArgumentFactory extends BaseArgumentFactory<Polygon> { | ||
|
||
} | ||
|
||
static final class PolygonColumnMapper extends BaseColumnMapper<Polygon> { | ||
|
||
} | ||
} |
Oops, something went wrong.