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

sdmxdl.cli.CheckConfigCommand Maven / Gradle / Ivy

/*
 * Copyright 2018 National Bank of Belgium
 *
 * Licensed under the EUPL, Version 1.1 or - as soon they will be approved
 * by the European Commission - subsequent versions of the EUPL (the "Licence");
 * You may not use this work except in compliance with the Licence.
 * You may obtain a copy of the Licence at:
 *
 * http://ec.europa.eu/idabc/eupl
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the Licence is distributed on an "AS IS" basis,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the Licence for the specific language governing permissions and
 * limitations under the Licence.
 */
package sdmxdl.cli;

import internal.sdmxdl.cli.ext.Anchor;
import internal.sdmxdl.cli.ext.CsvTable;
import internal.sdmxdl.cli.ext.RFC4180OutputOptions;
import internal.sdmxdl.cli.ext.VerboseOptions;
import nbbrd.console.picocli.ConfigHelper;
import nbbrd.io.text.Formatter;
import picocli.CommandLine;
import sdmxdl.About;

import java.util.Properties;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.concurrent.Callable;
import java.util.stream.Stream;

/**
 * @author Philippe Charles
 */
@CommandLine.Command(name = "config")
@SuppressWarnings("FieldMayBeFinal")
public final class CheckConfigCommand implements Callable {

    @CommandLine.Mixin
    private VerboseOptions verboseOptions;

    @CommandLine.Mixin
    private final RFC4180OutputOptions csv = new RFC4180OutputOptions();

    @CommandLine.Spec
    private CommandLine.Model.CommandSpec spec;

    @Override
    public Void call() throws Exception {
        getTable().write(csv, getRows());
        return null;
    }

    private CsvTable getTable() {
        return CsvTable
                .builderOf(ScopedProperty.class)
                .columnOf("Scope", ScopedProperty::getScope, Formatter.onEnum())
                .columnOf("PropertyKey", ScopedProperty::getKey)
                .columnOf("PropertyValue", ScopedProperty::getValue)
                .columnOf("Category", ScopedProperty::getCategory, Formatter.onEnum())
                .build();
    }

    private Stream getRows() {
        return getProperties(getConfigHelper())
                .entrySet()
                .stream()
                .flatMap(entry -> getEntries(entry.getKey(), entry.getValue(), spec.commandLine()));
    }

    private ConfigHelper getConfigHelper() {
        return ConfigHelper
                .builder()
                .appName(About.NAME)
                .onLoadingError((path, ex) -> verboseOptions.reportToErrorStream(Anchor.CFG, path.toString(), ex))
                .build();
    }

    private static SortedMap getProperties(ConfigHelper helper) {
        SortedMap result = new TreeMap<>();
        for (ConfigHelper.Scope scope : ConfigHelper.Scope.values()) {
            Properties properties = new Properties();
            helper.load(properties, scope);
            result.put(scope, properties);
        }
        return result;
    }

    private static Stream getEntries(ConfigHelper.Scope scope, Properties properties, CommandLine cmd) {
        return properties.stringPropertyNames().stream()
                .map(key -> new ScopedProperty(scope, key, properties.getProperty(key), Category.get(key, getRoot(cmd))));
    }

    private static CommandLine getRoot(CommandLine cmd) {
        CommandLine parent = cmd.getParent();
        return parent != null ? getRoot(parent) : cmd;
    }

    private enum Category {

        WIDE_OPTION, NARROW_OPTION, OTHER;

        static Category get(String key, CommandLine cmd) {
            for (CommandLine.Model.OptionSpec option : cmd.getCommandSpec().options()) {
                String descriptionKey = option.descriptionKey();
                if (descriptionKey != null) {
                    if (key.equals(cmd.getCommandSpec().qualifiedName(".") + "." + descriptionKey))
                        return NARROW_OPTION;
                    if (key.equals(descriptionKey)) return WIDE_OPTION;
                }
                String longestName = stripPrefix(option.longestName());
                if (key.equals(cmd.getCommandSpec().qualifiedName(".") + "." + longestName)) return NARROW_OPTION;
                if (key.equals(longestName)) return WIDE_OPTION;
            }
            for (CommandLine sub : cmd.getSubcommands().values()) {
                Category result = get(key, sub);
                if (result != OTHER) {
                    return result;
                }
            }
            return OTHER;
        }

        private static String stripPrefix(String prefixed) {
            for (int i = 0; i < prefixed.length(); i++) {
                if (Character.isJavaIdentifierPart(prefixed.charAt(i))) {
                    return prefixed.substring(i);
                }
            }
            return prefixed;
        }
    }

    @lombok.Value
    private static class ScopedProperty {
        ConfigHelper.Scope scope;
        String key;
        String value;
        Category category;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy