blob: ac94f2a307bb9283248d60e5d5f8901777cddd32 [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.pirk.inputformat.hadoop;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.List;
import org.apache.hadoop.io.ArrayWritable;
import org.apache.hadoop.io.BytesWritable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* ArrayWritable class with ByteWritable entries
*
*/
public class BytesArrayWritable extends ArrayWritable
{
private static final Logger logger = LoggerFactory.getLogger(BytesArrayWritable.class);
public BytesArrayWritable()
{
super(BytesWritable.class);
}
/**
* Constructor for use when underlying array will be BytesWritable representations of byte[]
*/
public BytesArrayWritable(byte[][] elements)
{
super(BytesWritable.class);
BytesWritable[] bwElements = new BytesWritable[elements.length];
for (int i = 0; i < elements.length; i++)
{
bwElements[i] = new BytesWritable(elements[i]);
}
set(bwElements);
}
/**
* Constructor for use when underlying array will be ByteWritable representations of BigInteger objects
*/
public BytesArrayWritable(List<BigInteger> elements)
{
super(BytesWritable.class);
BytesWritable[] bwElements = new BytesWritable[elements.size()];
for (int i = 0; i < elements.size(); i++)
{
byte[] bytes = elements.get(i).toByteArray();
bwElements[i] = trim(bytes);
}
set(bwElements);
}
/**
* Returns the number of elements in the underlying array
*/
public int size()
{
return this.get().length;
}
/**
* Return the ith element from the underlying array
* <p>
* Assumes that the underlying array consists of BytesWritable representations of BigInteger objects
* <p>
* Assumes that the underlying BigIntegers are unsigned, but have been stripped of zero padding (and hence the sign bit) -- must add it back in
*
*/
public BigInteger getBigInteger(int i) throws IOException
{
BytesWritable element = (BytesWritable) this.get()[i];
return new BigInteger(pad(element.getBytes()));
}
/**
* Return the ith element as a BytesWritable
*
*/
public BytesWritable get(int i)
{
return (BytesWritable) this.get()[i];
}
/**
* Return the ith element as a byte array
*
*/
public byte[] getBytes(int i)
{
return ((BytesWritable) this.get()[i]).getBytes();
}
/**
* Return the ith element as an int
*
*/
public int getByteAsInt(int i)
{
int retVal = 0;
byte[] elementByteArray = this.get(i).getBytes();
if (elementByteArray.length > 0)
{
retVal = elementByteArray[0] & 0xFF;
}
return retVal;
}
// Removes zero padding at the beginning of the byte array - assumes
// big endian ordering
private BytesWritable trim(byte[] bytes)
{
byte[] trimmedBytes = bytes;
if (bytes[0] == 0)
{
trimmedBytes = Arrays.copyOfRange(bytes, 1, bytes.length);
}
return new BytesWritable(trimmedBytes);
}
// Adds back the zero padding at the beginning of the byte array -
// assumes big endian ordering -- will not change value
private byte[] pad(byte[] bytes) throws IOException
{
byte[] zeroByte = new byte[] {0};
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
outputStream.write(zeroByte);
outputStream.write(bytes);
return outputStream.toByteArray();
}
}