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

cdc.mf.html.MfHtmlGenerationArgs Maven / Gradle / Ivy

There is a newer version: 0.42.0
Show newest version
package cdc.mf.html;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import cdc.issues.Issue;
import cdc.issues.IssueSeverity;
import cdc.issues.io.SnapshotData;
import cdc.issues.locations.Location;
import cdc.issues.rules.Profile;
import cdc.issues.rules.Rule;
import cdc.issues.rules.RuleId;
import cdc.mf.Config;
import cdc.mf.html.index.Index;
import cdc.mf.model.MfElement;
import cdc.mf.model.MfLocation;
import cdc.mf.model.MfModel;
import cdc.mf.model.MfPackage;
import cdc.util.lang.Checks;

/**
 * Arguments used to configure HTML generation, including images.
 *
 * @author Damien Carbonne
 */
public final class MfHtmlGenerationArgs {
    public static final int DEFAULT_LTOR_THRESHOLD = 25;
    public static final int DEFAULT_LAYOUT_DEPTH = 5;

    /** The base directory for HTML generation. */
    private final File baseDir;
    /** The model for which HTML is generated. */
    private final MfModel model;
    private final SnapshotData snapshot;
    /** The associated issues. */
    private final List issues;
    /** The profile associated to issues. */
    private final Profile profile;
    /** The left to right threshold. */
    private final int ltorThreshold;
    /** The maximum depth for layout. */
    private final int layoutDepth;
    /** The generation boolean hints. */
    private final Set hints;
    /** The packages that are ignored in model overview image. */
    private final Predicate modelOverviewIgnoredPackages;
    /** The pattern of name parts that must be removed. */
    private final List nameRemovedParts = new ArrayList<>();

    private final Map> elementToIssues = new HashMap<>();
    private final Map issueToNumber = new HashMap<>();
    private final Map> ruleIdToIssues = new HashMap<>();
    private final Index index;

    private MfHtmlGenerationArgs(Builder builder) {
        this.baseDir = Checks.isNotNull(builder.baseDir, "baseDir");
        this.model = Checks.isNotNull(builder.model, "model");
        this.snapshot = builder.snapshot;
        this.issues = Checks.isNotNull(builder.issues, "issues");
        this.profile = builder.profile;
        this.ltorThreshold = builder.ltorThreshold;
        this.layoutDepth = builder.layoutDepth;
        this.hints = builder.hints;
        this.modelOverviewIgnoredPackages = pack -> {
            for (final Pattern p : builder.modelOverviewIgnoredPackages) {
                if (p.matcher(pack.getQName().toStringSlash()).matches()) {
                    return true;
                }
            }
            return false;
        };
        this.nameRemovedParts.addAll(builder.nameRemovedParts);

        // Associate issues to elements, rules, and number them
        int number = 0;
        for (final Issue issue : issues) {
            number++;
            issueToNumber.put(issue, number);
            for (final Location location : issue.getLocations()) {
                if (location instanceof final MfLocation mflocation) {
                    final MfElement ref = mflocation.resolve(model).orElse(model);
                    final List list = elementToIssues.computeIfAbsent(ref, k -> new ArrayList<>());
                    list.add(issue);
                }
            }
            final List list = ruleIdToIssues.computeIfAbsent(issue.getRuleId(), k -> new ArrayList<>());
            list.add(issue);
        }

        this.index = new Index(this.model);
    }

    public File getBaseDir() {
        return baseDir;
    }

    public MfModel getModel() {
        return model;
    }

    public SnapshotData getSnapshot() {
        return snapshot;
    }

    public List getIssues() {
        return issues;
    }

    public Profile getProfile() {
        return profile;
    }

    public Index getIndex() {
        return index;
    }

    @SuppressWarnings("static-method")
    public String getConfigVersion() {
        return Config.VERSION;
    }

    /**
     * @param element The element.
     * @return The issues directly associated to {@code element}.
     */
    public List getIssues(MfElement element) {
        return elementToIssues.getOrDefault(element, Collections.emptyList());
    }

    private static IssueSeverity max(IssueSeverity x,
                                     IssueSeverity y) {
        if (x == null) {
            return y;
        } else if (y == null) {
            return x;
        } else {
            return IssueSeverity.max(x, y);
        }
    }

    public IssueSeverity getMaxIssueSeverity(MfElement element) {
        IssueSeverity max = null;
        for (final Issue issue : getIssues(element)) {
            max = max(max, issue.getSeverity());
        }
        return max;
    }

