/*
* Agiato: A simple no frill Cassandra API
* Author: Pranab Ghosh
*
* 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 agiato.cassandra.data;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.cassandra.thrift.Column;
import org.apache.cassandra.thrift.ColumnOrSuperColumn;
/**
* byte encoding decoding
* @author pranab
*/
public class Util {
public static final String ENCODING = "utf-8";
/**
* byte array from string
* @param value
* @return
* @throws IOException
*/
public static byte[] getBytesFromString(String value) throws IOException{
return value.getBytes(Util.ENCODING);
}
/**
* ByteBuffer from String
* @param value
* @return
* @throws IOException
*/
public static ByteBuffer getByteBufferFromString(String value) throws IOException{
return ByteBuffer.wrap(value.getBytes(Util.ENCODING));
}
/**
* ByteBuffer from byte array
* @param data
* @return
* @throws IOException
*/
public static ByteBuffer getByteBufferFromBytes(byte[] data) throws IOException{
return ByteBuffer.wrap(data);
}
/**
* byte array from long
* @param value
* @return
* @throws IOException
*/
public static byte[] getBytesFromLong(long value) throws IOException{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
dos.writeLong(value);
dos.flush();
return bos.toByteArray();
}
/**
* byte array from long
* @param value
* @return
* @throws IOException
*/
public static byte[] getBytesFromInt(int value) throws IOException{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
dos.writeInt(value);
dos.flush();
return bos.toByteArray();
}
/**
* byte array from double
* @param value
* @return
* @throws IOException
*/
public static byte[] getBytesFromDouble(double value) throws IOException{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
dos.writeDouble(value);
dos.flush();
return bos.toByteArray();
}
/**
* byte array from list
* @param values
* @return
* @throws IOException
*/
public static byte[] getBytesFromList(List<Object> values) throws IOException{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
for (Object value : values){
if (value instanceof String)
dos.writeUTF((String)value);
else if (value instanceof Long)
dos.writeLong((Long)value);
else if (value instanceof Integer)
dos.writeInt((Integer)value);
else if (value instanceof Double)
dos.writeDouble((Long)value);
}
dos.flush();
return bos.toByteArray();
}
/**
* ByteBuffer from list
* @param values
* @return
* @throws IOException
*/
public static ByteBuffer getByteBufferFromList(List<Object> values) throws IOException{
return ByteBuffer.wrap(getBytesFromList(values));
}
/**
* ByteBuffer from long
* @param value
* @return
* @throws IOException
*/
public static ByteBuffer getByteBufferFromLong(long value) throws IOException{
return ByteBuffer.wrap(getBytesFromLong(value));
}
/**
* ByteBuffer from long
* @param value
* @return
* @throws IOException
*/
public static ByteBuffer getByteBufferFromInt(int value) throws IOException{
return ByteBuffer.wrap(getBytesFromInt(value));
}
/**
* ByteBuffer from double
* @param value
* @return
* @throws IOException
*/
public static ByteBuffer getByteBufferFromDouble(double value) throws IOException{
return ByteBuffer.wrap(getBytesFromDouble(value));
}
/**
* byte array from UUID
* @param uuid
* @return
*/
public static byte[] getBytesFromUUID(java.util.UUID uuid) {
long msb = uuid.getMostSignificantBits();
long lsb = uuid.getLeastSignificantBits();
byte[] buffer = new byte[16];
for (int i = 0; i < 8; i++) {
buffer[i] = (byte) (msb >>> 8 * (7 - i));
}
for (int i = 8; i < 16; i++) {
buffer[i] = (byte) (lsb >>> 8 * (7 - i));
}
return buffer;
}
/**
* ByteBuffer from UUID
* @param uuid
* @return
*/
public static ByteBuffer getByteBufferFromUUID(java.util.UUID uuid) {
return ByteBuffer.wrap(getBytesFromUUID(uuid));
}
/**
* double from ByteBuffer
* @param data
* @return
* @throws IOException
*/
public static double getDoubleFromByteBuffer(ByteBuffer data) throws IOException{
return getDoubleFromBytes(data.array());
}
/**
* string from byte array
* @param data
* @return
* @throws IOException
*/
public static String getStringFromBytes(byte[] data) throws IOException{
return new String(data, ENCODING);
}
/**
* string from ByteBuffer
* @param data
* @return
* @throws IOException
*/
public static String getStringFromByteBuffer(ByteBuffer data) throws IOException{
return new String(data.array(), ENCODING);
}
/**
* long from byte array
* @param data
* @return
* @throws IOException
*/
public static Long getLongFromBytes(byte[] data) throws IOException{
ByteArrayInputStream bis = new ByteArrayInputStream(data);
DataInputStream dis = new DataInputStream(bis);
Long value = dis.readLong();
return value;
}
/**
* long from byte array
* @param data
* @return
* @throws IOException
*/
public static Integer getIntFromBytes(byte[] data) throws IOException{
ByteArrayInputStream bis = new ByteArrayInputStream(data);
DataInputStream dis = new DataInputStream(bis);
Integer value = dis.readInt();
return value;
}
/**
* double from byte array
* @param data
* @return
* @throws IOException
*/
public static Double getDoubleFromBytes(byte[] data) throws IOException{
ByteArrayInputStream bis = new ByteArrayInputStream(data);
DataInputStream dis = new DataInputStream(bis);
Double value = dis.readDouble();
return value;
}
/**
* long from ByteBuffer
* @param data
* @return
* @throws IOException
*/
public static Long getLongFromByteBuffer(ByteBuffer data) throws IOException{
return getLongFromBytes(data.array());
}
/**
* int from ByteBuffer
* @param data
* @return
* @throws IOException
*/
public static Integer getIntFromByteBuffer(ByteBuffer data) throws IOException{
return getIntFromBytes(data.array());
}
/**
* list from byte array
* @param data
* @param classes
* @return
* @throws IOException
*/
public static List<Object> getListFromBytes(byte[] data, List<Class> classes) throws IOException{
List<Object> values = new ArrayList<Object>();
ByteArrayInputStream bis = new ByteArrayInputStream(data);
DataInputStream dis = new DataInputStream(bis);
for (Class cl : classes){
Object value = null;
if (cl == String.class)
value = dis.readUTF();
else if (cl == Long.class)
value = dis.readLong();
else if (cl == Integer.class)
value = dis.readInt();
else if (cl == Double.class)
value = dis.readDouble();
if (null != value)
values.add(value);
}
dis.close();
return values;
}
/**
* list from ByteBuffer
* @param data
* @param classes
* @return
* @throws IOException
*/
public static List<Object> getListFromByteBuffer(ByteBuffer data, List<Class> classes) throws IOException{
return getListFromBytes(data.array(), classes);
}
/**
* time UUID
* @return
*/
public static java.util.UUID getTimeUUID(){
return java.util.UUID.fromString(new com.eaio.uuid.UUID().toString());
}
/**
* UUID from byte array
* @param uuid
* @return
*/
public static java.util.UUID getUUIDFromBytes( byte[] uuid ){
long msb = 0;
long lsb = 0;
assert uuid.length == 16;
for (int i=0; i<8; i++)
msb = (msb << 8) | (uuid[i] & 0xff);
for (int i=8; i<16; i++)
lsb = (lsb << 8) | (uuid[i] & 0xff);
com.eaio.uuid.UUID u = new com.eaio.uuid.UUID(msb,lsb);
return java.util.UUID.fromString(u.toString());
}
/**
* UUID from ByteBuffer
* @param uuid
* @return
*/
public static java.util.UUID getUUIDFromByteBuffer(ByteBuffer uuid ){
return getUUIDFromBytes(uuid.array());
}
/**
* map from list of columns
* @param cList
* @return
* @throws Exception
*/
public static Map<String, String> getColumns( List<ColumnOrSuperColumn> cList) throws Exception{
Map<String, String> columns = new HashMap<String, String>();
for (ColumnOrSuperColumn colSup : cList){
Column col = colSup.getColumn();
if (null != col){
String name = getStringFromBytes(col.getName());
String value = getStringFromBytes(col.getValue());
columns.put(name, value);
}
}
return columns;
}
/**
* empty ByteBuffer
* @return
*/
public static ByteBuffer getEmptyByteBuffer(){
byte[] data = {};
return ByteBuffer.wrap(data);
}
/**
* byte arrayfrom primitives
* @param obj
* @return
* @throws IOException
*/
public static byte[] getBytesFromObject(Object obj) throws IOException {
byte[] bytes = null;
if (obj instanceof String) {
bytes = getBytesFromString((String)obj);
} else if (obj instanceof Long) {
bytes = getBytesFromLong((Long)obj);
} else if (obj instanceof Integer) {
bytes = getBytesFromInt((Integer)obj);
} else if (obj instanceof Double) {
bytes = getBytesFromDouble((Double)obj);
} else if (obj instanceof List<?>) {
StringBuilder stBld = new StringBuilder("[");
for (Object elem : (List<?>)obj) {
stBld.append(elem).append(",");
}
stBld.deleteCharAt(stBld.length()-1);
stBld.append("]");
bytes = getBytesFromString(stBld.toString());
} else if (obj instanceof Map<?, ?>) {
StringBuilder stBld = new StringBuilder("{");
Map<?,?> map = (Map<?,?>)obj;
for (Object elem : map.entrySet()) {
Map.Entry<?,?> entry = (Map.Entry<?,?>)elem;
stBld.append(entry.getKey()).append(":").append(entry.getValue());
}
stBld.deleteCharAt(stBld.length()-1);
stBld.append("}");
bytes = getBytesFromString(stBld.toString());
}
return bytes;
}
/**
* @param obj
* @return
* @throws IOException
*/
public static ByteBuffer getByteBufferFromObject(Object obj) throws IOException {
return ByteBuffer.wrap(getBytesFromObject(obj));
}
/**
* @param byteBuffer
* @return
*/
public static byte[] getBytesFromByteBuffer(ByteBuffer byteBuffer) {
byte[] bytes = new byte[byteBuffer.remaining()];
byteBuffer.get(bytes, 0, byteBuffer.remaining());
return bytes;
}
/**
* @param value
* @param protoValue
* @return
* @throws IOException
*/
public static Object getObjectFromBytes(byte[] value, Object protoValue) throws IOException {
Object typedVal = null;
if (protoValue instanceof Integer) {
typedVal = getIntFromBytes(value);
} else if (protoValue instanceof Long) {
typedVal = getLongFromBytes(value);
} else if (protoValue instanceof Double) {
typedVal = getDoubleFromBytes(value);
} else if (protoValue instanceof String) {
typedVal = getStringFromBytes(value);
}
return typedVal;
}
/**
* makes composite column name or row key
* @param bytesList
* @return
*/
public static byte[] encodeComposite(List<byte[]> bytesList){
byte[] encBytes;
if (bytesList.size() == 1) {
encBytes = bytesList.get(0);
} else {
encBytes = encodeCompositeAlways( bytesList);
}
return encBytes;
}
/**
* makes composite column name or row key
* @param bytesList
* @return
*/
public static byte[] encodeCompositeAlways(List<byte[]> bytesList){
byte[] encBytes;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
for (byte[] bytes : bytesList){
//length
bos.write( (byte) ((bytes.length >> 8 ) & 0xFF)) ;
bos.write( (byte) (bytes.length & 0xFF)) ;
//content
for (int j=0;j<bytes.length;j++){
bos.write( bytes[j] & 0xFF) ;
}
//sentinel
bos.write((byte)0);
}
encBytes = bos.toByteArray();
return encBytes;
}
/**
* desrializes encoded composite key
* @param encBytes
* @return
* @throws IOException
*/
public static List<byte[]> dcodeComposite(byte[] encBytes) throws IOException {
List<byte[]> bytesList = new ArrayList<byte[]>();
int cur = 0;
int elemLen = 0;
byte[] elemBytes = null;
//System.out.println("encBytes length:" + encBytes.length);
int sentinel = 0;
int actualLen;
ByteArrayInputStream bis = new ByteArrayInputStream(encBytes);
while (true) {
elemLen = bis.read() << 8;
elemLen = elemLen | bis.read();
elemBytes = new byte[elemLen];
//System.out.println("next elemLen:" + elemLen);
actualLen = bis.read(elemBytes, 0, elemLen);
if (actualLen < elemLen ) {
throw new IllegalArgumentException("can not decode composite");
}
bytesList.add(elemBytes);
sentinel = bis.read();
if (bis.available() == 0) {
break;
}
}
bis.close();
return bytesList;
}
}