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

info.bliki.wiki.model.WikiModel Maven / Gradle / Ivy

The newest version!
package info.bliki.wiki.model;

import info.bliki.Messages;
import info.bliki.htmlcleaner.ContentToken;
import info.bliki.htmlcleaner.TagToken;
import info.bliki.wiki.filter.Encoder;
import info.bliki.wiki.filter.HTMLConverter;
import info.bliki.wiki.filter.ITextConverter;
import info.bliki.wiki.filter.WikipediaPreTagParser;
import info.bliki.wiki.namespaces.INamespace;
import info.bliki.wiki.tags.HTMLTag;
import info.bliki.wiki.tags.PTag;
import info.bliki.wiki.tags.WPATag;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import static info.bliki.wiki.model.IConfiguration.Casing.FirstLetter;
import static info.bliki.wiki.tags.WPATag.ANCHOR;
import static info.bliki.wiki.tags.WPATag.CLASS;
import static info.bliki.wiki.tags.WPATag.HREF;
import static info.bliki.wiki.tags.WPATag.TITLE;
import static info.bliki.wiki.tags.WPATag.WIKILINK;

/**
 * Standard model implementation.
 */
public class WikiModel extends AbstractWikiModel {
    /**
     * A map for categories and their associated sort keys
     */
    protected Map categories;
    protected Set links;
    protected Set templates;
    protected Set includes;
    protected List semanticRelations;
    protected List semanticAttributes;

    private String fExternalImageBaseURL;
    private String fExternalWikiBaseURL;

    /**
     * @param imageBaseURL a url string which must contains a "${image}"
     *                     variable which will be replaced by the image name, to create
     *                     links to images.
     * @param linkBaseURL  a url string which must contains a "${title}"
     *                     variable which will be replaced by the topic title, to create
     *                     links to other wiki topics.
     */
    public WikiModel(String imageBaseURL, String linkBaseURL) {
        this(new Configuration(), imageBaseURL, linkBaseURL);
    }

    public WikiModel(Configuration configuration, String imageBaseURL, String linkBaseURL) {
        super(configuration);
        fExternalImageBaseURL = imageBaseURL;
        fExternalWikiBaseURL = linkBaseURL;
    }

    public WikiModel(Configuration configuration, Locale locale, String imageBaseURL, String linkBaseURL) {
        super(configuration, locale);
        fExternalImageBaseURL = imageBaseURL;
        fExternalWikiBaseURL = linkBaseURL;
    }

    public WikiModel(Configuration configuration, Locale locale, INamespace namespace, String imageBaseURL, String linkBaseURL) {
        super(configuration, locale, namespace);
        fExternalImageBaseURL = imageBaseURL;
        fExternalWikiBaseURL = linkBaseURL;
    }

    @Override
    public void addCategory(String categoryName, String sortKey) {
        categories.put(categoryName, sortKey);
    }

    @Override
    public void addLink(String topicName) {
        links.add(topicName);
    }

    @Override
    public boolean addSemanticAttribute(String attribute, String attributeValue) {
        if (semanticAttributes == null) {
            semanticAttributes = new ArrayList<>();
        }
        semanticAttributes
                .add(new SemanticAttribute(attribute, attributeValue));
        return true;
    }

    @Override
    public boolean addSemanticRelation(String relation, String relationValue) {
        if (semanticRelations == null) {
            semanticRelations = new ArrayList<>();
        }
        semanticRelations.add(new SemanticRelation(relation, relationValue));
        return true;
    }

    @Override
    public void addTemplate(String template) {
        templates.add(template);
    }

    @Override
    public void addInclude(String pageName) {
        includes.add(pageName);
    }

    @Override
    public void appendInternalLink(String topic, String hashSection,
                                   String topicDescription, String cssClass,
                                   boolean parseRecursive) {
        appendInternalLink(topic, hashSection, topicDescription, cssClass, parseRecursive, true);
    }

