@SuppressWarnings("unchecked")
  public static <K, V> V getWithDefault(final Map<K, ? extends Object> map,
                                        final K key,
                                        final V defaultValue,
                                        final Class<V> valueClass)
  {
    final Object actualValue = map.get(key);
    if (actualValue == null)
    {
      return defaultValue;
    }

    if (valueClass.isAssignableFrom(actualValue.getClass()))
    {
      return (V) actualValue;
    }

    if (!(actualValue instanceof String))
    {
      throw new IllegalArgumentException("Unsupported actual value type: "
          + actualValue.getClass());
    }

    final String valStr = (String) actualValue;
    if (valueClass.equals(Double.class))
    {
      return (V) Double.valueOf(Double.parseDouble(valStr));
    }
    if (valueClass.equals(Float.class))
    {
      return (V) Float.valueOf(Float.parseFloat(valStr));
    }
    if (valueClass.equals(Long.class))
    {
      return (V) Long.valueOf(Long.parseLong(valStr));
    }
    if (valueClass.equals(Integer.class))
    {
      return (V) Integer.valueOf(Integer.parseInt(valStr));
    }
    if (valueClass.equals(Boolean.class))
    {
      return (V) Boolean.valueOf(Boolean.parseBoolean(valStr));
    }

    throw new IllegalArgumentException("Unsupported expected value type: " + valueClass + " and value = " +
                                           actualValue);
  }
@Test
  public void testGetWithDefault()
  {
    Assert.assertTrue(MapUtil.getWithDefault(_subjectMap, "boolean", false));
    Assert.assertFalse(MapUtil.getWithDefault(_subjectMap, "boolean_default", false));

    Assert.assertEquals(MapUtil.getWithDefault(_subjectMap, "integer", 11), (Integer) 1);
    Assert.assertEquals(MapUtil.getWithDefault(_subjectMap, "integer_default", 11),
                        (Integer) 11);

    Assert.assertEquals(MapUtil.getWithDefault(_subjectMap, "long", 12L), (Long) 2L);
    Assert.assertEquals(MapUtil.getWithDefault(_subjectMap, "long_default", 12L), (Long) 12L);

    Assert.assertEquals(MapUtil.getWithDefault(_subjectMap, "float", 13F), 3F);
    Assert.assertEquals(MapUtil.getWithDefault(_subjectMap, "float_default", 13F), 13F);

    Assert.assertEquals(MapUtil.getWithDefault(_subjectMap, "double", 14D), 4D);
    Assert.assertEquals(MapUtil.getWithDefault(_subjectMap, "double_default", 14D), 14D);

    Assert.assertEquals(MapUtil.getWithDefault(_subjectMap, "string", "Bar"), "Foo");
    Assert.assertEquals(MapUtil.getWithDefault(_subjectMap, "string_default", "Bar"), "Bar");

    Assert.assertSame(MapUtil.getWithDefault(_subjectMap, "subMap", null, LinkedHashMap.class).getClass(), LinkedHashMap.class);
    Assert.assertSame(MapUtil.getWithDefault(_subjectMap, "subMap", _probeMap).getClass(), LinkedHashMap.class);
    Assert.assertSame(MapUtil.getWithDefault(_subjectMap, "subMap_default", _probeMap).getClass(), HashMap.class);
    Assert.assertNull(MapUtil.getWithDefault(_subjectMap, "subMap_default", null, Object.class));

    Assert.assertSame(MapUtil.getWithDefault(_subjectMap, "siblingMap", null, Hashtable.class).getClass(), Hashtable.class);
    Assert.assertSame(MapUtil.getWithDefault(_subjectMap, "siblingMap", _probeMap, Map.class).getClass(), Hashtable.class);
    Assert.assertSame(MapUtil.getWithDefault(_subjectMap, "siblingMap_default", _probeMap, Map.class).getClass(), HashMap.class);
  }