    /**
     * @param issue The issue.
     * @return The number associated to {@code issue}.
     */
    public int getNumber(Issue issue) {
        return issueToNumber.getOrDefault(issue, -1);
    }

    /**
     * @param element The element.
     * @return {@code true} if {@code element} or one of its children, recursively, has issues.
     */
    public boolean hasDeepIssues(MfElement element) {
        if (!getIssues(element).isEmpty()) {
            return true;
        } else {
            for (final MfElement child : element.getChildren()) {
                if (hasDeepIssues(child)) {
                    return true;
                }
            }
            return false;
        }
    }

    public IssueSeverity getDeepMaxIssueSeverity(MfElement element) {
        IssueSeverity max = getMaxIssueSeverity(element);
        for (final MfElement child : element.getChildren()) {
            max = max(max, getMaxIssueSeverity(child));
        }
        return max;
    }

    public List getIssues(Rule rule) {
        return ruleIdToIssues.getOrDefault(rule.getId(), Collections.emptyList());
    }

    public boolean hasIssues(Rule rule) {
        return ruleIdToIssues.containsKey(rule.getId());
    }

    public int getLtorThreshold() {
        return ltorThreshold;
    }

    public int getLayoutDepth() {
        return layoutDepth;
    }

    public Set getHints() {
        return hints;
    }

    public Predicate getModelOverviewIgnoredPackages() {
        return modelOverviewIgnoredPackages;
    }

    public String simplifyName(String name) {
        if (nameRemovedParts.isEmpty()) {
            return name;
        } else {
            String s = name;
            for (final Pattern pattern : nameRemovedParts) {
                final Matcher m = pattern.matcher(s);
                s = m.replaceAll("");
            }
            return s;
        }
    }

    public static Builder builder() {
        return new Builder();
    }

    public static class Builder {
        private File baseDir;
        private MfModel model;
        private SnapshotData snapshot;
        private final List issues = new ArrayList<>();
        private Profile profile;
        private int ltorThreshold = DEFAULT_LTOR_THRESHOLD;
        private int layoutDepth = DEFAULT_LAYOUT_DEPTH;
        private final Set hints = EnumSet.noneOf(MfHtmlGenerationHint.class);
        private final List modelOverviewIgnoredPackages = new ArrayList<>();
        private final List nameRemovedParts = new ArrayList<>();

        protected Builder() {
        }

        public Builder baseDir(File baseDir) {
            this.baseDir = baseDir;
            return this;
        }

        public Builder model(MfModel model) {
            this.model = model;
            return this;
        }

        public Builder snapshot(SnapshotData snapshot) {
            this.snapshot = snapshot;
            return this;
        }

        public Builder issues(List issues) {
            this.issues.addAll(issues);
            return this;
        }

        public Builder profile(Profile profile) {
            this.profile = profile;
            return this;
        }

        public Builder ltorThreshold(int ltorThreshold) {
            this.ltorThreshold = ltorThreshold;
            return this;
        }

        public Builder layoutDepth(int layoutDepth) {
            this.layoutDepth = layoutDepth;
            return this;
        }

        public Builder hint(MfHtmlGenerationHint hint) {
            this.hints.add(hint);
            return this;
        }

        public Builder hint(MfHtmlGenerationHint hint,
                            boolean enabled) {
            if (enabled) {
                this.hints.add(hint);
            } else {
                this.hints.remove(hint);
            }
            return this;
        }

        public Builder modelOverviewIgnoredPackage(Pattern pattern) {
            this.modelOverviewIgnoredPackages.add(pattern);
            return this;
        }

        public Builder modelOverviewIgnoredPackage(String pattern) {
            return modelOverviewIgnoredPackage(Pattern.compile(pattern));
        }

        public Builder modelOverviewIgnoredPackages(List patterns) {
            this.modelOverviewIgnoredPackages.addAll(patterns);
            return this;
        }

        public Builder nameRemovedPart(Pattern pattern) {
            this.nameRemovedParts.add(pattern);
            return this;
        }

        public Builder nameRemovedPart(String pattern) {
            return nameRemovedPart(Pattern.compile(pattern));
        }

        public Builder nameRemovedParts(List patterns) {
            this.nameRemovedParts.addAll(patterns);
            return this;
        }

        public MfHtmlGenerationArgs build() {
            return new MfHtmlGenerationArgs(this);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy