1
1
package com .fasterxml .jackson .dataformat .avro .interop .annotations ;
2
2
3
3
import java .io .IOException ;
4
- import java .util .ArrayList ;
5
- import java .util .Arrays ;
6
- import java .util .HashMap ;
7
- import java .util .Map ;
4
+ import java .nio .ByteBuffer ;
5
+ import java .util .*;
8
6
7
+ import org .apache .avro .SchemaBuilder ;
9
8
import org .apache .avro .io .Decoder ;
10
9
import org .apache .avro .io .Encoder ;
11
10
import org .apache .avro .reflect .AvroEncode ;
@@ -53,13 +52,16 @@ static class CustomComponent {
53
52
@ Nullable
54
53
public Long longValue ;
55
54
55
+ @ AvroEncode (using = UuidAsBytesAvroEncoding .class )
56
+ private UUID uuidValue ;
57
+
56
58
protected CustomComponent () { }
57
59
}
58
60
59
61
public static class ApacheImplEncoding extends CustomEncoding <CustomComponent > {
60
62
61
63
public ApacheImplEncoding () {
62
- schema = ApacheAvroInteropUtil .getJacksonSchema (CustomComponent .class );
64
+ schema = ApacheAvroInteropUtil .getApacheSchema (CustomComponent .class );
63
65
}
64
66
65
67
@ Override
@@ -74,8 +76,67 @@ protected CustomComponent read(Object reuse, Decoder in) throws IOException {
74
76
75
77
}
76
78
77
- protected Wrapper wrapper ;
79
+ public static class UuidAsBytesAvroEncoding extends CustomEncoding <UUID > {
80
+ public static byte [] asByteArray (UUID uuid ) {
81
+ long msb = uuid .getMostSignificantBits ();
82
+ long lsb = uuid .getLeastSignificantBits ();
83
+ byte [] buffer = new byte [16 ];
84
+ for (int i = 0 ; i < 8 ; i ++) {
85
+ buffer [i ] = (byte ) (msb >>> 8 * (7 - i ));
86
+ }
87
+ for (int i = 8 ; i < 16 ; i ++) {
88
+ buffer [i ] = (byte ) (lsb >>> 8 * (7 - i ));
89
+ }
90
+ return buffer ;
91
+ }
78
92
93
+ public static UUID toUUID (byte [] byteArray ) {
94
+ long msb = 0 ;
95
+ long lsb = 0 ;
96
+ for (int i = 0 ; i < 8 ; i ++) { msb = (msb << 8 ) | (byteArray [i ] & 0xff ); }
97
+ for (int i = 8 ; i < 16 ; i ++) { lsb = (lsb << 8 ) | (byteArray [i ] & 0xff ); }
98
+ return new UUID (msb , lsb );
99
+ }
100
+
101
+ public UuidAsBytesAvroEncoding () {
102
+ this .schema = SchemaBuilder .unionOf ().nullType ().and ().bytesBuilder ().endBytes ().endUnion ();
103
+ }
104
+
105
+ @ Override
106
+ public void write (Object datum , Encoder encoder ) throws IOException {
107
+ if (datum == null ) {
108
+ encoder .writeIndex (0 );
109
+ encoder .writeNull ();
110
+ return ;
111
+ }
112
+ encoder .writeIndex (1 );
113
+ encoder .writeBytes (asByteArray ((UUID ) datum ));
114
+ }
115
+
116
+ @ Override
117
+ public UUID read (Object datum , Decoder decoder ) throws IOException {
118
+ try {
119
+ // get index in union
120
+ int index = decoder .readIndex ();
121
+ if (index == 1 ) {
122
+ // read in 16 bytes of data
123
+ ByteBuffer b = ByteBuffer .allocate (16 );
124
+ decoder .readBytes (b );
125
+ // convert
126
+ UUID uuid = toUUID (b .array ());
127
+ return uuid ;
128
+ } else {
129
+ decoder .readNull ();
130
+ // no uuid present
131
+ return null ;
132
+ }
133
+ } catch (Exception exception ) {
134
+ throw new IllegalStateException ("Could not decode bytes into UUID" , exception );
135
+ }
136
+ }
137
+ }
138
+
139
+ protected Wrapper wrapper ;
79
140
protected Wrapper result ;
80
141
81
142
@ Before
@@ -92,6 +153,7 @@ public void setup() throws IOException {
92
153
mv .put ("cats" , new ArrayList <Integer >());
93
154
mv .put ("dogs" , new ArrayList <>(Arrays .asList (-1234 , 56 , 6767 , 54134 , 57 , 86 )));
94
155
wrapper .component .stringValue = "Hello World!" ;
156
+ wrapper .component .uuidValue = UUID .randomUUID ();
95
157
96
158
CustomComponent cc = new CustomComponent ();
97
159
cc .byteValue = (byte ) 42 ;
@@ -100,8 +162,8 @@ public void setup() throws IOException {
100
162
cc .doubleValue = Double .POSITIVE_INFINITY ;
101
163
cc .longValue = Long .MAX_VALUE ;
102
164
cc .stringValue = "Nested Hello World!" ;
165
+ cc .uuidValue = UUID .randomUUID ();
103
166
wrapper .component .nestedRecordValue = cc ;
104
-
105
167
//
106
168
result = roundTrip (wrapper );
107
169
}
@@ -136,4 +198,13 @@ public void testIntegerValue() {
136
198
assertThat (result .component .intValue ).isEqualTo (wrapper .component .intValue );
137
199
}
138
200
201
+ @ Test
202
+ public void testNestedUuidValue () {
203
+ assertThat (result .component .nestedRecordValue .uuidValue ).isEqualTo (wrapper .component .nestedRecordValue .uuidValue );
204
+ }
205
+
206
+ @ Test
207
+ public void testUuidValue () {
208
+ assertThat (result .component .uuidValue ).isEqualTo (wrapper .component .uuidValue );
209
+ }
139
210
}
0 commit comments