// Path: common/src/main/java/com/kumuluz/ee/configuration/ConfigurationDecoder.java
// public interface ConfigurationDecoder {
// 
//     /**
//      * Check if key's value should be decoded.
//      *
//      * @param key configuration key to be checked for decoding
//      * @return returns true if key's value should be decoded with the decode(String key, String value) method
//      */
//     boolean shouldDecode(String key);
// 
//     /**
//      * Decode values of encoded keys.
//      *
//      * @param key   encoded key
//      * @param value encoded value
//      * @return decoded value
//      */
//     String decode(String key, String value);
// }


import com.kumuluz.ee.configuration.ConfigurationDecoder;
import com.kumuluz.ee.configuration.ConfigurationListener;
import com.kumuluz.ee.configuration.ConfigurationSource;
import com.kumuluz.ee.configuration.enums.ConfigurationValueType;
import java.util.*;
                        mapKeys.add(s);
                    }
                }
            }
        }

        if (mapKeys.isEmpty()) {
            return Optional.empty();
        }

        return Optional.of(new ArrayList<>(mapKeys));
    }

    public void subscribe(String key, ConfigurationListener listener) {

        config.getDispatcher().subscribe(listener);

        for (ConfigurationSource configurationSource : config.getConfigurationSources()) {
            configurationSource.watch(key);
        }
    }

    public void unsubscribe(ConfigurationListener listener) {
        config.getDispatcher().unsubscribe(listener);
    }

    public List<ConfigurationSource> getConfigurationSources() {
        return Collections.unmodifiableList(this.config.getConfigurationSources());
    }

// Path: common/src/main/java/com/kumuluz/ee/configuration/ConfigurationDecoder.java
// public interface ConfigurationDecoder {
// 
//     /**
//      * Check if key's value should be decoded.
//      *
//      * @param key configuration key to be checked for decoding
//      * @return returns true if key's value should be decoded with the decode(String key, String value) method
//      */
//     boolean shouldDecode(String key);
// 
//     /**
//      * Decode values of encoded keys.
//      *
//      * @param key   encoded key
//      * @param value encoded value
//      * @return decoded value
//      */
//     String decode(String key, String value);
// }


// Path: common/src/main/java/com/kumuluz/ee/configuration/utils/ConfigurationUtil.java
import com.kumuluz.ee.configuration.ConfigurationDecoder;
import com.kumuluz.ee.configuration.ConfigurationListener;
import com.kumuluz.ee.configuration.ConfigurationSource;
import com.kumuluz.ee.configuration.enums.ConfigurationValueType;
import java.util.*;

                        mapKeys.add(s);
                    }
                }
            }
        }

        if (mapKeys.isEmpty()) {
            return Optional.empty();
        }

        return Optional.of(new ArrayList<>(mapKeys));
    }

    public void subscribe(String key, ConfigurationListener listener) {

        config.getDispatcher().subscribe(listener);

        for (ConfigurationSource configurationSource : config.getConfigurationSources()) {
            configurationSource.watch(key);
        }
    }

    public void unsubscribe(ConfigurationListener listener) {
        config.getDispatcher().unsubscribe(listener);
    }

    public List<ConfigurationSource> getConfigurationSources() {
        return Collections.unmodifiableList(this.config.getConfigurationSources());
    }

    public ConfigurationDecoder getConfigurationDecoder() {