• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
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  * A copy of the License is located at
7  *
8  *  http://aws.amazon.com/apache2.0
9  *
10  * or in the "license" file accompanying this file. This file is distributed
11  * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12  * express or implied. See the License for the specific language governing
13  * permissions and limitations under the License.
14  */
15 package software.amazon.eventstream;
16 
17 import java.io.DataOutputStream;
18 import java.io.IOException;
19 import java.nio.ByteBuffer;
20 import java.time.Instant;
21 import java.util.Arrays;
22 import java.util.Base64;
23 import java.util.Date;
24 import java.util.UUID;
25 
26 import static java.util.Objects.requireNonNull;
27 import static software.amazon.eventstream.HeaderType.TIMESTAMP;
28 import static software.amazon.eventstream.HeaderType.fromTypeId;
29 import static software.amazon.eventstream.Utils.writeBytes;
30 import static software.amazon.eventstream.Utils.writeString;
31 
32 /**
33  * A typed header value. The underlying value can be obtained by calling the
34  * appropriate getter.
35  */
36 public abstract class HeaderValue {
fromBoolean(boolean value)37     public static HeaderValue fromBoolean(boolean value) {
38         return new BooleanValue(value);
39     }
40 
fromByte(byte value)41     public static HeaderValue fromByte(byte value) {
42         return new ByteValue(value);
43     }
44 
fromShort(short value)45     public static HeaderValue fromShort(short value) {
46         return new ShortValue(value);
47     }
48 
fromInteger(int value)49     public static HeaderValue fromInteger(int value) {
50         return new IntegerValue(value);
51     }
52 
fromLong(long value)53     public static HeaderValue fromLong(long value) {
54         return new LongValue(value);
55     }
56 
fromByteArray(byte[] bytes)57     public static HeaderValue fromByteArray(byte[] bytes) {
58         return new ByteArrayValue(bytes);
59     }
60 
fromByteBuffer(ByteBuffer buf)61     public static HeaderValue fromByteBuffer(ByteBuffer buf) {
62         buf = buf.duplicate();
63         byte[] bytes = new byte[buf.remaining()];
64         buf.get(bytes);
65         return fromByteArray(bytes);
66     }
67 
fromString(String string)68     public static HeaderValue fromString(String string) {
69         return new StringValue(string);
70     }
71 
fromTimestamp(Instant value)72     public static HeaderValue fromTimestamp(Instant value) {
73         return new TimestampValue(value);
74     }
75 
fromDate(Date value)76     public static HeaderValue fromDate(Date value) {
77         return new TimestampValue(value.toInstant());
78     }
79 
fromUuid(UUID value)80     public static HeaderValue fromUuid(UUID value) {
81         return new UuidValue(value);
82     }
83 
HeaderValue()84     protected HeaderValue() {}
85 
getType()86     public abstract HeaderType getType();
87 
getBoolean()88     public boolean getBoolean() {
89         throw new IllegalStateException();
90     }
91 
getByte()92     public byte getByte() {
93         throw new IllegalStateException("Expected byte, but type was " + getType().name());
94     }
95 
getShort()96     public short getShort() {
97         throw new IllegalStateException("Expected short, but type was " + getType().name());
98     }
99 
getInteger()100     public int getInteger() {
101         throw new IllegalStateException("Expected integer, but type was " + getType().name());
102     }
103 
getLong()104     public long getLong() {
105         throw new IllegalStateException("Expected long, but type was " + getType().name());
106     }
107 
getByteArray()108     public byte[] getByteArray() {
109         throw new IllegalStateException();
110     }
111 
getByteBuffer()112     public final ByteBuffer getByteBuffer() {
113         return ByteBuffer.wrap(getByteArray());
114     }
115 
getString()116     public String getString() {
117         throw new IllegalStateException();
118     }
119 
getTimestamp()120     public Instant getTimestamp() {
121         throw new IllegalStateException("Expected timestamp, but type was " + getType().name());
122     }
123 
getDate()124     public Date getDate() {
125         return Date.from(getTimestamp());
126     }
127 
getUuid()128     public UUID getUuid() {
129         throw new IllegalStateException("Expected UUID, but type was " + getType().name());
130     }
131 
encode(DataOutputStream dos)132     void encode(DataOutputStream dos) throws IOException {
133         dos.writeByte(getType().headerTypeId);
134         encodeValue(dos);
135     }
136 
encodeValue(DataOutputStream dos)137     abstract void encodeValue(DataOutputStream dos) throws IOException;
138 
decode(ByteBuffer buf)139     static HeaderValue decode(ByteBuffer buf) {
140         HeaderType type = fromTypeId(buf.get());
141         switch (type) {
142             case TRUE:
143                 return new BooleanValue(true);
144             case FALSE:
145                 return new BooleanValue(false);
146             case BYTE:
147                 return new ByteValue(buf.get());
148             case SHORT:
149                 return new ShortValue(buf.getShort());
150             case INTEGER:
151                 return fromInteger(buf.getInt());
152             case LONG:
153                 return new LongValue(buf.getLong());
154             case BYTE_ARRAY:
155             return fromByteArray(Utils.readBytes(buf));
156             case STRING:
157             return fromString(Utils.readString(buf));
158             case TIMESTAMP:
159                 return TimestampValue.decode(buf);
160             case UUID:
161                 return UuidValue.decode(buf);
162             default:
163                 throw new IllegalStateException();
164         }
165     }
166 
167     private static final class BooleanValue extends HeaderValue {
168         private final boolean value;
169 
BooleanValue(boolean value)170         private BooleanValue(boolean value) {
171             this.value = value;
172         }
173 
174         @Override
getType()175         public HeaderType getType() {
176             if (value) {
177                 return HeaderType.TRUE;
178             } else {
179                 return HeaderType.FALSE;
180             }
181         }
182 
183         @Override
getBoolean()184         public boolean getBoolean() {
185             return value;
186         }
187 
188         @Override
encodeValue(DataOutputStream dos)189         void encodeValue(DataOutputStream dos) {}
190 
191         @Override
equals(Object o)192         public boolean equals(Object o) {
193             if (this == o) return true;
194             if (o == null || getClass() != o.getClass()) return false;
195 
196             BooleanValue that = (BooleanValue) o;
197 
198             return value == that.value;
199         }
200 
201         @Override
hashCode()202         public int hashCode() {
203             if (value) {
204                 return 1;
205             } else {
206                 return 0;
207             }
208         }
209 
210         @Override
toString()211         public String toString() {
212             return String.valueOf(value);
213         }
214     }
215 
216     private static final class ByteValue extends HeaderValue {
217         private final byte value;
218 
ByteValue(byte value)219         private ByteValue(byte value) {
220             this.value = value;
221         }
222 
223         @Override
getType()224         public HeaderType getType() {
225             return HeaderType.BYTE;
226         }
227 
228         @Override
getByte()229         public byte getByte() {
230             return value;
231         }
232 
233         @Override
encodeValue(DataOutputStream dos)234         void encodeValue(DataOutputStream dos) {}
235 
236         @Override
equals(Object o)237         public boolean equals(Object o) {
238             if (this == o) return true;
239             if (o == null || getClass() != o.getClass()) return false;
240 
241             ByteValue that = (ByteValue) o;
242 
243             return value == that.value;
244         }
245 
246         @Override
hashCode()247         public int hashCode() {
248             return (int) value;
249         }
250 
251         @Override
toString()252         public String toString() {
253             return String.valueOf(value);
254         }
255     }
256 
257     private static final class ShortValue extends HeaderValue {
258         private final short value;
259 
ShortValue(short value)260         private ShortValue(short value) {
261             this.value = value;
262         }
263 
264         @Override
getType()265         public HeaderType getType() {
266             return HeaderType.SHORT;
267         }
268 
269         @Override
getShort()270         public short getShort() {
271             return value;
272         }
273 
274         @Override
encodeValue(DataOutputStream dos)275         void encodeValue(DataOutputStream dos) {}
276 
277         @Override
equals(Object o)278         public boolean equals(Object o) {
279             if (this == o) return true;
280             if (o == null || getClass() != o.getClass()) return false;
281 
282             ShortValue that = (ShortValue) o;
283 
284             return value == that.value;
285         }
286 
287         @Override
hashCode()288         public int hashCode() {
289             return (int) value;
290         }
291 
292         @Override
toString()293         public String toString() {
294             return String.valueOf(value);
295         }
296     }
297 
298     private static final class IntegerValue extends HeaderValue {
299         private final int value;
300 
IntegerValue(int value)301         private IntegerValue(int value) {
302             this.value = value;
303         }
304 
305         @Override
getType()306         public HeaderType getType() {
307             return HeaderType.INTEGER;
308         }
309 
310         @Override
getInteger()311         public int getInteger() {
312             return value;
313         }
314 
315         @Override
encodeValue(DataOutputStream dos)316         void encodeValue(DataOutputStream dos) throws IOException {
317             dos.writeInt(value);
318         }
319 
320         @Override
equals(Object o)321         public boolean equals(Object o) {
322             if (this == o) return true;
323             if (o == null || getClass() != o.getClass()) return false;
324 
325             IntegerValue that = (IntegerValue) o;
326 
327             return value == that.value;
328         }
329 
330         @Override
hashCode()331         public int hashCode() {
332             return value;
333         }
334 
335         @Override
toString()336         public String toString() {
337             return String.valueOf(value);
338         }
339     }
340 
341     private static final class LongValue extends HeaderValue {
342         private final long value;
343 
LongValue(long value)344         private LongValue(long value) {
345             this.value = value;
346         }
347 
348         @Override
getType()349         public HeaderType getType() {
350             return HeaderType.LONG;
351         }
352 
353         @Override
getLong()354         public long getLong() {
355             return value;
356         }
357 
358         @Override
encodeValue(DataOutputStream dos)359         void encodeValue(DataOutputStream dos) throws IOException {
360             dos.writeLong(value);
361         }
362 
363         @Override
equals(Object o)364         public boolean equals(Object o) {
365             if (this == o) return true;
366             if (o == null || getClass() != o.getClass()) return false;
367 
368             LongValue longValue = (LongValue) o;
369 
370             return value == longValue.value;
371         }
372 
373         @Override
hashCode()374         public int hashCode() {
375             return (int) (value ^ (value >>> 32));
376         }
377 
378         @Override
toString()379         public String toString() {
380             return String.valueOf(value);
381         }
382     }
383 
384     private static final class ByteArrayValue extends HeaderValue {
385         private final byte[] value;
386 
ByteArrayValue(byte[] value)387         private ByteArrayValue(byte[] value) {
388             this.value = requireNonNull(value);
389         }
390 
391         @Override
getType()392         public HeaderType getType() {
393             return HeaderType.BYTE_ARRAY;
394         }
395 
396         @Override
getByteArray()397         public byte[] getByteArray() {
398             return value;
399         }
400 
401         @Override
encodeValue(DataOutputStream dos)402         void encodeValue(DataOutputStream dos) throws IOException {
403             writeBytes(dos, value);
404         }
405 
406         @Override
equals(Object o)407         public boolean equals(Object o) {
408             if (this == o) return true;
409             if (o == null || getClass() != o.getClass()) return false;
410 
411             ByteArrayValue that = (ByteArrayValue) o;
412 
413             return Arrays.equals(value, that.value);
414         }
415 
416         @Override
hashCode()417         public int hashCode() {
418             return Arrays.hashCode(value);
419         }
420 
421         @Override
toString()422         public String toString() {
423             return Base64.getEncoder().encodeToString(value);
424         }
425     }
426 
427     private static final class StringValue extends HeaderValue {
428         private final String value;
429 
StringValue(String value)430         private StringValue(String value) {
431             this.value = requireNonNull(value);
432         }
433 
434         @Override
getType()435         public HeaderType getType() {
436             return HeaderType.STRING;
437         }
438 
439         @Override
getString()440         public String getString() {
441             return value;
442         }
443 
444         @Override
encodeValue(DataOutputStream dos)445         void encodeValue(DataOutputStream dos) throws IOException {
446             writeString(dos, value);
447         }
448 
449         @Override
equals(Object o)450         public boolean equals(Object o) {
451             if (this == o) return true;
452             if (o == null || getClass() != o.getClass()) return false;
453 
454             StringValue that = (StringValue) o;
455 
456             return value.equals(that.value);
457         }
458 
459         @Override
hashCode()460         public int hashCode() {
461             return value.hashCode();
462         }
463 
464         @Override
toString()465         public String toString() {
466             return '"' + value + '"';
467         }
468     }
469 
470     private static final class TimestampValue extends HeaderValue {
471         private final Instant value;
472 
TimestampValue(Instant value)473         private TimestampValue(Instant value) {
474             this.value = requireNonNull(value);
475         }
476 
decode(ByteBuffer buf)477         static TimestampValue decode(ByteBuffer buf) {
478             long epochMillis = buf.getLong();
479             return new TimestampValue(Instant.ofEpochMilli(epochMillis));
480         }
481 
482         @Override
getType()483         public HeaderType getType() {
484             return TIMESTAMP;
485         }
486 
487         @Override
getTimestamp()488         public Instant getTimestamp() {
489             return value;
490         }
491 
492         @Override
encodeValue(DataOutputStream dos)493         void encodeValue(DataOutputStream dos) throws IOException {
494             dos.writeLong(value.toEpochMilli());
495         }
496 
497         @Override
equals(Object o)498         public boolean equals(Object o) {
499             if (this == o) return true;
500             if (o == null || getClass() != o.getClass()) return false;
501 
502             TimestampValue that = (TimestampValue) o;
503 
504             return value.equals(that.value);
505         }
506 
507         @Override
hashCode()508         public int hashCode() {
509             return value.hashCode();
510         }
511 
512         @Override
toString()513         public String toString() {
514             return value.toString();
515         }
516     }
517 
518     private static final class UuidValue extends HeaderValue {
519         private final UUID value;
520 
UuidValue(UUID value)521         private UuidValue(UUID value) {
522             this.value = requireNonNull(value);
523         }
524 
decode(ByteBuffer buf)525         static UuidValue decode(ByteBuffer buf) {
526             long msb = buf.getLong();
527             long lsb = buf.getLong();
528             return new UuidValue(new UUID(msb, lsb));
529         }
530 
531         @Override
getType()532         public HeaderType getType() {
533             return HeaderType.UUID;
534         }
535 
536         @Override
getUuid()537         public UUID getUuid() {
538             return value;
539         }
540 
541         @Override
encodeValue(DataOutputStream dos)542         void encodeValue(DataOutputStream dos) throws IOException {
543             dos.writeLong(value.getMostSignificantBits());
544             dos.writeLong(value.getLeastSignificantBits());
545         }
546 
547         @Override
equals(Object o)548         public boolean equals(Object o) {
549             if (this == o) return true;
550             if (o == null || getClass() != o.getClass()) return false;
551 
552             UuidValue uuidValue = (UuidValue) o;
553 
554             return value.equals(uuidValue.value);
555         }
556 
557         @Override
hashCode()558         public int hashCode() {
559             return value.hashCode();
560         }
561 
562         @Override
toString()563         public String toString() {
564             return value.toString();
565         }
566     }
567 }
568