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