/* * Copyright © 2015 Cask Data, Inc. * * 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 co.cask.cdap.data2.dataset2.lib.partitioned; import co.cask.cdap.api.common.Bytes; import co.cask.cdap.api.dataset.lib.Partitioning.FieldType; /** * Common utility methods when dealing wit partitioning field types. */ public class FieldTypes { /** * Parse a string into a value of this field type. For example, {@link FieldType#INT} delegates this * to {@link Integer#parseInt}. * @param str the string to parse */ public static <T extends Comparable> T parse(String str, FieldType type) { Comparable value; switch(type) { case STRING: value = str; break; case LONG: value = Long.parseLong(str); break; case INT: value = Integer.parseInt(str); break; default: throw new IllegalArgumentException("Unhandled field type: " + type.name()); } @SuppressWarnings("unchecked") T t = (T) value; return t; } /** * Convert a value of this field type to a byte array. * @param value the value to convert * @param <T> the Java type represented by this field type */ public static <T extends Comparable> byte[] toBytes(T value, FieldType type) { switch(type) { case STRING: if (value instanceof String) { return Bytes.toBytes((String) value); } break; case LONG: if (value instanceof Long) { // trick to preserve the ordering of the generated byte array return Bytes.toBytes(((Long) value) ^ Long.MIN_VALUE); } break; case INT: if (value instanceof Integer) { // trick to preserve the ordering of the generated byte array return Bytes.toBytes(((Integer) value) ^ Integer.MIN_VALUE); } break; default: throw new IllegalArgumentException("Unhandled field type: " + type.name()); } throw new IllegalArgumentException(String.format( "Incompatible value %s of type %s for field type %s.", value, value.getClass(), type.name())); } /** * @return the number of bytes that need to be read to deserialize a value of this field type * at the given position in the byte array. For integer and long values, this is constant, * but for strings, this is variable depending on the length of the string. */ public static int determineLengthInBytes(byte[] bytes, int offset, FieldType type) { switch(type) { case STRING: for (int i = offset; i < bytes.length; i++) { if (bytes[i] == 0) { return i - offset; } } return bytes.length - offset; case LONG: return Bytes.SIZEOF_LONG; case INT: return Bytes.SIZEOF_INT; default: throw new IllegalArgumentException("Unhandled field type: " + type.name()); } } /** * Deserialize a value of this field type, starting at given offset in the byte array, consuming * the given number of bytes. */ public static <T extends Comparable> T fromBytes(byte[] bytes, int offset, int length, FieldType type) { Comparable value; switch(type) { case STRING: value = Bytes.toString(bytes, offset, length); break; case LONG: value = Bytes.toLong(bytes, offset, length) ^ Long.MIN_VALUE; break; case INT: value = Bytes.toInt(bytes, offset, length) ^ Integer.MIN_VALUE; break; default: throw new IllegalArgumentException("Unhandled field type: " + type.name()); } @SuppressWarnings("unchecked") T t = (T) value; return t; } /** * Validate that a given value has the type that is required by this field type. */ public static boolean validateType(Comparable value, FieldType type) { switch(type) { case STRING: return value instanceof String; case LONG: return value instanceof Long; case INT: return value instanceof Integer; default: throw new IllegalArgumentException("Unhandled field type: " + type.name()); } } /** * @return the type name used by the Hive DDL to represent this field type */ public static String toHiveType(FieldType type) { switch(type) { case STRING: return "STRING"; case LONG: return "BIGINT"; case INT: return "INT"; default: throw new IllegalArgumentException("Unhandled field type: " + type.name()); } } }