Skip to content

Commit 57479ea

Browse files
committed
feature: adding support for lseg type
1 parent 83ffd14 commit 57479ea

File tree

6 files changed

+289
-2
lines changed

6 files changed

+289
-2
lines changed

src/main/java/io/r2dbc/postgresql/codec/DefaultCodecs.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ public DefaultCodecs(ByteBufAllocator byteBufAllocator) {
9797

9898
//Geometry
9999
new CircleCodec(byteBufAllocator),
100+
new LineSegmentCodec(byteBufAllocator),
100101
new PointCodec(byteBufAllocator)
101102
));
102103
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright 2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.r2dbc.postgresql.codec;
18+
19+
import io.r2dbc.postgresql.util.Assert;
20+
21+
public final class LineSegment {
22+
23+
private final Point point1;
24+
25+
private final Point point2;
26+
27+
public LineSegment(Point point1, Point point2) {
28+
this.point1 = Assert.requireNonNull(point1, "First Point must not be null");
29+
this.point2 = Assert.requireNonNull(point2, "Second Point must not be null");
30+
}
31+
32+
public LineSegment(double x1, double y1, double x2, double y2) {
33+
this.point1 = Point.of(x1, y1);
34+
this.point2 = Point.of(x2, y2);
35+
}
36+
37+
public Point getPoint1() {
38+
return point1;
39+
}
40+
41+
public Point getPoint2() {
42+
return point2;
43+
}
44+
45+
@Override
46+
public boolean equals(Object obj) {
47+
if (obj instanceof LineSegment) {
48+
LineSegment lineSegment = (LineSegment) obj;
49+
return (lineSegment.point1.equals(this.point1) && lineSegment.point2.equals(this.point2))
50+
|| (lineSegment.point1.equals(this.point2) && lineSegment.point2.equals(this.point1));
51+
}
52+
return false;
53+
}
54+
55+
@Override
56+
public int hashCode() {
57+
return point1.hashCode() ^ point2.hashCode();
58+
}
59+
60+
@Override
61+
public String toString() {
62+
return "[" + this.point1.toString() + "," + this.point2.toString() + "]";
63+
}
64+
65+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*
2+
* Copyright 2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.r2dbc.postgresql.codec;
18+
19+
import io.netty.buffer.ByteBuf;
20+
import io.netty.buffer.ByteBufAllocator;
21+
import io.r2dbc.postgresql.client.Parameter;
22+
import io.r2dbc.postgresql.message.Format;
23+
import io.r2dbc.postgresql.type.PostgresqlObjectId;
24+
import io.r2dbc.postgresql.util.Assert;
25+
import io.r2dbc.postgresql.util.ByteBufUtils;
26+
import reactor.util.annotation.Nullable;
27+
28+
import static io.r2dbc.postgresql.message.Format.FORMAT_BINARY;
29+
import static io.r2dbc.postgresql.type.PostgresqlObjectId.LSEG;
30+
31+
final class LineSegmentCodec extends AbstractCodec<LineSegment> {
32+
33+
private final ByteBufAllocator byteBufAllocator;
34+
35+
LineSegmentCodec(ByteBufAllocator byteBufAllocator) {
36+
super(LineSegment.class);
37+
this.byteBufAllocator = Assert.requireNonNull(byteBufAllocator, "byteBufAllocator must not be null");
38+
}
39+
40+
@Override
41+
boolean doCanDecode(PostgresqlObjectId type, @Nullable Format format) {
42+
Assert.requireNonNull(type, "type must not be null");
43+
44+
return LSEG == type;
45+
}
46+
47+
@Override
48+
LineSegment doDecode(ByteBuf buffer, PostgresqlObjectId dataType, Format format, Class<? extends LineSegment> type) {
49+
Assert.requireNonNull(buffer, "byteBuf must not be null");
50+
Assert.requireNonNull(type, "type must not be null");
51+
Assert.requireNonNull(format, "format must not be null");
52+
53+
if (format == FORMAT_BINARY) {
54+
double x1 = buffer.readDouble();
55+
double y1 = buffer.readDouble();
56+
double x2 = buffer.readDouble();
57+
double y2 = buffer.readDouble();
58+
return new LineSegment(Point.of(x1, y1), Point.of(x2, y2));
59+
}
60+
61+
String decodedAsString = ByteBufUtils.decode(buffer);
62+
String parenRemovedVal = decodedAsString.replaceAll("[()]", "")
63+
.replace("[", "")
64+
.replace("]", "")
65+
.trim();
66+
String[] coordinatesAsString = parenRemovedVal.split(",");
67+
double x1 = Double.parseDouble(coordinatesAsString[0]);
68+
double y1 = Double.parseDouble(coordinatesAsString[1]);
69+
double x2 = Double.parseDouble(coordinatesAsString[2]);
70+
double y2 = Double.parseDouble(coordinatesAsString[3]);
71+
return new LineSegment(Point.of(x1, y1), Point.of(x2, y2));
72+
}
73+
74+
@Override
75+
Parameter doEncode(LineSegment value) {
76+
Assert.requireNonNull(value, "value must not be null");
77+
Point p1 = value.getPoint1();
78+
Point p2 = value.getPoint2();
79+
return create(LSEG, FORMAT_BINARY, () -> this.byteBufAllocator
80+
.buffer(lengthInBytes())
81+
.writeDouble(p1.getX())
82+
.writeDouble(p1.getY())
83+
.writeDouble(p2.getX())
84+
.writeDouble(p2.getY()));
85+
}
86+
87+
@Override
88+
public Parameter encodeNull() {
89+
return createNull(LSEG, FORMAT_BINARY);
90+
}
91+
92+
int lengthInBytes() {
93+
return 32;
94+
}
95+
96+
}

src/main/java/io/r2dbc/postgresql/type/PostgresqlObjectId.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,9 +188,9 @@ public enum PostgresqlObjectId {
188188
LINE(628),
189189

190190
/**
191-
* The line segment object id
191+
* The line segment(lseg) object id
192192
*/
193-
LINE_SEGMENT(601),
193+
LSEG(601),
194194

195195
/**
196196
* The money object id.

src/test/java/io/r2dbc/postgresql/AbstractCodecIntegrationTests.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import io.r2dbc.postgresql.codec.Circle;
2525
import io.r2dbc.postgresql.codec.EnumCodec;
2626
import io.r2dbc.postgresql.codec.Json;
27+
import io.r2dbc.postgresql.codec.LineSegment;
2728
import io.r2dbc.postgresql.codec.Point;
2829
import io.r2dbc.spi.Blob;
2930
import io.r2dbc.spi.Clob;
@@ -334,6 +335,12 @@ void jsonb() {
334335
}, "JSONB");
335336
}
336337

338+
@Test
339+
void lineSegment() {
340+
testCodec(LineSegment.class, new LineSegment(Point.of(1.12, 2.12), Point.of(3.12, 4.12)), "LSEG");
341+
testCodec(LineSegment.class, new LineSegment(Point.of(Double.MIN_VALUE, Double.MIN_VALUE), Point.of(Double.MAX_VALUE, Double.MAX_VALUE)), "LSEG");
342+
}
343+
337344
@Test
338345
void localDate() {
339346
testCodec(LocalDate.class, LocalDate.now(), "DATE");
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/*
2+
* Copyright 2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.r2dbc.postgresql.codec;
18+
19+
import io.netty.buffer.ByteBuf;
20+
import io.r2dbc.postgresql.client.Parameter;
21+
import io.r2dbc.postgresql.client.ParameterAssert;
22+
import org.junit.jupiter.api.Test;
23+
24+
import static io.r2dbc.postgresql.client.Parameter.NULL_VALUE;
25+
import static io.r2dbc.postgresql.message.Format.FORMAT_BINARY;
26+
import static io.r2dbc.postgresql.message.Format.FORMAT_TEXT;
27+
import static io.r2dbc.postgresql.type.PostgresqlObjectId.LSEG;
28+
import static io.r2dbc.postgresql.type.PostgresqlObjectId.VARCHAR;
29+
import static io.r2dbc.postgresql.util.TestByteBufAllocator.TEST;
30+
import static org.assertj.core.api.Assertions.assertThat;
31+
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
32+
33+
/**
34+
* Unit tests for {@link LineSegmentCodec}.
35+
*/
36+
final class LineSegmentCodecUnitTests {
37+
38+
@Test
39+
void constructorNoByteBufAllocator() {
40+
assertThatIllegalArgumentException().isThrownBy(() -> new LineSegmentCodec(null))
41+
.withMessage("byteBufAllocator must not be null");
42+
}
43+
44+
@Test
45+
void doCanDecodeNoType() {
46+
assertThatIllegalArgumentException().isThrownBy(() -> new LineSegmentCodec(TEST).doCanDecode(null, FORMAT_BINARY))
47+
.withMessage("type must not be null");
48+
}
49+
50+
@Test
51+
void doCanDecode() {
52+
LineSegmentCodec codec = new LineSegmentCodec(TEST);
53+
54+
assertThat(codec.doCanDecode(VARCHAR, FORMAT_BINARY)).isFalse();
55+
assertThat(codec.doCanDecode(LSEG, FORMAT_TEXT)).isTrue();
56+
assertThat(codec.doCanDecode(LSEG, FORMAT_BINARY)).isTrue();
57+
}
58+
59+
@Test
60+
void doDecodeNoByteBuf() {
61+
assertThatIllegalArgumentException().isThrownBy(() -> new LineSegmentCodec(TEST).doDecode(null, LSEG, FORMAT_BINARY, LineSegment.class))
62+
.withMessage("byteBuf must not be null");
63+
}
64+
65+
@Test
66+
void doDecodeNoType() {
67+
assertThatIllegalArgumentException().isThrownBy(() -> new LineSegmentCodec(TEST).doDecode(TEST.buffer(), LSEG, FORMAT_BINARY, null))
68+
.withMessage("type must not be null");
69+
}
70+
71+
@Test
72+
void doDecodeNoFormat() {
73+
assertThatIllegalArgumentException().isThrownBy(() -> new LineSegmentCodec(TEST).doDecode(TEST.buffer(), LSEG, null, LineSegment.class))
74+
.withMessage("format must not be null");
75+
}
76+
77+
@Test
78+
void doDecode() {
79+
LineSegmentCodec codec = new LineSegmentCodec(TEST);
80+
Point point1 = Point.of(1.12, 2.12);
81+
Point point2 = Point.of(3.12, 4.12);
82+
LineSegment lineSegment = new LineSegment(point1, point2);
83+
ByteBuf lineSegmentAsBinary = TEST.buffer(codec.lengthInBytes())
84+
.writeDouble(1.12)
85+
.writeDouble(2.12)
86+
.writeDouble(3.12)
87+
.writeDouble(4.12);
88+
assertThat(codec.doDecode(lineSegmentAsBinary, LSEG, FORMAT_BINARY, LineSegment.class)).isEqualTo(lineSegment);
89+
}
90+
91+
@Test
92+
void doEncodeNoValue() {
93+
assertThatIllegalArgumentException().isThrownBy(() -> new LineSegmentCodec(TEST).doEncode(null))
94+
.withMessage("value must not be null");
95+
}
96+
97+
@Test
98+
void doEncode() {
99+
LineSegmentCodec codec = new LineSegmentCodec(TEST);
100+
ByteBuf lineSegmentAsBinary = TEST.buffer(codec.lengthInBytes())
101+
.writeDouble(1.12)
102+
.writeDouble(2.12)
103+
.writeDouble(3.12)
104+
.writeDouble(4.12);
105+
106+
ParameterAssert.assertThat(codec.doEncode(new LineSegment(Point.of(1.12, 2.12), Point.of(3.12, 4.12))))
107+
.hasFormat(FORMAT_BINARY)
108+
.hasType(LSEG.getObjectId())
109+
.hasValue(lineSegmentAsBinary);
110+
}
111+
112+
@Test
113+
void encodeNull() {
114+
ParameterAssert.assertThat(new LineSegmentCodec(TEST).encodeNull())
115+
.isEqualTo(new Parameter(FORMAT_BINARY, LSEG.getObjectId(), NULL_VALUE));
116+
}
117+
118+
}

0 commit comments

Comments
 (0)