public static Entry typify()

in common/src/main/java/org/apache/drill/common/Typifier.java [163:309]


  public static Entry<Class, String> typify(String data,
                                            boolean bool01,
                                            boolean commonTypes,
                                            boolean postfixFL,
                                            boolean parseDates) {

    // -2. if the input data has 0 length, return as null object
    if (data == null || data.length() == 0) {
      return new SimpleEntry<>(Object.class, null);
    }

    String s = data.trim();
    int slen = s.length();

    // -1. if the input data is only whitespace, return "String" and input as-is
    if (slen == 0) {
      return new SimpleEntry<>(String.class, data);
    }

    // In most data, numerical values are more common than true/false values. So,
    // if we want to speed up data parsing, we can move this block to the end when
    // looking only for common types.

    /// Check if the data is Boolean (true or false)
    if (!commonTypes) {
      if (contains(falseAliases, s)) {
        return new SimpleEntry<>(Boolean.class, "false");
      } else if (contains(trueAliases, s)) {
        return new SimpleEntry<>(Boolean.class, "true");
      }
    }

    // Check for any String-only characters; if we find them, don't bother trying to parse this as a number
    if (!containsAny(s, StringCharacters)) {

      // try again for boolean -- need to make sure it's not parsed as Byte
      if (bool01) {
        if (s.equals("0")) {
          return new SimpleEntry<>(Boolean.class, "false");
        } else if (s.equals("1")) {
          return new SimpleEntry<>(Boolean.class, "true");
        }
      }

      char lastChar = s.charAt(slen - 1);
      boolean lastCharF = (lastChar == 'f' || lastChar == 'F');
      boolean lastCharL = (lastChar == 'l' || lastChar == 'L');

      // If we're not restricted to common types, look for anything
      if (!commonTypes) {
        // 1. Check if data is a Byte (1-byte integer with range [-(2e7) = -128, ((2e7)-1) = 127])
        try {
          byte b = Byte.parseByte(s);
          return new SimpleEntry<>(Byte.class, Byte.toString(b));
        } catch (NumberFormatException ex) {
          // Okay, guess it's not a Byte
        }

        // 2. Check if data is a Short (2-byte integer with range [-(2e15) = -32768, ((2e15)-1) = 32767])
        try {
          short h = Short.parseShort(s);
          return new SimpleEntry<>(Short.class, Short.toString(h));
        } catch (NumberFormatException ex) {
          // Okay, guess it's not a Short
        }

        // 3. Check if data is an Integer (4-byte integer with range [-(2e31), (2e31)-1])
        try {
          int i = Integer.parseInt(s);
          return new SimpleEntry<>(Integer.class, Integer.toString(i));
        } catch (NumberFormatException ex) {
          // okay, guess it's not an Integer
        }
        String s_L_trimmed = s;

        // 4. Check if data is a Long (8-byte integer with range [-(2e63), (2e63)-1])
        //    ...first, see if the last character of the string is "L" or "l"
        //    ... Java parses "3.3F", etc. fine as a float, but throws an error with "3L", etc.
        if (postfixFL && slen > 1 && lastCharL) {
          s_L_trimmed = s.substring(0, slen - 1);
        }

        try {
          long l = Long.parseLong(s_L_trimmed);
          return new SimpleEntry<>(Long.class, Long.toString(l));
        } catch (NumberFormatException ex) {
          // okay, guess it's not a Long
        }

        // 5. Check if data is a Float (32-bit IEEE 754 floating point with approximate extents +/- 3.4028235e38)
        if (postfixFL || !lastCharF) {
          try {
            float f = Float.parseFloat(s);
            // If it's beyond the range of Float, maybe it's not beyond the range of Double
            if (!Float.isInfinite(f)) {
              return new SimpleEntry<>(Float.class, Float.toString(f));
            }
          } catch (NumberFormatException ex) {
            // okay, guess it's not a Float
          }
        }
      }

      // 6. Check if data is a Double (64-bit IEEE 754 floating point with approximate extents +/- 1.797693134862315e308 )
      if (postfixFL || !lastCharF) {
        try {
          double d = Double.parseDouble(s);
          if (!Double.isInfinite(d)) {
            return new SimpleEntry<>(Double.class, Double.toString(d));
          } else {
            return new SimpleEntry<>(String.class, s);
          }
        } catch (NumberFormatException ex) {
          // okay, guess it's not a Double
        }
      }
    }

    // Check for either Boolean or String
    if (commonTypes) {
      if (contains(falseAliases, s)) {
        return new SimpleEntry<>(Boolean.class, "false");
      } else if (contains(trueAliases, s)) {
        return new SimpleEntry<>(Boolean.class, "true");
      }
    }

    // 7. revert to String by default, with caveats...

    // 7a. if string has length 1, it is a single character
    if (!commonTypes && slen == 1) {
      return new SimpleEntry<>(Character.class, s); // end uncommon types 2/2
    }

    // 7b. attempt to parse String as a LocalDateTime
    if (parseDates && stringAsDateTime(s) != null) {
      return new SimpleEntry<>(LocalDateTime.class, s);
    }

    // 7c. Attempt to parse the String as a LocalDate
    if (parseDates && stringAsDate(s) != null) {
      return new SimpleEntry<>(LocalDate.class, s);
    }

    // ...if we've made it all the way to here without returning, give up and return "String" and input as-is
    return new SimpleEntry<>(String.class, data);
  }