ConfigWithFallback implements ScopedConfig, ConfigMergeable { public static ConfigWithFallback newInstance(final Config originalConfig, final String configPath, final KnownConfigValue[] fallBackValues) { validateArgument(originalConfig, "original Config"); validateArgument(configPath, "config path"); validateArgument(fallBackValues, "fall-back values"); Config baseConfig; if (originalConfig.hasPath(configPath)) { baseConfig = DefaultScopedConfig.newInstance(originalConfig, configPath); } else { baseConfig = DefaultScopedConfig.empty(configPath); } if (0 < fallBackValues.length) { baseConfig = baseConfig.withFallback(arrayToConfig(fallBackValues)); } String configPathToUse = configPath; if (originalConfig instanceof ScopedConfig) { final WithConfigPath scopedConfig = (WithConfigPath) originalConfig; configPathToUse = scopedConfig.getConfigPath() + "." + configPath; } return new ConfigWithFallback(baseConfig, configPathToUse); } private  ConfigWithFallback(final Config theBaseConfig, final String theConfigPath); static ConfigWithFallback newInstance(final Config originalConfig, final String configPath,
            final KnownConfigValue[] fallBackValues); static ConfigWithFallback newInstance(final Config originalConfig, final KnownConfigValue[] fallBackValues); @Override ConfigObject root(); @Override ConfigOrigin origin(); @Override Config withFallback(final ConfigMergeable other); @Override Config resolve(); @Override Config resolve(final ConfigResolveOptions options); @Override boolean isResolved(); @Override Config resolveWith(final Config source); @Override Config resolveWith(final Config source, final ConfigResolveOptions options); @Override void checkValid(final Config reference, final String... restrictToPaths); @Override boolean hasPath(final String path); @Override boolean hasPathOrNull(final String path); @Override boolean isEmpty(); @Override Set<Map.Entry<String, ConfigValue>> entrySet(); @Override boolean getIsNull(final String path); @Override boolean getBoolean(final String path); @Override Number getNumber(final String path); @Override int getInt(final String path); @Override long getLong(final String path); @Override double getDouble(final String path); @Override String getString(final String path); @Nullable String getStringOrNull(final WithConfigPath withConfigPath); @Override T getEnum(final Class<T> enumClass, final String path); @Override ConfigObject getObject(final String path); @Override Config getConfig(final String path); @Override Object getAnyRef(final String path); @Override ConfigValue getValue(final String path); @Override Long getBytes(final String path); @Override ConfigMemorySize getMemorySize(final String path); @Override @Deprecated Long getMilliseconds(final String path); @Override @Deprecated Long getNanoseconds(final String path); @Override long getDuration(final String path, final TimeUnit unit); @Override Duration getDuration(final String path); @Override Period getPeriod(final String path); @Override TemporalAmount getTemporal(final String path); @Override ConfigList getList(final String path); @Override List<Boolean> getBooleanList(final String path); @Override List<Number> getNumberList(final String path); @Override List<Integer> getIntList(final String path); @Override List<Long> getLongList(final String path); @Override List<Double> getDoubleList(final String path); @Override List<String> getStringList(final String path); @Override List<T> getEnumList(final Class<T> enumClass,
            final String path); @Override List<? extends ConfigObject> getObjectList(final String path); @Override List<? extends Config> getConfigList(final String path); @Override List<? extends Object> getAnyRefList(final String path); @Override List<Long> getBytesList(final String path); @Override List<ConfigMemorySize> getMemorySizeList(final String path); @Override @Deprecated List<Long> getMillisecondsList(final String path); @Override @Deprecated List<Long> getNanosecondsList(final String path); @Override List<Long> getDurationList(final String path, final TimeUnit unit); @Override List<Duration> getDurationList(final String path); @Override Config withOnlyPath(final String path); @Override Config withoutPath(final String path); @Override Config atPath(final String path); @Override Config atKey(final String key); @Override Config withValue(final String path, final ConfigValue value); @Override String getConfigPath(); @Override boolean equals(final Object o); @Override int hashCode(); @Override String toString();  }
@Test public void tryToCreateInstanceWithNullOriginalConfig() { assertThatExceptionOfType(DittoConfigError.class) .isThrownBy(() -> ConfigWithFallback.newInstance(null, KNOWN_CONFIG_PATH, new KnownConfigValue[0])) .withCause(new NullPointerException("The original Config must not be null!")); }
@Test public void tryToCreateInstanceWithNullConfigPath() { assertThatExceptionOfType(DittoConfigError.class) .isThrownBy(() -> ConfigWithFallback.newInstance(ConfigFactory.empty(), null, new KnownConfigValue[0])) .withCause(new NullPointerException("The config path must not be null!")); }
@Test public void tryToCreateInstanceWithNullFallBackValues() { final Config config = ConfigFactory.parseMap(Collections.singletonMap(KNOWN_CONFIG_PATH, "nothing")); assertThatExceptionOfType(DittoConfigError.class) .isThrownBy(() -> ConfigWithFallback.newInstance(config, KNOWN_CONFIG_PATH, null)) .withCause(new NullPointerException("The fall-back values must not be null!")); }
@Test public void tryToGetInstanceWithConfigWithWrongTypeAtConfigPath() { final Config config = ConfigFactory.parseMap(Collections.singletonMap(KNOWN_CONFIG_PATH, "bar")); assertThatExceptionOfType(DittoConfigError.class) .isThrownBy(() -> ConfigWithFallback.newInstance(config, KNOWN_CONFIG_PATH, new KnownConfigValue[0])) .withMessage("Failed to get nested Config at <%s>!", KNOWN_CONFIG_PATH) .withCauseInstanceOf(ConfigException.WrongType.class); }