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

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

The newest version!
package cdc.mf.html;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import org.apache.commons.text.StringEscapeUtils;

import com.vladsch.flexmark.html.HtmlRenderer;
import com.vladsch.flexmark.parser.Parser;
import com.vladsch.flexmark.util.ast.Node;
import com.vladsch.flexmark.util.data.MutableDataSet;

import cdc.graphs.impl.BasicGraphEdge;
import cdc.issues.Issue;
import cdc.issues.Meta;
import cdc.issues.rules.Rule;
import cdc.issues.rules.RuleId;
import cdc.mf.html.index.IndexSection;
import cdc.mf.model.MfClass;
import cdc.mf.model.MfConnector;
import cdc.mf.model.MfConstraint;
import cdc.mf.model.MfElement;
import cdc.mf.model.MfElementRef;
import cdc.mf.model.MfEnumeration;
import cdc.mf.model.MfInterface;
import cdc.mf.model.MfLocation;
import cdc.mf.model.MfLocationPart;
import cdc.mf.model.MfModel;
import cdc.mf.model.MfNameItem;
import cdc.mf.model.MfPackage;
import cdc.mf.model.MfQNameItem;
import cdc.mf.model.MfType;
import cdc.mf.model.MfUtils;
import cdc.util.strings.StringUtils;

public final class MfParams {
    private MfParams() {
    }

    private static final Pattern CMAPX_FIX1 = Pattern.compile(" id=\"[^\"]+\"");
    private static final Pattern CMAPX_FIX2 = Pattern.compile("\"/>");

    private static final Map, String> PUML_KIND = new HashMap<>();
    static {
        PUML_KIND.put(MfClass.class, "class");
        PUML_KIND.put(MfInterface.class, "interface");
        PUML_KIND.put(MfEnumeration.class, "enum");
        PUML_KIND.put(MfPackage.class, "package");
    }

    public static final String DEFAULT_VALID_STRING = "?";

    public static List getMetas(MfElement element) {
        return element.getMetas().getSortedMetas();
    }

    public static String validate(String s) {
        return StringUtils.isNullOrEmpty(s) ? DEFAULT_VALID_STRING : s;
    }

    public static  List sort(Collection collection,
                                   Comparator comparator) {
        return collection.stream()
                         .sorted(comparator)
                         .collect(Collectors.toList());
    }

    public static String getHtmlId(MfElement element) {
        final StringBuilder builder = new StringBuilder();
        builder.append(getKind(element));
        for (final int index : element.getIndices()) {
            builder.append('.');
            builder.append(index);
        }
        return builder.toString();
    }

    public static String getHtmlId(Issue issue,
                                   MfHtmlGenerationArgs args) {
        return "issue." + args.getNumber(issue);
    }

    public static String getHtmlId(Rule rule) {
        return getHtmlId(rule.getId());
    }

    public static String getHtmlId(RuleId ruleId) {
        return "rule." + toHashString(ruleId.toString());
    }

    public static String getId(Issue issue) {
        return "I@" + toHashString(issue.getId().toString());
    }

    public static String getId(Rule rule) {
        return "R@" + toHashString(rule.getId().toString());
    }

    public static String getHtmlId(IndexSection section) {
        return "index." + section.getNumber();

    }

    public static String getDisplayName(MfElement element) {
        if (element instanceof final MfType x) {
            return x.getTypePath().toString().replace('/', '$');
        } else if (element instanceof final MfNameItem x) {
            return validate(x.getName());
        } else {
            return DEFAULT_VALID_STRING;
        }
    }

    public static String getKind(MfElement element) {
        return MfUtils.getKind(element);
    }

    public static String getPumlKind(MfElement element) {
        return PUML_KIND.get(element.getClass());
    }

    public static String toHashString(Object object) {
        return Integer.toHexString(object.hashCode());
    }

    private static String toHtmlSpan(String cl,
                                     String text) {
        return "" + text + "";
    }

    private static String toHtmlLocationPath(MfLocation location) {
        final StringBuilder builder = new StringBuilder();
        final List parts = location.getParts();
        for (int i = 0; i < parts.size(); i++) {
            final MfLocationPart part = parts.get(i);

            if (i > 0) {
                builder.append("/");
            }
            if (i == parts.size() - 1) {
                builder.append(toHtmlSpan("location-part, location-part-last", part.toString()));
            } else {
                builder.append(toHtmlSpan("location-part", part.toString()));
            }
        }
        return builder.toString();
    }

    private static String toHtmlLocationText(MfLocation location) {
        final StringBuilder builder = new StringBuilder();
        builder.append(toHtmlSpan("location-path", toHtmlLocationPath(location)));
        if (location.hasAnchor()) {
            builder.append(toHtmlSpan("location-separator", "::"));
            builder.append(toHtmlSpan("location-anchor", location.getAnchor()));
        }
        return builder.toString();
    }

    private static String toHtmlA(String href,
                                  String target,
                                  String text) {
        final StringBuilder builder = new StringBuilder();
        builder.append("')
               .append(text)
               .append("");

        return builder.toString();
    }

    private static String getTarget(MfHtmlGenerationArgs args) {
        if (args.getHints().contains(MfHtmlGenerationHint.SINGLE_PAGE)) {
            return null;
        } else {
            return "rightFrame";
        }
    }

    private static String toHtmlRef(MfLocation location,
                                    String upPath,
                                    MfHtmlGenerationArgs args) {
        final MfElement element = location.resolve(args.getModel()).orElse(null);
        if (element == null) {
            return toHtmlLocationText(location);
        } else {
            return toHtmlA(toItemHRef(element, upPath, args),
                           getTarget(args),
                           toHtmlLocationText(location));
        }
    }

    private static String replaceLocations(String s,
                                           String upPath,
                                           MfHtmlGenerationArgs args) {
        final Matcher m = MfLocation.PATH_PATTERN.matcher(s);
        return m.replaceAll(r -> toHtmlRef(MfLocation.of(r.group(), null), upPath, args));
    }

    private static String escapeSpecial(String s) {
        if (s == null) {
            return s;
        } else {
            return s.replace("*", "\\*");
        }
    }

    public static String toHtml(String text,
                                MfHtmlGenerationArgs args) {
        if (text == null) {
            return null;
        } else {
            final MutableDataSet options = new MutableDataSet();
            options.set(HtmlRenderer.SOFT_BREAK, "
\n"); final Parser parser = Parser.builder(options).build(); final HtmlRenderer renderer = HtmlRenderer.builder(options).build(); text = args.formatDescription(text); text = StringEscapeUtils.escapeHtml4(text); text = escapeSpecial(text); final Node document = parser.parse(text); return renderer.render(document); } } public static String toHtml(String text, String upPath, MfHtmlGenerationArgs args) { final String html = toHtml(text, args); return replaceLocations(html, upPath, args); } public static String toString(File file) { return file == null ? "???" : file.getPath().replace('\\', '/'); } public static String toUrl(File file) { // try { // // TODO encode each name individually // return URLEncoder.encode(toString(file), "UTF-8"); // } catch (final UnsupportedEncodingException e) { // return toString(file); // } return toString(file).replace(" ", "%20"); } public static String toItemRef(MfElement element, MfHtmlGenerationArgs args) { // The down path if (args.getHints().contains(MfHtmlGenerationHint.SINGLE_PAGE)) { return "#" + getHtmlId(element); } else { return toString(Files.getHtmlItemFile(element, args)) + "#" + getHtmlId(element); } } public static String toItemHRef(MfElement element, String upPath, MfHtmlGenerationArgs args) { if (args.getHints().contains(MfHtmlGenerationHint.SINGLE_PAGE)) { return toItemRef(element, args); } else { return upPath + "/" + toItemRef(element, args); } } public static String toItemUrl(MfElement element, MfHtmlGenerationArgs args) { // The down path if (args.getHints().contains(MfHtmlGenerationHint.SINGLE_PAGE)) { return "#" + getHtmlId(element); } else { return toUrl(Files.getHtmlItemFile(element, args)) + "#" + getHtmlId(element); } } public static String getUpPath(MfElement element, MfHtmlGenerationArgs args) { // The up path if (args.getHints().contains(MfHtmlGenerationHint.SINGLE_PAGE)) { return "."; } else { return MfParams.toString(MfParams.Dirs.getUpPath(element, args)); } } public static String getPumlId(MfElement element) { final String id = element.getId(); final String result; if (id == null) { if (element instanceof final MfQNameItem x) { result = toHashString(x.getQName().toStringSlash()); } else { final String parentPumlId = getPumlId(element.getParent()); return parentPumlId + "_" + element.getIndex(); } } else { result = toHashString(id); } return result; } private static boolean isDisplayed(MfElementRef ref) { return ref.isValid() && ref.getElement() instanceof MfType; } public static List> getDisplayedConstrainedElementRefs(MfConstraint constraint) { return constraint.getConstrainedElementRefs() .stream() .filter(MfParams::isDisplayed) .toList(); } public static List> getLayoutLinks(MfElement element) { final List> list = new ArrayList<>(); if (element instanceof final MfPackage p) { final List sub = p.getPackages(); final int s = (int) Math.ceil(Math.sqrt(sub.size())); for (int to = 1; to < sub.size(); to++) { if (to % s != 0) { list.add(new BasicGraphEdge<>(sub.get(to - 1), sub.get(to))); } } } return list; } /** * @param pack The package. * @param args The generations arguments. * @return The number of items to be displayed in the overview image of package {@code pack}. */ public static int getItemsCount(MfPackage pack, MfHtmlGenerationArgs args) { return pack.getTypes().size() + getExternalTypes(pack, args).size(); } /** * @param type The type. * @param args The generations arguments. * @return The number of items to be displayed in the overview image of {@code type}. */ public static int getItemsCount(MfType type, MfHtmlGenerationArgs args) { return 1 + getRelatedTypes(type, args).size(); } public static List getExternalTypes(MfPackage pack, MfHtmlGenerationArgs args) { final Set set = new HashSet<>(); for (final MfType type : pack.getTypes()) { for (final MfType ancestor : type.getDirectGenitors()) { if (ancestor.getRootType().getOwningPackage() != pack) { set.add(ancestor); } } if (args.getHints().contains(MfHtmlGenerationHint.IMG_PACKAGE_OVERVIEW_SHOW_EXTERNAL_IMPLEMENTATIONS)) { for (final MfType ancestor : type.getDirectProGenitors()) { if (ancestor.getRootType().getOwningPackage() != pack) { set.add(ancestor); } } } for (final MfConnector connector : type.getConnectors()) { if (connector.getTargetTip().getTypeRef().get().getRootType().getOwningPackage() != pack) { set.add(connector.getTargetTip().getTypeRef().get()); } } } return sort(set, MfQNameItem.QNAME_COMPARATOR); } public static List getRelatedTypes(MfType type, MfHtmlGenerationArgs args) { final Set set = new HashSet<>(); for (final MfType ancestor : type.getDirectGenitors()) { set.add(ancestor); } for (final MfType ancestor : type.getDirectProGenitors()) { set.add(ancestor); } for (final MfType descendant : type.getDirectSpecializations()) { set.add(descendant); } for (final MfConnector connector : type.getConnectors()) { set.add(connector.getTargetTip().getTypeRef().get()); } for (final MfConnector connector : type.getReversedConnectors()) { set.add(connector.getSourceTip().getTypeRef().get()); } set.remove(type); return sort(set, MfQNameItem.QNAME_COMPARATOR); } public static File getCmapxFile(File basedir, String prefix, MfElement element) { return new File(basedir, Dirs.IMAGES.getPath() + "/" + prefix + getPumlId(element) + ".cmapx"); } public static boolean hasCmapx(File basedir, String prefix, MfElement element) { final File file = getCmapxFile(basedir, prefix, element); return file.exists(); } public static String loadCmapx(File basedir, String prefix, MfElement element) { final File file = getCmapxFile(basedir, prefix, element); try { String s = java.nio.file.Files.readString(file.toPath()); s = CMAPX_FIX1.matcher(s).replaceAll(""); s = CMAPX_FIX2.matcher(s).replaceAll("\">"); return s; } catch (final IOException e) { return null; } } /** * Files of images, packages, items, ... */ public static final class Files { private Files() { } private static final File HTML_ALL_PACKAGES = new File("all-packages.html"); private static final File HTML_ALL_ITEMS = new File("all-items.html"); private static final File HTML_FRAMES = new File("index.html"); private static final File HTML_ISSUES = new File("issues.html"); private static final File HTML_OVERVIEW = new File("overview.html"); private static final File HTML_PROFILE = new File("profile.html"); private static final File HTML_SINGLE = new File("single.html"); public static File getHtmlSinglePageFile() { return HTML_SINGLE; } /** * @return The file used for the HTML frame listing all packages. */ public static File getHtmlAllPackagesFile() { return HTML_ALL_PACKAGES; } /** * @return The file used for the HTML frame listing all items. */ public static File getHtmlAllItemsFile() { return HTML_ALL_ITEMS; } /** * @return The file used for the HTML index. */ public static File getHtmlFramesFile() { return HTML_FRAMES; } /** * @return The file used for the model issues HTML frame. */ public static File getHtmlIssuesFile() { return HTML_ISSUES; } /** * @return The file used for the model profile HTML frame. */ public static File getHtmlProfileFile() { return HTML_PROFILE; } /** * @return The file used for the model overview HTML frame. */ public static File getHtmlOverviewFile() { return HTML_OVERVIEW; } /** * @param item The model. * @param type The image type. * @return The file used for the model overview image. */ public static File getImgOverviewFile(MfModel item, ImageType type) { return new File(Dirs.IMAGES.getPath(), "model-overview-" + getPumlId(item) + "." + type.getExt()); } /** * @param pack The package. * @param args The generation arguments. * @return The file used for the frame listing items of the {@code pack} package. */ public static File getHtmlPackageItemsFile(MfPackage pack, MfHtmlGenerationArgs args) { return new File(Dirs.getPackageDir(pack, args), "package-items.html"); } /** * @param pack The package. * @param args The generation arguments. * @return The file used for the {@code pack} package overview frame. */ public static File getHtmlPackageOverviewFile(MfPackage pack, MfHtmlGenerationArgs args) { return new File(Dirs.getPackageDir(pack, args), "package-overview.html"); } /** * @param item The package. * @param type The image type. * @return The file used for the {@code pack} package overview image. */ public static File getImgPackageOverviewFile(MfPackage item, ImageType type) { return new File(Dirs.IMAGES.getPath(), "package-overview-" + getPumlId(item) + "." + type.getExt()); } public static File getImgTypeOverviewFile(MfType item, ImageType type) { return new File(Dirs.IMAGES.getPath(), "type-overview-" + getPumlId(item) + "." + type.getExt()); } /** * @param element The element. * @param args The generation arguments. * @return The file used for the {@code element} overview frame. */ public static File getHtmlItemFile(MfElement element, MfHtmlGenerationArgs args) { if (element instanceof final MfPackage e) { return getHtmlPackageOverviewFile(e, args); } else if (element instanceof MfModel) { return HTML_OVERVIEW; } else if (element instanceof final MfType e) { return new File(Dirs.getPackageDir(e.getRootType().getOwningPackage(), args), getDisplayName(element) + ".html"); } else { // Recurse on parent return getHtmlItemFile(element.getParent(), args); } } public static File getHtmlIndexFile(char key, MfHtmlGenerationArgs args) { final IndexSection section = args.getIndex().getSection(key); return new File(Dirs.INDEX, "index-" + section.getNumber() + ".html"); } } /** * Names of parameters passed to ST4 templates. */ public static final class Names { private Names() { } public static final String ARGS = "args"; public static final String CLASSES = "classes"; public static final String ENUMERATIONS = "enumerations"; public static final String HINTS = "hints"; public static final String INTERFACES = "interfaces"; public static final String ISSUES = "issues"; public static final String LTOR = "ltor"; public static final String MODEL = "model"; public static final String PACKAGE = "package"; public static final String PROFILE = "profile"; public static final String SECTION = "section"; public static final String SNAPSHOT = "snapshot"; public static final String TYPE = "type"; } /** * Directories containing images, packages and items. */ public static final class Dirs { private Dirs() { } /** Relative directory containing images. */ public static final File IMAGES = new File("images"); /** Relative root directory where data related to packages are placed. */ public static final File PACKAGES = new File("packages"); /** Relative directory where index files are placed. */ public static final File INDEX = new File("index-files"); private static final File IMAGES_UP_PATH = new File(".."); /** * * @param pack The package. * @param args The generation arguments. * @return The relative directory used for {@code pack}. */ public static File getPackageDir(MfPackage pack, MfHtmlGenerationArgs args) { if (args.getHints().contains(MfHtmlGenerationHint.FLAT_DIRS)) { return new File(PACKAGES.getPath(), toHashString(pack.getQName().toRelative().toStringSlash())); } else { return new File(PACKAGES.getPath(), pack.getQName().toRelative().toString()); } } /** * @param element The element. * @param args The generation arguments. * @return The up path corresponding to the HTML file of {@code element}. */ public static File getUpPath(MfElement element, MfHtmlGenerationArgs args) { final File file = Files.getHtmlItemFile(element, args); if (file == null) { return null; } else { final StringBuilder builder = new StringBuilder(); File index = file.getParentFile(); while (index != null) { if (builder.length() > 0) { builder.append('/'); } builder.append(".."); index = index.getParentFile(); } if (builder.length() == 0) { builder.append('.'); } return new File(builder.toString()); } } public static File getImgUpPath(MfElement element, MfHtmlGenerationArgs args) { return IMAGES_UP_PATH; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy