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

info.bliki.wiki.filter.WPList Maven / Gradle / Ivy

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

import info.bliki.wiki.model.Configuration;
import info.bliki.wiki.model.IWikiModel;
import info.bliki.wiki.tags.WPTag;
import info.bliki.wiki.tags.util.TagStack;

import java.io.IOException;
import java.util.ArrayList;

/**
 * Represents a Wikipedia list. See http://meta.wikimedia.org/wiki/Help:List
 *
 * @see info.bliki.wiki.filter.WPListElement
 *
 */
public class WPList extends WPTag implements PlainTextConvertable {
    public final static char DL_DD_CHAR = ':';
    public final static char DL_DT_CHAR = ';';
    public final static char OL_CHAR = '#';
    public final static char UL_CHAR = '*';
    // public final static char DL_CHAR = '+';

    private char[] fLastSequence;

    private InternalList fNestedElements;

    private ArrayList fInternalListStack;

    public static class InternalList extends ArrayList {

        /**
         *
         */
        private static final long serialVersionUID = -3760843632697162014L;

        char fChar;

        public char getChar() {
            return fChar;
        }

        public InternalList(char ch) {
            super();
            fChar = ch;
        }
    }

    public WPList() {
        super("*#:;");
        fLastSequence = null;
        fNestedElements = null;
        fInternalListStack = new ArrayList<>();
    }

    public boolean isEmpty() {
        return fNestedElements == null;
    }

    public boolean add(WPListElement listElement) {
        char[] sequence = listElement.getSequence();
        int s1Length = 0;
        int s2Length = sequence.length;
        if (fLastSequence != null) {
            s1Length = fLastSequence.length;
        } else {
            fNestedElements = new InternalList(sequence[0]);
            fInternalListStack.add(fNestedElements);
        }
        InternalList list;
        int min;
        int level;
        if (s1Length > s2Length) {
            min = s2Length;
        } else {
            min = s1Length;
        }
        level = min;
        for (int i = 0; i < min; i++) {
            if (sequence[i] != fLastSequence[i]) {
                if ((sequence[i] == DL_DT_CHAR || sequence[i] == DL_DD_CHAR)
                        && (fLastSequence[i] == DL_DT_CHAR || fLastSequence[i] == DL_DD_CHAR)) {
                    continue;
                }
                level = i;
                break;
            }
        }

        popListStack(level);

        if (level < s2Length) {
            // push stack
            for (int i = level; i < s2Length; i++) {
                list = new InternalList(sequence[i]);
                fInternalListStack.get(fInternalListStack.size() - 1).add(list);
                fInternalListStack.add(list);
            }
        }
        fInternalListStack.get(fInternalListStack.size() - 1).add(listElement);

        fLastSequence = sequence;
        return true;
    }

    private void popListStack(int level) {
        if (fInternalListStack.size() > level) {
            for (int i = fInternalListStack.size() - 1; i > level; i--) {
                fInternalListStack.remove(i);
            }
        }
    }

    @Override
    public void renderHTML(ITextConverter converter, Appendable buf, IWikiModel wikiModel) throws IOException {
        if (!isEmpty()) {
            fInternalListStack = null;

            for (Object element : fNestedElements) {
                if (element instanceof InternalList) {
                    InternalList subList = (InternalList) element;
                    beginHTMLTag(buf, subList);
                    renderSubListHTML(subList, converter, buf, wikiModel);
                    if (NEW_LINES) {
                        buf.append('\n');
                    }
                    if (subList.fChar == UL_CHAR) {
                        // bullet list
                        buf.append("");
                    } else if (subList.fChar == OL_CHAR) {
                        // numbered list
                        buf.append("");
                    } else {
                        // definition list
                        buf.append("");
                    }
                } else {
                    TagStack stack = ((WPListElement) element).getTagStack();
                    if (stack != null) {
                        converter.nodesToText(stack.getNodeList(), buf, wikiModel);
                    }
                }
            }
        }
    }

    private void beginHTMLTag(Appendable buf, InternalList subList) throws IOException {
        if (NEW_LINES) {
            buf.append('\n');
        }
        if (subList.fChar == UL_CHAR) {
            // bullet list
            buf.append("
    "); } else if (subList.fChar == OL_CHAR) { // numbered list buf.append("
      "); } else { // definition list buf.append("
      "); } } private void endHTMLTag(Appendable buf, InternalList subList) throws IOException { if (NEW_LINES) { buf.append('\n'); } if (subList.fChar == UL_CHAR) { // bullet list buf.append("
"); } else if (subList.fChar == OL_CHAR) { // numbered list buf.append(""); } else { // definition list buf.append(""); } } private void renderSubListHTML(InternalList list, ITextConverter converter, Appendable buf, IWikiModel wikiModel) throws IOException { if (list.size() == 0) { return; } char currentChar = list.fChar; char lastChar; if (currentChar == DL_DD_CHAR) { buf.append("\n
"); } else if (currentChar == DL_DT_CHAR) { buf.append("\n
"); } else { buf.append("\n
  • "); } for (int i = 0; i < list.size(); i++) { Object element = list.get(i); if (element instanceof InternalList) { InternalList subList = (InternalList) element; beginHTMLTag(buf, subList); // recursive call: renderSubListHTML(subList, converter, buf, wikiModel); endHTMLTag(buf, subList); } else { TagStack stack = ((WPListElement) element).getTagStack(); if (stack != null) { converter.nodesToText(stack.getNodeList(), buf, wikiModel); } } if ((i < list.size() - 1) && list.get(i + 1) instanceof WPListElement) { lastChar = currentChar; char[] temp = ((WPListElement) list.get(i + 1)).getSequence(); currentChar = temp[temp.length - 1]; switch (lastChar) { case DL_DD_CHAR: buf.append(""); break; case DL_DT_CHAR: buf.append("
  • "); break; default: buf.append(""); break; } if (NEW_LINES) { buf.append('\n'); } switch (currentChar) { case DL_DD_CHAR: buf.append("
    "); break; case DL_DT_CHAR: buf.append("
    "); break; default: buf.append("
  • "); break; } } } if (currentChar == DL_DD_CHAR) { buf.append(""); } else if (currentChar == DL_DT_CHAR) { buf.append("
  • "); } else { buf.append(""); } } @SuppressWarnings("unchecked") @Override public Object clone() { WPList tt = (WPList) super.clone(); if (fNestedElements == null) { tt.fNestedElements = null; } else { tt.fNestedElements = (InternalList) this.fNestedElements.clone(); } tt.fInternalListStack = (ArrayList) this.fInternalListStack.clone(); if (fLastSequence == null) { tt.fLastSequence = null; } else { tt.fLastSequence = new char[this.fLastSequence.length]; System.arraycopy(this.fLastSequence, 0, tt.fLastSequence, 0, this.fLastSequence.length); } return tt; } @Override public boolean isReduceTokenStack() { return true; } @Override public String getParents() { return Configuration.SPECIAL_BLOCK_TAGS; } public InternalList getNestedElements() { return fNestedElements; } private void renderSubListPlainText(InternalList list, ITextConverter converter, Appendable buf, IWikiModel wikiModel) throws IOException { if (list.size() > 0) { buf.append("\n");//
  • "); } for (int i = 0; i < list.size(); i++) { Object element = list.get(i); if (element instanceof InternalList) { InternalList subList = (InternalList) element; // beginHTMLTag(buf, subList); // recursive call: renderSubListPlainText(subList, converter, buf, wikiModel); // endHTMLTag(buf, subList); } else { TagStack stack = ((WPListElement) element).getTagStack(); if (stack != null) { converter.nodesToText(stack.getNodeList(), buf, wikiModel); } } if ((i < list.size() - 1) && list.get(i + 1) instanceof WPListElement) { if (NEW_LINES) { buf.append("\n"); } } } } @Override public void renderPlainText(ITextConverter converter, Appendable buf, IWikiModel wikiModel) throws IOException { if (!isEmpty()) { fInternalListStack = null; for (Object element : fNestedElements) { if (element instanceof InternalList) { InternalList subList = (InternalList) element; renderSubListPlainText(subList, converter, buf, wikiModel); } else { TagStack stack = ((WPListElement) element).getTagStack(); if (stack != null) { converter.nodesToText(stack.getNodeList(), buf, wikiModel); } } } if (NEW_LINES) { buf.append("\n"); } } } private void toStringSubList(InternalList list, Appendable buf) throws IOException { for (Object element : list) { if (element instanceof InternalList) { InternalList subList = (InternalList) element; buf.append(subList.fChar); buf.append("-"); toStringSubList(subList, buf); } else { buf.append(element.toString()); buf.append("\n"); } } } @Override public String toString() { if (!isEmpty()) { try { StringBuilder buf = new StringBuilder(fNestedElements.size() * 32); for (Object element : fNestedElements) { if (element instanceof InternalList) { InternalList subList = (InternalList) element; buf.append(subList.fChar); buf.append("-"); toStringSubList(subList, buf); } else { buf.append(element.toString()); buf.append("\n"); } } return buf.toString(); } catch (IOException e) { return "IOException"; } } return ""; } }