package org.infinispan.query.remote.impl.indexing;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.Arrays;
import java.util.Collections;
import java.util.Set;
import org.infinispan.commons.io.UnsignedNumeric;
import org.infinispan.commons.marshall.AbstractExternalizer;
import org.infinispan.protostream.descriptors.Descriptor;
import org.infinispan.query.remote.impl.ExternalizerIds;
/**
* This is used to wrap binary values encoded with Protocol Buffers. {@link ProtobufValueWrapperFieldBridge} is used as
* a class bridge to allow indexing of the binary payload.
*
* @author anistor@redhat.com
* @since 6.0
*/
public final class ProtobufValueWrapper {
// The protobuf encoded payload
private final byte[] binary;
private int hashCode = 0;
// The Descriptor of the message (if it's a Message and not a primitive value). Transient field!
private Descriptor messageDescriptor;
public ProtobufValueWrapper(byte[] binary) {
if (binary == null) {
throw new IllegalArgumentException("argument cannot be null");
}
this.binary = binary;
}
public byte[] getBinary() {
return binary;
}
public Descriptor getMessageDescriptor() {
return messageDescriptor;
}
public void setMessageDescriptor(Descriptor messageDescriptor) {
this.messageDescriptor = messageDescriptor;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ProtobufValueWrapper that = (ProtobufValueWrapper) o;
return Arrays.equals(binary, that.binary);
}
@Override
public int hashCode() {
if (hashCode == 0) {
hashCode = Arrays.hashCode(binary);
}
return hashCode;
}
@Override
public String toString() {
// Render only max 40 bytes
int len = Math.min(binary.length, 40);
StringBuilder sb = new StringBuilder(50 + 3 * len);
sb.append("ProtobufValueWrapper(length=").append(binary.length).append(", binary=[");
for (int i = 0; i < len; i++) {
if (i != 0) {
sb.append(' ');
}
sb.append(String.format("%02X", binary[i] & 0xff));
}
if (len < binary.length) {
sb.append("...");
}
sb.append("])");
return sb.toString();
}
public static final class Externalizer extends AbstractExternalizer<ProtobufValueWrapper> {
@Override
public void writeObject(ObjectOutput output, ProtobufValueWrapper protobufValueWrapper) throws IOException {
UnsignedNumeric.writeUnsignedInt(output, protobufValueWrapper.binary.length);
output.write(protobufValueWrapper.binary);
}
@Override
public ProtobufValueWrapper readObject(ObjectInput input) throws IOException {
int length = UnsignedNumeric.readUnsignedInt(input);
byte[] binary = new byte[length];
input.readFully(binary);
return new ProtobufValueWrapper(binary);
}
@Override
public Integer getId() {
return ExternalizerIds.PROTOBUF_VALUE_WRAPPER;
}
@Override
public Set<Class<? extends ProtobufValueWrapper>> getTypeClasses() {
return Collections.singleton(ProtobufValueWrapper.class);
}
}
}