![JAR search and dependency download from the Maven repository](/logo.png)
co.cask.cdap.common.stream.StreamEventDataCodec Maven / Gradle / Ivy
/*
* Copyright © 2014-2015 Cask Data, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package co.cask.cdap.common.stream;
import co.cask.cdap.api.data.schema.Schema;
import co.cask.cdap.api.data.schema.UnsupportedTypeException;
import co.cask.cdap.api.stream.StreamEventData;
import co.cask.cdap.common.io.Decoder;
import co.cask.cdap.common.io.Encoder;
import co.cask.cdap.internal.io.ReflectionSchemaGenerator;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Map;
/**
* Utility class for encode/decode {@link co.cask.cdap.api.stream.StreamEventData}.
*
* The StreamEventData is encoded using Avro binary encoding, with the schema:
*
*
* {
* "type": "record",
* "name": "StreamEvent",
* "fields" : [
* {"name": "body", "type": "bytes"},
* {"name": "headers", "type": {"type": "map", "values": ["string", "null"]}}
* ]
* }
*
*
*/
public final class StreamEventDataCodec {
public static final Schema STREAM_DATA_SCHEMA;
static {
Schema schema;
try {
schema = new ReflectionSchemaGenerator().generate(StreamEventData.class);
} catch (UnsupportedTypeException e) {
// Never happen, as schema can always be generated from StreamEventData.
schema = null;
}
STREAM_DATA_SCHEMA = schema;
}
/**
* Encodes the given {@link StreamEventData} using the {@link Encoder}.
*
* @param data The data to encode
* @param encoder The encoder
* @throws IOException If there is any IO error during encoding.
*/
public static void encode(StreamEventData data, Encoder encoder) throws IOException {
// The schema is sorted by name, hence it is {body, header}.
// Writes the body
encoder.writeBytes(data.getBody());
// Writes the headers
Map headers = data.getHeaders();
encoder.writeInt(headers.size());
for (Map.Entry entry : headers.entrySet()) {
String value = entry.getValue();
encoder.writeString(entry.getKey())
.writeInt(value == null ? 1 : 0)
.writeString(entry.getValue());
}
if (!headers.isEmpty()) {
encoder.writeInt(0);
}
}
/**
* Decodes from the given {@link Decoder} to reconstruct a {@link StreamEventData}.
*
* @param decoder the decoder to read data from
* @return A new instance of {@link co.cask.cdap.api.stream.StreamEventData}.
* @throws IOException If there is any IO error during decoding.
*/
public static StreamEventData decode(Decoder decoder) throws IOException {
return decode(decoder, ImmutableMap.of());
}
/**
* Decodes from the given {@link Decoder} to reconstruct a {@link StreamEventData}.
* The set of headers provided is used as the default set of headers.
*
* @param decoder the decoder to read data from
* @param defaultHeaders A map of headers available by default.
* @return A new instance of {@link co.cask.cdap.api.stream.StreamEventData}.
* @throws IOException If there is any IO error during decoding.
*/
public static StreamEventData decode(Decoder decoder, Map defaultHeaders) throws IOException {
// Reads the body
ByteBuffer body = decoder.readBytes();
// Reads the headers
int len = decoder.readInt();
// A special optimization for the case where there is no event header.
if (len == 0) {
return new StreamEventData(defaultHeaders, body);
}
Map headers = defaultHeaders.isEmpty() ? Maps.newHashMap()
: Maps.newHashMap(defaultHeaders);
do {
for (int i = 0; i < len; i++) {
String key = decoder.readString();
String value = decoder.readInt() == 0 ? decoder.readString() : (String) decoder.readNull();
headers.put(key, value);
}
len = decoder.readInt();
} while (len != 0);
return new StreamEventData(headers, body);
}
/**
* Skips an encoded {@link co.cask.cdap.api.stream.StreamEventData}.
*
* @param decoder Decoder to skip data from.
* @throws IOException If there is any IO error during decoding.
*/
public static void skip(Decoder decoder) throws IOException {
// Skips the body
decoder.skipBytes();
// Skips the headers
int len = decoder.readInt();
while (len != 0) {
for (int i = 0; i < len; i++) {
decoder.skipString();
if (decoder.readInt() == 0) {
decoder.skipString();
} else {
decoder.readNull();
}
}
len = decoder.readInt();
}
}
private StreamEventDataCodec() {
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy