@Override
    @SuppressWarnings("unchecked")
    public <T> T get(final PluginConfigSpec<T> configSpec) {
        if (rawSettings.containsKey(configSpec.name())) {
            Object o = rawSettings.get(configSpec.name());
            if (configSpec.type().isAssignableFrom(o.getClass())) {
                return (T) o;
            } else if (configSpec.type() == Double.class && o.getClass() == Long.class) {
                return configSpec.type().cast(((Long)o).doubleValue());
            } else if (configSpec.type() == Boolean.class && o instanceof String) {
                return configSpec.type().cast(Boolean.parseBoolean((String) o));
            } else if (configSpec.type() == Codec.class && o instanceof String && pluginFactory != null) {
                Codec codec = pluginFactory.buildDefaultCodec((String) o);
                return configSpec.type().cast(codec);
            } else if (configSpec.type() == Codec.class && o instanceof RubyObject && RubyCodecDelegator.isRubyCodecSubclass((RubyObject) o)) {
                Codec codec = pluginFactory.buildRubyCodecWrapper((RubyObject) o);
                return configSpec.type().cast(codec);
            } else if (configSpec.type() == URI.class && o instanceof String) {
                try {
                    URI uri = new URI((String) o);
                    return configSpec.type().cast(uri);
                } catch (URISyntaxException ex) {
                    throw new IllegalStateException(
                            String.format("Invalid URI specified for '%s'", configSpec.name()));
                }
            } else if (configSpec.type() == Password.class && o instanceof String) {
                Password p = new Password((String) o);
                return configSpec.type().cast(p);
            } else {
                throw new IllegalStateException(
                        String.format("Setting value for '%s' of type '%s' incompatible with defined type of '%s'",
                                configSpec.name(), o.getClass(), configSpec.type()));
            }
        } else if (configSpec.type() == Codec.class && configSpec.getRawDefaultValue() != null && pluginFactory != null) {
            Codec codec = pluginFactory.buildDefaultCodec(configSpec.getRawDefaultValue());
            return configSpec.type().cast(codec);
        } else if (configSpec.type() == URI.class && configSpec.getRawDefaultValue() != null) {
            try {
                URI uri = new URI(configSpec.getRawDefaultValue());
                return configSpec.type().cast(uri);
            } catch (URISyntaxException ex) {
                throw new IllegalStateException(
                        String.format("Invalid default URI specified for '%s'", configSpec.name()));
            }
        } else if (configSpec.type() == Password.class && configSpec.getRawDefaultValue() != null) {
            Password p = new Password(configSpec.getRawDefaultValue());
            return configSpec.type().cast(p);
        } else {
            return configSpec.defaultValue();
        }
    }
@Test
    public void testDefaultValues() {
        Configuration unsetConfig = new ConfigurationImpl(new HashMap<>());

        String defaultStringValue = "defaultStringValue";
        long defaultLongValue = 43L;
        boolean defaultBooleanValue = false;

        PluginConfigSpec<String> stringConfig = PluginConfigSpec.stringSetting(stringKey, defaultStringValue, false, false);
        PluginConfigSpec<Long> numberConfig = PluginConfigSpec.numSetting(numberKey, defaultLongValue, false, false);
        PluginConfigSpec<Boolean> booleanConfig = PluginConfigSpec.booleanSetting(booleanKey, defaultBooleanValue, false, false);

        Assert.assertEquals(defaultStringValue, unsetConfig.get(stringConfig));
        Assert.assertEquals(defaultLongValue, (long) unsetConfig.get(numberConfig));
        Assert.assertEquals(defaultBooleanValue, unsetConfig.get(booleanConfig));

        Configuration config = getTestConfiguration();
        Assert.assertNotEquals(defaultStringValue, config.get(stringConfig));
        Assert.assertNotEquals(defaultLongValue, (long) config.get(numberConfig));
        Assert.assertNotEquals(defaultBooleanValue, config.get(booleanConfig));
    }