    protected void appendInternalLink(final String topic,
                                      final String hashSection,
                                      final String topicDescription, String cssClass,
                                      boolean parseRecursive, boolean topicExists) {
        String hrefLink;
        String description = topicDescription.trim();
        WPATag aTagNode = new WPATag();

        if (topic.length() > 0) {
            String title = Encoder.normaliseTitle(topic, true, ' ', casing() == FirstLetter);
            if (hashSection == null) {
                String pageName = Encoder.normaliseTitle(fPageTitle, true, ' ', true);
                // self link?
                if (title.equals(pageName)) {
                    HTMLTag selfLink = new HTMLTag("strong");
                    selfLink.addAttribute("class", "selflink", false);
                    pushNode(selfLink);
                    selfLink.addChild(new ContentToken(description));
                    popNode();
                    return;
                }
            }

            String encodedTopic = encodeTitleToUrl(topic, casing() == FirstLetter);
            if (replaceColon()) {
                encodedTopic = encodedTopic.replace(':', '/');
            }
            hrefLink = getWikiBaseURL().replace("${title}", encodedTopic);
            if (!topicExists) {
                if (cssClass == null) {
                    cssClass = "new";
                }
                if (hrefLink.indexOf('?') != -1) {
                    hrefLink += "&";
                } else {
                    hrefLink += "?";
                }
                hrefLink += "action=edit&redlink=1";
                String redlinkString = Messages.getString(getResourceBundle(),
                        Messages.WIKI_TAGS_RED_LINK,
                        "${title} (page does not exist)");
                title = redlinkString.replace("${title}", title);
            }
            aTagNode.addAttribute(TITLE, title, true);
        } else {
            // assume, the own topic exists
            if (hashSection != null) {
                hrefLink = "";
                if (description.length() == 0) {
                    description = "#" + hashSection; // #....
                }
            } else {
                hrefLink = getWikiBaseURL().replace("${title}", "");
            }
        }

        String href = hrefLink;
        if (topicExists && hashSection != null) {
            aTagNode.addObjectAttribute(ANCHOR, hashSection);
            href = href + '#' + encodeTitleDotUrl(hashSection, false);
        }
        aTagNode.addAttribute(HREF, href, true);
        if (cssClass != null) {
            aTagNode.addAttribute(CLASS, cssClass, true);
        }
        aTagNode.addObjectAttribute(WIKILINK, topic);

        pushNode(aTagNode);
        if (parseRecursive) {
            WikipediaPreTagParser.parseRecursive(description, this, false, true);
        } else {
            aTagNode.addChild(new ContentToken(description));
        }
        popNode();
    }

    /**
     * Get the set of Wikipedia category names used in this text
     *
     * @return the set of category strings
     */
    public Map getCategories() {
        return categories;
    }

    /**
     * Get the set of Wikipedia links used in this text
     *
     * @return the set of category strings
     */
    @Override
    public Set getLinks() {
        return links;
    }

    @Override
    public List getSemanticAttributes() {
        return semanticAttributes;
    }

    @Override
    public List getSemanticRelations() {
        return semanticRelations;
    }

    /**
     * Gets the names of all included pages in the template namespace.
     *
     * @return page names without the template namespace prefix
     */
    public Set getTemplates() {
        return templates;
    }

    /**
     * Gets the names of all included pages outside the template namespace.
     *
     * @return page names including their namespace prefix
     */
    public Set getIncludes() {
        return includes;
    }

    /**
     * Append the internal wiki image link to this model.
     *
     * 
*
* Note: the pipe symbol (i.e. "|") splits the * rawImageLink into different segments. The first segment is * used as the <image-name> and typically ends with * extensions like .png, .gif, .jpg * or .jpeg. * *
*
* Note: if the image link contains a "width" attribute, the filename * is constructed as <size>px-<image-name>, * otherwise it's only the <image-name>. * *
*
* See Image markup * and see Help:Images * * @param imageNamespace * the image namespace * @param rawImageLink * the raw image link text without the surrounding * [[...]] */ @Override public void parseInternalImageLink(String imageNamespace, String rawImageLink) { String imageSrc = getImageBaseURL(); if (imageSrc != null) { String imageHref = getWikiBaseURL(); ImageFormat imageFormat = ImageFormat.getImageFormat(rawImageLink, imageNamespace); String imageName = createImageName(imageFormat); String link = imageFormat.getLink(); if (link != null) { if (link.length() == 0) { imageHref = ""; } else { String encodedTitle = encodeTitleToUrl(link, true); imageHref = imageHref.replace("${title}", encodedTitle); } } else { if (replaceColon()) { imageHref = imageHref.replace("${title}", imageNamespace + '/' + imageName); } else { imageHref = imageHref.replace("${title}", imageNamespace + ':' + imageName); } } imageSrc = imageSrc.replace("${image}", imageName); String type = imageFormat.getType(); TagToken tag = null; if ("thumb".equals(type) || "frame".equals(type)) { if (fTagStack.size() > 0) { tag = peekNode(); } reduceTokenStack(Configuration.HTML_DIV_OPEN); } appendInternalImageLink(imageHref, imageSrc, imageFormat); if (tag instanceof PTag) { pushNode(new PTag()); } } } protected String createImageName(ImageFormat imageFormat) { String imageName = imageFormat.getFilename(); String sizeStr = imageFormat.getWidthStr(); if (sizeStr != null) { imageName = sizeStr + '-' + imageName; } if (imageName.endsWith(".svg")) { imageName += ".png"; } imageName = Encoder.encodeUrl(imageName); if (replaceColon()) { imageName = imageName.replace(':', '/'); } return imageName; } @Override public boolean replaceColon() { return false; } @Override public void setUp() { super.setUp(); categories = new HashMap<>(); links = new HashSet<>(); templates = new HashSet<>(); includes = new HashSet<>(); semanticRelations = null; semanticAttributes = null; } /** * */ @Override public INamespace getNamespace() { return fNamespace; } /** * Convert a given text in wiki notation into another format. * * @param model * a wiki model * @param converter * a text converter. Note the converter may be * null, if you only would like to analyze the raw * wiki text and don't need to convert. This speeds up the * parsing process. * @param rawWikiText * a raw wiki text * @param resultBuffer * the buffer to which to append the resulting HTML code. * @param templateTopic * if true, render the wiki text as if a template * topic will be displayed directly, otherwise render the text as * if a common wiki topic will be displayed. * @param parseTemplates * parses the template expansion step (parses include, * onlyinclude, includeonly etc) * @throws IOException */ public static void toText(IWikiModel model, ITextConverter converter, String rawWikiText, Appendable resultBuffer, boolean templateTopic, boolean parseTemplates) throws IOException { model.render(converter, rawWikiText, resultBuffer, templateTopic, parseTemplates); } /** * Convert a given text in wiki notation into HTML text. * * @param rawWikiText * a raw wiki text * @param resultBuffer * the buffer to which to append the resulting HTML code. * @param imageBaseURL * a url string which must contains a "${image}" * variable which will be replaced by the image name, to create * links to images. * @param linkBaseURL * a url string which must contains a "${title}" * variable which will be replaced by the topic title, to create * links to other wiki topics. * @throws IOException */ public static void toHtml(String rawWikiText, Appendable resultBuffer, String imageBaseURL, String linkBaseURL) throws IOException { toText(new WikiModel(imageBaseURL, linkBaseURL), new HTMLConverter(), rawWikiText, resultBuffer, false, false); } /** * Convert a given text in wiki notation into HTML text. * * @param rawWikiText * a raw wiki text * @param resultBuffer * the buffer to which to append the resulting HTML code. * @throws IOException */ public static void toHtml(String rawWikiText, Appendable resultBuffer) throws IOException { toText(new WikiModel("/${image}", "/${title}"), new HTMLConverter(), rawWikiText, resultBuffer, false, false); } /** * Convert a given text in wiki notation into HTML text. * * @param rawWikiText * a raw wiki text * @return the resulting HTML text; nay returns null, if an * IOException occured. */ public static String toHtml(String rawWikiText) { try { StringBuilder resultBuffer = new StringBuilder(rawWikiText.length() + rawWikiText.length() / 10); toText(new WikiModel("/${image}", "/${title}"), new HTMLConverter(), rawWikiText, resultBuffer, false, false); return resultBuffer.toString(); } catch (IOException ignored) { } return null; } @Override public String getImageBaseURL() { return fExternalImageBaseURL; } @Override public String getWikiBaseURL() { return fExternalWikiBaseURL; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy