All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.peterbecker.configuration.storage.YamlStore Maven / Gradle / Ivy

package com.github.peterbecker.configuration.storage;

import com.github.peterbecker.configuration.ConfigurationException;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.representer.Representer;
import org.yaml.snakeyaml.resolver.Resolver;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.Optional;

@SuppressWarnings("unchecked")
public class YamlStore implements Store {
    private final Map data;

    @SuppressWarnings("unchecked")
    public YamlStore(Path resource) throws IOException {
        Yaml yaml = new Yaml(
                new Constructor(), // default
                new Representer(), // default
                new DumperOptions(), // default
                new CustomResolver());
        data = yaml.load(Files.newBufferedReader(resource));
    }

    @Override
    public Optional getValue(Key key) throws ConfigurationException {
        return getNode(data,key).map(Object::toString);
    }

    private Optional getNode(Map context, Key key) throws ConfigurationException {
        Optional node = getContextObject(context, key).map(o -> o.get(key.getOptionName()));
        if(key.isIndexed()) {
            node = node.map(object -> {
                if(!(object instanceof List)) {
                    return null;
                }
                List> listNode = (List>) object;
                if(listNode.size() <= key.getIndex()) {
                    return null;
                }
                return listNode.get(key.getIndex());
            });
        }
        return node;
    }

    private Optional> getContextObject(Map context, Key key) throws ConfigurationException {
        if(key.isTopLevel()) {
            return Optional.of(context);
        } else {
            Optional parent = getNode(context, key.getContext());
            if (!parent.isPresent()) {
                return Optional.empty();
            }
            if (!(parent.get() instanceof Map)) {
                throw new ConfigurationException(key.getOptionName() + " is not an object");
            }
            return Optional.of((Map)parent.get());

        }
    }

    private class CustomResolver extends Resolver {
        protected void addImplicitResolvers() {
            // no implicit resolving, that is up to the Configuration Parser
        }
    }
}