blob: 9d6ba5e084a4fbfb8959e64154c7fc753beed024 [file] [log] [blame]
/* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.pig.backend.hadoop.accumulo;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Map;
import org.apache.accumulo.core.Constants;
import org.apache.pig.LoadStoreCaster;
import org.apache.pig.ResourceSchema.ResourceFieldSchema;
import org.apache.pig.backend.executionengine.ExecException;
import org.apache.pig.data.DataBag;
import org.apache.pig.data.DataByteArray;
import org.apache.pig.data.Tuple;
import org.joda.time.DateTime;
import com.google.common.base.Preconditions;
/**
* A LoadStoreCaster implementation which stores most type implementations as
* bytes generated from the toString representation with a UTF8 Charset. Pulled
* some implementations from the Accumulo Lexicoder implementations in 1.6.0.
*/
public class AccumuloBinaryConverter implements LoadStoreCaster {
private static final int SIZE_OF_INT = Integer.SIZE / Byte.SIZE;
private static final int SIZE_OF_LONG = Long.SIZE / Byte.SIZE;
/**
* NOT IMPLEMENTED
*/
@Override
public DataBag bytesToBag(byte[] b, ResourceFieldSchema fieldSchema)
throws IOException {
throw new ExecException("Can't generate DataBags from byte[]");
}
@Override
public BigDecimal bytesToBigDecimal(byte[] b) throws IOException {
throw new ExecException("Can't generate a BigInteger from byte[]");
}
@Override
public BigInteger bytesToBigInteger(byte[] b) throws IOException {
// Taken from Accumulo's BigIntegerLexicoder in 1.6.0
DataInputStream dis = new DataInputStream(new ByteArrayInputStream(b));
int len = dis.readInt();
len = len ^ 0x80000000;
len = Math.abs(len);
byte[] bytes = new byte[len];
dis.readFully(bytes);
bytes[0] = (byte) (0x80 ^ bytes[0]);
return new BigInteger(bytes);
}
@Override
public Boolean bytesToBoolean(byte[] b) throws IOException {
Preconditions.checkArgument(1 == b.length);
return b[0] == (byte) 1;
}
@Override
public String bytesToCharArray(byte[] b) throws IOException {
return new String(b, Constants.UTF8);
}
/**
* NOT IMPLEMENTED
*/
@Override
public DateTime bytesToDateTime(byte[] b) throws IOException {
String s = new String(b, Constants.UTF8);
return DateTime.parse(s);
}
@Override
public Double bytesToDouble(byte[] b) throws IOException {
return Double.longBitsToDouble(bytesToLong(b));
}
@Override
public Float bytesToFloat(byte[] b) throws IOException {
return Float.intBitsToFloat(bytesToInteger(b));
}
@Override
public Integer bytesToInteger(byte[] b) throws IOException {
Preconditions.checkArgument(b.length == SIZE_OF_INT);
int n = 0;
for (int i = 0; i < b.length; i++) {
n <<= 8;
n ^= b[i] & 0xFF;
}
return n;
}
@Override
public Long bytesToLong(byte[] b) throws IOException {
Preconditions.checkArgument(b.length == SIZE_OF_LONG);
long l = 0;
for (int i = 0; i < b.length; i++) {
l <<= 8;
l ^= b[i] & 0xFF;
}
return l;
}
/**
* NOT IMPLEMENTED
*/
@Override
public Map<String, Object> bytesToMap(byte[] b,
ResourceFieldSchema fieldSchema) throws IOException {
throw new ExecException("Can't generate Map from byte[]");
}
/**
* NOT IMPLEMENTED
*/
@Override
public Tuple bytesToTuple(byte[] b, ResourceFieldSchema fieldSchema)
throws IOException {
throw new ExecException("Can't generate a Tuple from byte[]");
}
/**
* Not implemented!
*/
@Override
public byte[] toBytes(BigDecimal bd) throws IOException {
throw new IOException("Can't generate bytes from BigDecimal");
}
@Override
public byte[] toBytes(BigInteger bi) throws IOException {
// Taken from Accumulo's BigIntegerLexicoder in 1.6.0
byte[] bytes = bi.toByteArray();
byte[] ret = new byte[4 + bytes.length];
DataOutputStream dos = new DataOutputStream(
new FixedByteArrayOutputStream(ret));
// flip the sign bit
bytes[0] = (byte) (0x80 ^ bytes[0]);
int len = bytes.length;
if (bi.signum() < 0)
len = -len;
len = len ^ 0x80000000;
try {
dos.writeInt(len);
dos.write(bytes);
} finally {
dos.close();
}
return ret;
}
@Override
public byte[] toBytes(Boolean b) throws IOException {
return new byte[] { b ? (byte) 1 : (byte) 0 };
}
/**
* NOT IMPLEMENTED
*/
@Override
public byte[] toBytes(DataBag bag) throws IOException {
throw new ExecException("Cant' generate bytes from DataBag");
}
@Override
public byte[] toBytes(DataByteArray a) throws IOException {
return a.get();
}
@Override
public byte[] toBytes(DateTime dt) throws IOException {
return dt.toString().getBytes(Constants.UTF8);
}
@Override
public byte[] toBytes(Double d) throws IOException {
return toBytes(Double.doubleToRawLongBits(d));
}
@Override
public byte[] toBytes(Float f) throws IOException {
return toBytes(Float.floatToRawIntBits(f));
}
@Override
public byte[] toBytes(Integer val) throws IOException {
int intVal = val.intValue();
byte[] b = new byte[4];
for (int i = 3; i > 0; i--) {
b[i] = (byte) intVal;
intVal >>>= 8;
}
b[0] = (byte) intVal;
return b;
}
@Override
public byte[] toBytes(Long val) throws IOException {
long longVal = val.longValue();
byte[] b = new byte[8];
for (int i = 7; i > 0; i--) {
b[i] = (byte) longVal;
longVal >>>= 8;
}
b[0] = (byte) longVal;
return b;
}
/**
* NOT IMPLEMENTED
*/
@Override
public byte[] toBytes(Map<String, Object> m) throws IOException {
throw new IOException("Can't generate bytes from Map");
}
@Override
public byte[] toBytes(String s) throws IOException {
return s.getBytes(Constants.UTF8);
}
/**
* NOT IMPLEMENTED
*/
@Override
public byte[] toBytes(Tuple t) throws IOException {
throw new IOException("Can't generate bytes from Tuple");
}
}