package com.twitter.elephantbird.util;
import java.util.List;
import com.google.protobuf.DescriptorProtos;
import com.google.protobuf.DescriptorProtos.FieldDescriptorProto.Type;
import com.google.protobuf.DescriptorProtos.FieldDescriptorProto.Label;
import com.google.protobuf.Descriptors;
import com.google.protobuf.DynamicMessage;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.Message;
/**
* Metadata stored with columnar storage like Hive's RCFile <p>
*
* This is a {@link DynamicMessage} equivalent of following protobuf : <pre>
*
* message ColumnarMetadata {
* optional string classname = 1; // FYI only, not used.
* repeated int32 fieldId = 2; // list of field ids stored
* optional int32 nesting = 3 [default = 0]; // when nesting is used
* };
* </pre>
*/
public class ColumnarMetadata {
private final Message message;
// use newInstance() to create a new message
private ColumnarMetadata(Message message) {
this.message = message;
}
public Message getMessage() {
return message;
}
public String getClassname() {
return (String) message.getField(classnameDesc);
}
public int getNesting() {
return (Integer) message.getField(nestingDesc);
}
public int getFieldId(int index) {
return getFieldIdList().get(index);
}
public List<Integer> getFieldIdList() {
return (List<Integer>) message.getField(fieldIdDesc);
}
public static ColumnarMetadata newInstance(String classname, List<Integer> fieldIdList) {
return newInstance(classname, fieldIdList, 0);
}
public static ColumnarMetadata newInstance(String classname, List<Integer> fieldIdList, int nesting) {
return new ColumnarMetadata(
DynamicMessage.newBuilder(messageDescriptor)
.setField(classnameDesc, classname)
.setField(fieldIdDesc, fieldIdList)
.setField(nestingDesc, nesting)
.build());
}
public static ColumnarMetadata parseFrom(byte[] messageBuffer)
throws InvalidProtocolBufferException {
return new ColumnarMetadata(
DynamicMessage.newBuilder(messageDescriptor)
.mergeFrom(messageBuffer)
.build());
}
private static final Descriptors.Descriptor messageDescriptor;
private static final Descriptors.FieldDescriptor classnameDesc;
private static final Descriptors.FieldDescriptor fieldIdDesc;
private static final Descriptors.FieldDescriptor nestingDesc;
static {
// initialize messageDescriptor and the three field descriptors
DescriptorProtos.FieldDescriptorProto classname =
DescriptorProtos.FieldDescriptorProto.newBuilder()
.setName("classname")
.setNumber(1)
.setType(Type.TYPE_STRING)
.setLabel(Label.LABEL_OPTIONAL)
.build();
DescriptorProtos.FieldDescriptorProto fieldId =
DescriptorProtos.FieldDescriptorProto.newBuilder()
.setName("fieldId")
.setNumber(2)
.setType(Type.TYPE_INT32)
.setLabel(Label.LABEL_REPEATED)
.build();
DescriptorProtos.FieldDescriptorProto nesting =
DescriptorProtos.FieldDescriptorProto.newBuilder()
.setName("nesting")
.setNumber(3)
.setType(Type.TYPE_INT32)
.setLabel(Label.LABEL_OPTIONAL)
.setDefaultValue("0")
.build();
try {
messageDescriptor = Protobufs.makeMessageDescriptor(
DescriptorProtos.DescriptorProto.newBuilder()
.setName("ColumnarMetadata")
.addField(classname)
.addField(fieldId)
.addField(nesting)
.build());
} catch (Descriptors.DescriptorValidationException e) {
throw new RuntimeException(e);
}
classnameDesc = messageDescriptor.findFieldByName("classname");
fieldIdDesc = messageDescriptor.findFieldByName("fieldId");
nestingDesc = messageDescriptor.findFieldByName("nesting");
}
}