class ConfigTree {
    private ConfigurableEnvironment environment;
    private String prefix;

    public ConfigTree(ConfigurableEnvironment environment, String prefix) {
        Assert.notNull(environment, "environment is required");
        Assert.notNull(prefix, "prefix is required");
        this.environment = environment;
        this.prefix = prefix;
    }

    public ConfigTree subTree(String prefix) {
        return new ConfigTree(environment, fullPrefixOrKey(prefix));
    }

    private String fullPrefixOrKey(String prefixOrKey) {
        return this.prefix + prefixOrKey;
    }

    public Map<String, Object> getProperties() {<FILL_FUNCTION_BODY>}

    public boolean containsProperty(String key) {
        key = fullPrefixOrKey(key);
        return environment.containsProperty(key);
    }

    public String getProperty(String key) {
        key = fullPrefixOrKey(key);
        return environment.getProperty(key);
    }

    public String getProperty(String key, String defaultValue) {
        if (containsProperty(key)) {
            return getProperty(key);
        } else {
            return defaultValue;
        }
    }

    public boolean getProperty(String key, boolean defaultValue) {
        if (containsProperty(key)) {
            return Boolean.parseBoolean(getProperty(key));
        } else {
            return defaultValue;
        }
    }

    public int getProperty(String key, int defaultValue) {
        if (containsProperty(key)) {
            return Integer.parseInt(getProperty(key));
        } else {
            return defaultValue;
        }
    }

    public long getProperty(String key, long defaultValue) {
        if (containsProperty(key)) {
            return Long.parseLong(getProperty(key));
        } else {
            return defaultValue;
        }
    }

    public String getPrefix() {
        return prefix;
    }

    public Set<String> directChildrenKeys() {
        Map<String, Object> m = getProperties();
        return m.keySet().stream().map(
                s -> s.indexOf('.') >= 0 ? s.substring(0, s.indexOf('.')) : null)
                .filter(s -> s != null)
                .collect(Collectors.toSet());
    }
}

        Map<String, Object> m = new HashMap<>();
        for (PropertySource<?> source : environment.getPropertySources()) {
            if (source instanceof EnumerablePropertySource) {
                for (String name : ((EnumerablePropertySource<?>) source)
                        .getPropertyNames()) {
                    if (name != null && name.startsWith(prefix)) {
                        String subKey = name.substring(prefix.length());
                        m.put(subKey, environment.getProperty(name));
                    }
                }
            }
        }
        return m;
    
<no_super_class>