code: public static Object getApiValue(Value value) {
      if (value instanceof BooleanValue) {
        return ((BooleanValue) value).getValue();
      } else if (value instanceof NumberValue) {
        if (Strings.isNullOrEmpty(((NumberValue) value).getValue())) {
          return null;
        } else {
          try {
            return NumberFormat.getInstance().parse(((NumberValue) value).getValue());
          } catch (ParseException e) {
            throw new IllegalStateException(
                "Received invalid number format from API: " + ((NumberValue) value).getValue());
          }
        }
      } else if (value instanceof TextValue) {
        return ((TextValue) value).getValue();
      } else if (value instanceof DateTimeValue) {
        return ((DateTimeValue) value).getValue();
      } else if (value instanceof DateValue) {
        return ((DateValue) value).getValue();
      } else if (value instanceof TargetingValue) {
        return ((TargetingValue) value).getValue();
      } else if (value instanceof SetValue) {
        Value[] setValues = ((SetValue) value).getValues();
        Set<Object> apiValue = new LinkedHashSet<Object>();
        if (setValues != null) {
          for (Value setValue : setValues) {
            validateSetValueEntryForSet(getApiValue(setValue), apiValue);
            apiValue.add(getApiValue(setValue));
          }
        }
        return apiValue;
      } else {
        throw new IllegalArgumentException("Unsupported Value type [" + value.getClass() + "]");
      }
    }
docs: Gets the underlying value of the {@code Value} object that's comparable to what would be
  returned in any other API object (i.e. DateTimeValue will return an API DateTime, not a Joda
  DateTime).
  
  @param value the value to convert
  @return the native value of {@code Value} or {@code null} if the underlying value is null
  @throws IllegalArgumentException if value cannot be converted