# AbstractRuleParametersFactory.java

    package org.thewonderlemming.c4plantuml.mojo.linting.rules.builtin;

    import java.util.AbstractMap.SimpleEntry;
    import java.util.Map.Entry;
    import java.util.Optional;
    import java.util.Set;
    import java.util.stream.Collectors;

    import org.thewonderlemming.c4plantuml.linter.rules.AbstractLintingRule;
    import org.thewonderlemming.c4plantuml.linter.rules.RuleParameters;
    import org.thewonderlemming.c4plantuml.mojo.linting.BuiltInRules;

    /**
     * A base implementation of a factory pattern to build {@link RuleParameters} for any {@link AbstractLintingRule}.
     *
     * @author thewonderlemming
     *
     * <P> the type of POJO embedded within the {@link BuiltInRules} object to configure the current rule.
     */
    public abstract class AbstractRuleParametersFactory<P> {

        private final boolean isActivated;

        private final RuleParameters ruleParameters;

        private static Entry<String, String> toStringStringEntry(final Entry<String, Optional<String>> entry) {

            assert (entry.getValue().isPresent()) : "Expected value to be non empty";

            final String value = entry.getValue().isPresent() ? entry.getValue().get() : "";
            return new SimpleEntry<>(entry.getKey(), value);
        }

        /**
         * Default constructor.
         *
         * @param mojoParameters the PJO containing the configuration from the {@code pom.xml} file.
         */
        protected AbstractRuleParametersFactory(final BuiltInRules mojoParameters) {

            final P pojoParameters = getPojoFromBuiltInRules(mojoParameters);
            this.isActivated = getActivatedParameter(pojoParameters);
            this.ruleParameters = buildRuleParameters(pojoParameters);
        }

        /**
         * Returns the built {@link RuleParameters} instance.
         *
         * @return the  built {@link RuleParameters}.
         */
        public RuleParameters getRuleParameters() {
            return this.ruleParameters;
        }

        /**
         * Tells whether or not the current {@link AbstractLintingRule} is enabled or disabled.
         *
         * @return {@code true} is the rule is enabled, {@code false} else.
         */
        public boolean isActivated() {
            return this.isActivated;
        }

        /**
         * Extracts and returns the value of the {@code isActivated} parameter from a POJO in the {@link BuiltInRules} POJO.
         *
         * @param pojoParameters the POJO that holds the {@code pom.xml} plugin configuration.
         * @return the value of the {@code isActivated} parameter.
         */
        protected abstract boolean getActivatedParameter(final P pojoParameters);

        /**
         * Retrieves the rule configuration POJO from the {@link BuiltInRules} POJO.
         *
         * @param mojoParameters the POJO that hosts the rule configuration object.
         * @return the rule configuration object.
         */
        protected abstract P getPojoFromBuiltInRules(final BuiltInRules mojoParameters);

        /**
         * Returns the parameters names for the current {@link AbstractLintingRule}.
         *
         * @return the parameters names for the rule.
         */
        protected abstract Set<String> getRuleParametersKeys();

        /**
         * Extracts and returns the value of the given parameter {@code key} from a POJO in the {@link BuiltInRules} POJO.
         *
         * @param key the name of the parameter to retrieves the value from.
         * @param pojoParameters the POJO that holds the {@code pom.xml} plugin configuration.
         * @return the value of the {@code key} parameter.
         */
        protected abstract Optional<String> getValueForParameter(final String key, final P pojoParameters);

        private RuleParameters buildRuleParameters(final P pojoParameters) {

            final Set<String> parametersKeys = getRuleParametersKeys();

            return RuleParameters
                .builder()
                    .addParameters(parametersKeys
                        .stream()
                            .map(key -> keyToKeyValuePair(key, pojoParameters))
                            .filter(entry -> entry.getValue().isPresent())
                            .map(AbstractRuleParametersFactory::toStringStringEntry)
                            .collect(Collectors.toMap(Entry::getKey, Entry::getValue)))
                    .build();
        }

        private Entry<String, Optional<String>> keyToKeyValuePair(final String key, final P pojoParameters) {
            return new SimpleEntry<>(key, getValueForParameter(key, pojoParameters));
        }
    }