blob: 0cd27dffa00ef2341d3640aba2b422666918f28a [file] [log] [blame]
// SPDX-License-Identifier: LGPL-2.1-or-later
// Copyright (c) 2012-2014 Monty Program Ab
// Copyright (c) 2015-2021 MariaDB Corporation Ab
package org.mariadb.jdbc.type;
import java.sql.SQLDataException;
import org.mariadb.jdbc.client.Column;
import org.mariadb.jdbc.client.ReadableByteBuf;
/** Geometry parser */
public interface Geometry {
/**
* Parse point from packet
*
* @param littleEndian encoding order
* @param buf packet buffer
* @return point value
*/
static Point parsePoint(boolean littleEndian, ReadableByteBuf buf) {
double x = littleEndian ? buf.readDouble() : buf.readDoubleBE();
double y = littleEndian ? buf.readDouble() : buf.readDoubleBE();
return new Point(x, y);
}
/**
* parse geometry object
*
* @param buf packet buffer
* @param length data length
* @param column column meta
* @return geometry parsed object
* @throws SQLDataException if parsing exception occurs
*/
static Geometry getGeometry(ReadableByteBuf buf, int length, Column column)
throws SQLDataException {
if (length == 0) return null;
boolean littleEndian = buf.readByte() == 0x01;
int dataType = littleEndian ? buf.readInt() : buf.readIntBE();
switch (dataType) {
case 1:
// wkbPoint
return parsePoint(littleEndian, buf);
case 2:
// wkbLineString
int pointNumber = littleEndian ? buf.readInt() : buf.readIntBE();
Point[] points = new Point[pointNumber];
for (int i = 0; i < pointNumber; i++) {
points[i] = parsePoint(littleEndian, buf);
}
return new LineString(points, true);
case 3:
// wkbPolygon
int numRings = littleEndian ? buf.readInt() : buf.readIntBE();
LineString[] lines = new LineString[numRings];
for (int i = 0; i < numRings; i++) {
int pointNb = littleEndian ? buf.readInt() : buf.readIntBE();
Point[] lsPoints = new Point[pointNb];
for (int j = 0; j < pointNb; j++) {
lsPoints[j] = parsePoint(littleEndian, buf);
}
lines[i] = new LineString(lsPoints, false);
}
return new Polygon(lines);
case 4:
// wkbMultiPoint
int pointNb = littleEndian ? buf.readInt() : buf.readIntBE();
Point[] pointArr = new Point[pointNb];
for (int i = 0; i < pointNb; i++) {
pointArr[i] = (Point) getGeometry(buf, length, column);
}
return new MultiPoint(pointArr);
case 5:
// wkbMultiLinestring
int multiNb = littleEndian ? buf.readInt() : buf.readIntBE();
LineString[] multiLines = new LineString[multiNb];
for (int i = 0; i < multiNb; i++) {
multiLines[i] = (LineString) getGeometry(buf, length, column);
}
return new MultiLineString(multiLines);
case 6:
// wkbMultiPolygon
int multiPolyNb = littleEndian ? buf.readInt() : buf.readIntBE();
Polygon[] multiPolygons = new Polygon[multiPolyNb];
for (int i = 0; i < multiPolyNb; i++) {
multiPolygons[i] = (Polygon) getGeometry(buf, length, column);
}
return new MultiPolygon(multiPolygons);
case 7:
// wkbGeometryCollection
int multiCollNb = littleEndian ? buf.readInt() : buf.readIntBE();
Geometry[] multiGeos = new Geometry[multiCollNb];
for (int i = 0; i < multiCollNb; i++) {
multiGeos[i] = getGeometry(buf, length, column);
}
return new GeometryCollection(multiGeos);
default:
// ERROR
buf.skip(length - 5);
throw new SQLDataException(
String.format("Data type %s cannot be decoded as Geometry", column.getType()));
}
}
}