gt:                 Double valArray[] = new Double[objArray.length];
context: /* This file is part of VoltDB.
   * Copyright (C) 2008-2010 VoltDB L.L.C.
   *
   * VoltDB is free software: you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation, either version 3 of the License, or
   * (at your option) any later version.
   *
   * VoltDB is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with VoltDB.  If not, see <http://www.gnu.org/licenses/>.
   */
  
  package org.voltdb.utils;
  
  import java.text.ParseException;
  import java.text.SimpleDateFormat;
  import java.util.Date;
  import java.util.HashMap;
  import java.util.Map;
  import java.util.Random;
  import java.util.logging.Logger;
  import java.util.regex.Matcher;
  import java.util.regex.Pattern;
  
  import org.voltdb.VoltType;
  import org.voltdb.VoltTypeException;
  import org.voltdb.types.TimestampType;
  
  public abstract class VoltTypeUtil {
      private static final Logger LOG = Logger.getLogger(VoltTypeUtil.class.getName());
  
      protected final static Random rand = new Random();
      protected static final Integer DATE_STOP = Math.round(System.currentTimeMillis() / 1000);
      protected static final Integer DATE_START = VoltTypeUtil.DATE_STOP - 153792000;
      
      public static final String DATE_FORMAT_PATTERNS[] = {
          TimestampType.STRING_FORMAT,
          "EEE MMM dd HH:mm:ss zzz yyyy",     // Wed Aug 03 00:00:00 EDT 2011
          "yyyy-MM-dd HH:mm:ss",              // 2010-03-05 20:14:15
          "yyyy-MM-dd",                       // 2010-03-05
          TimestampType.STRING_FORMAT + ".0", // 2010-03-05T20:14:16.000.0
      };
      private static final Map<Thread, SimpleDateFormat[]> CACHED_DATE_FORMATS = new HashMap<Thread, SimpleDateFormat[]>();
  
      public static Object getRandomValue(VoltType type) {
          return getRandomValue(type, VoltTypeUtil.rand);
      }
      
      public static Object getRandomValue(VoltType type, Random rand) {
          Object ret = null;
          switch (type) {
              // --------------------------------
              // INTEGERS
              // --------------------------------
              case TINYINT:
                  ret = Integer.valueOf((byte) Math.abs(rand.nextInt() % 128));
                  break;
              case SMALLINT:
                  ret = Integer.valueOf((short) Math.abs(rand.nextInt() % 32768));
                  break;
              case INTEGER:
                  ret = Integer.valueOf(Math.abs(rand.nextInt() % 100000));
                  break;
              case BIGINT:
                  ret = Long.valueOf(Math.abs(rand.nextInt() % 100000));
                  break;
              // --------------------------------
              // FLOATS
              // --------------------------------
              case FLOAT:
              case DECIMAL:
                  ret = Double.valueOf(Math.abs(rand.nextDouble()));
                  break;
              // --------------------------------
              // STRINGS
              // --------------------------------
              case STRING:
                  //int size = rand.nextInt(31) + 1;
                  int size = 124; 
                  String ret_str = "";
                  for (int ctr = 0; ctr < size; ctr++) {
                      char data = (char)(Math.abs(rand.nextInt()) % 128);
                      //
                      // Skip quotation marks
                      //
                      if (Character.isLetter(data) == false) {
                         ctr--;
                      } else {
                         ret_str += String.valueOf(data);
                      }
                   }
                  ret = ret_str;
                  break;
              // --------------------------------
              // TIMESTAMP
              // --------------------------------
              case TIMESTAMP: {
                  int timestamp = rand.nextInt(VoltTypeUtil.DATE_STOP - VoltTypeUtil.DATE_START) + VoltTypeUtil.DATE_START;
                  ret = new TimestampType(Long.valueOf(timestamp * 1000));
                  break;
              }
              // --------------------------------
              // INVALID
              // --------------------------------
              default:
                  LOG.severe("ERROR: Unable to generate random value for invalid ValueType '" + type + "'");
          } // SWITCH
          return (ret);
      }
  
      /*
       * Determine if a cast is allowable w/o loss of precision
       * for index key comparison. This is probably overly strict.
       */
      public static boolean isAllowableCastForKeyComparator(VoltType from, VoltType to) {
          // self to self cast is obviously fine.
          if (from == to)
              return true;
  
          // allow only float to float
          // allow only decimal to decimal
          // allow only string to string
          if (to == VoltType.STRING    ||
              from == VoltType.STRING  ||
              to == VoltType.DECIMAL   ||
              from == VoltType.DECIMAL ||
              to == VoltType.FLOAT     ||
              from == VoltType.FLOAT)
          {
              return from == to;
          }
  
          // disallow integers getting smaller
          if (from == VoltType.BIGINT) {
              if (to == VoltType.SMALLINT ||
                  to == VoltType.TINYINT  ||
                  to == VoltType.INTEGER)
                  return false;
          }
          else if (from == VoltType.INTEGER) {
              if (to == VoltType.SMALLINT ||
                  to == VoltType.TINYINT)
                  return false;
          }
          else if (from == VoltType.SMALLINT) {
              if (to == VoltType.TINYINT)
                  return false;
          }
  
          return true;
      }
  
      public static VoltType determineImplicitCasting(VoltType left, VoltType right) {
          //
          // Make sure both are valid
          //
          if (left == VoltType.INVALID || right == VoltType.INVALID) {
              throw new VoltTypeException("ERROR: Unable to determine cast type for '" + left + "' and '" + right + "' types");
          }
          // Check for NULL first, if either type is NULL the output is always NULL
          // XXX do we need to actually check for all NULL_foo types here?
          else if (left == VoltType.NULL || right == VoltType.NULL)
          {
              return VoltType.NULL;
          }
          //
          // No mixing of strings and numbers
          //
          else if ((left == VoltType.STRING && right != VoltType.STRING) ||
                  (left != VoltType.STRING && right == VoltType.STRING))
          {
              throw new VoltTypeException("ERROR: Unable to determine cast type for '" +
                                          left + "' and '" + right + "' types");
          }
  
          // Allow promoting INTEGER types to DECIMAL.
          else if ((left == VoltType.DECIMAL || right == VoltType.DECIMAL) &&
                  !(left.isExactNumeric() && right.isExactNumeric()))
          {
              throw new VoltTypeException("ERROR: Unable to determine cast type for '" +
                                          left + "' and '" + right + "' types");
          }
          //
          // The following list contains the rules that use for casting:
          //
          //    (1) If both types are a STRING, the output is always a STRING
          //        Note that up above we made sure that they do not mix strings and numbers
          //            Example: STRING + STRING -> STRING
          //    (2) If one type is a DECIMAL, the output is always a DECIMAL
          //        Note that above we made sure that DECIMAL only mixes with
          //        allowed types
          //    (3) Floating-point types take precedence over integers
          //            Example: FLOAT + INTEGER -> FLOAT
          //    (4) Specific types for floating-point and integer types take precedence
          //        over the more general types
          //            Example: MONEY + FLOAT -> MONEY
          //            Example: TIMESTAMP + INTEGER -> TIMESTAMP
          VoltType cast_order[] = { VoltType.STRING,
                                    VoltType.DECIMAL,
                                    VoltType.FLOAT,
                                    VoltType.TIMESTAMP,
                                    VoltType.BIGINT };
          for (VoltType cast_type : cast_order) {
              //
              // If any one of the types is the current cast type, we'll use that
              //
              if (left == cast_type || right == cast_type)
              {
                  return cast_type;
              }
          }
  
          // If we have INT types smaller than BIGINT
          // promote the output up to BIGINT
          if ((left == VoltType.INTEGER || left == VoltType.SMALLINT || left == VoltType.TINYINT) &&
                  (right == VoltType.INTEGER || right == VoltType.SMALLINT || right == VoltType.TINYINT))
          {
              return VoltType.BIGINT;
          }
  
          // If we get here, we couldn't figure out what to do
          throw new VoltTypeException("ERROR: Unable to determine cast type for '" +
                                      left + "' and '" + right + "' types");
      }
  
      /**
       * Some of our workloads (like TPC-E) will have commands and other crap in the #s that we need to strip out 
       * @param value
       * @return
       */
      private static String cleanNumberString(String value) {
          Matcher m = pattern_cleanNumberString.matcher(value);
          return (m.replaceAll(""));
      }
      private static final Pattern pattern_cleanNumberString = Pattern.compile("[,)]");
      
      /**
       * Returns a casted object of the input value string based on the given type
       * @throws ParseException
       */
      public static Object getObjectFromString(VoltType type, String value) throws ParseException {
          return (VoltTypeUtil.getObjectFromString(type, value, Thread.currentThread()));
      }
          
      /**
       * Returns a casted object of the input value string based on the given type
       * You can pass the current thread to get a faster access for the cached SimpleDateFormats
       * @param type
       * @param value
       * @param self
       * @return
       * @throws ParseException
       */
      public static Object getObjectFromString(VoltType type, String value, Thread self) throws ParseException {
          Object ret = null;
          switch (type) {
              // NOTE: All runtime integer parameters are actually Longs,so we will have problems
              // if we actually try to convert the object to one of the smaller numeric sizes
  
              // --------------------------------
              // INTEGERS
              // --------------------------------
              case TINYINT:
                  //ret = Byte.valueOf(value);
                  //break;
              case SMALLINT:
                  //ret = Short.valueOf(value);
                  //break;
              case INTEGER:
                  ret = Integer.valueOf(value);
                  break;
              case BIGINT:
                  try {
                      ret = Long.valueOf(value);
                  } catch (NumberFormatException ex) {
                      ret = Long.valueOf(cleanNumberString(value));
                  }
                  break;
              // --------------------------------
              // FLOATS
              // --------------------------------
              case FLOAT:
              case DECIMAL:
                  try {
                      ret = Double.valueOf(value);
                  } catch (NumberFormatException ex) {
                      ret = Double.valueOf(cleanNumberString(value));
                  }
                  break;
              // --------------------------------
              // STRINGS
              // --------------------------------
              case STRING:
                  ret = value;
                  break;
              // --------------------------------
              // TIMESTAMP
              // --------------------------------
              case TIMESTAMP: {
                  Date date = null;
                  int usecs = 0;
                  if (value.isEmpty()) throw new RuntimeException("Empty " + type + " parameter value");
                  
                  // We have to do this because apparently SimpleDateFormat isn't thread safe
                  SimpleDateFormat formats[] = VoltTypeUtil.CACHED_DATE_FORMATS.get(self);
                  if (formats == null) {
                      formats = new SimpleDateFormat[VoltTypeUtil.DATE_FORMAT_PATTERNS.length];
                      for (int i = 0; i < formats.length; i++) {
                          formats[i] = new SimpleDateFormat(VoltTypeUtil.DATE_FORMAT_PATTERNS[i]);
                      } // FOR
                      VoltTypeUtil.CACHED_DATE_FORMATS.put(self, formats);
                  }
                  
                  ParseException last_ex = null;
                  for (int i = 0; i < formats.length; i++) {
                      try {
                          date = formats[i].parse(value);
                          // We need to get the last microseconds
                          if (i == 0) usecs = Integer.parseInt(value.substring(value.lastIndexOf('.')+1));
                      } catch (ParseException ex) {
                          last_ex = ex;
                      }
                      if (date != null) break;
                  } // FOR
                  if (date == null) throw last_ex;
                  ret = new TimestampType((date.getTime() * 1000) + usecs);
                  break;
              }
              // --------------------------------
              // BOOLEAN
              // --------------------------------
              case BOOLEAN:
                  ret = Boolean.parseBoolean(value);
                  break;
  
              // --------------------------------
              // NULL
              // --------------------------------
              case NULL:
                  ret = null;
                  break;
              // --------------------------------
              // INVALID
              // --------------------------------
              default: {
                  String msg = "Unable to get object for value with invalid ValueType '" + type + "'";
                  throw new ParseException(msg, 0);
                  // LOG.severe(msg);
              }
          }
          return (ret);
      }
      
      public static Object getPrimitiveArray(VoltType type, Object objArray[]) {
          Object ret = null;
          switch (type) {
              // --------------------------------
              // INTEGERS
              // --------------------------------
              case TINYINT: {
                  Byte valArray[] = new Byte[objArray.length];
                  for (int i = 0; i < objArray.length; i++) {
                      valArray[i] = ((Integer)objArray[i]).byteValue();
                  } // FOR
                  ret = valArray;
                  break;
              }
              case SMALLINT: {
                  Short valArray[] = new Short[objArray.length];
                  for (int i = 0; i < objArray.length; i++) {
                      valArray[i] = ((Integer)objArray[i]).shortValue();
                  } // FOR
                  ret = valArray;
                  break;
              }
              case INTEGER: {
                  Integer valArray[] = new Integer[objArray.length];
                  for (int i = 0; i < objArray.length; i++) {
                      valArray[i] = (Integer)objArray[i];
                  } // FOR
                  ret = valArray;
                  break;
              }
              case BIGINT: {
                  Long valArray[] = new Long[objArray.length];
                  for (int i = 0; i < objArray.length; i++) {
                      valArray[i] = (Long)objArray[i];
                  } // FOR
                  ret = valArray;
                  break;
              }
              // --------------------------------
              // FLOATS
              // --------------------------------
              case FLOAT:
              case DECIMAL: {
  