org.eclipse.mylyn.internal.wikitext.commonmark.inlines.PotentialEmphasisDelimiter.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.mylyn.internal.wikitext.commonmark.inlines.PotentialEmphasisDelimiter.java

Source

/*******************************************************************************
 * Copyright (c) 2015 David Green.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     David Green - initial API and implementation
 *******************************************************************************/

package org.eclipse.mylyn.internal.wikitext.commonmark.inlines;

import java.util.List;

import org.eclipse.mylyn.internal.wikitext.commonmark.Line;
import org.eclipse.mylyn.wikitext.core.parser.DocumentBuilder;

import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;

class PotentialEmphasisDelimiter extends InlineWithText {

    private final boolean canOpen;

    private final boolean canClose;

    public PotentialEmphasisDelimiter(Line line, int offset, int length, String text, boolean canOpen,
            boolean canClose) {
        super(line, offset, length, text);
        this.canOpen = canOpen;
        this.canClose = canClose;
    }

    @Override
    public void emit(DocumentBuilder builder) {
        builder.characters(text);
    }

    @Override
    Optional<InlinesSubstitution> secondPass(List<Inline> inlines) {
        if (!canClose) {
            return Optional.absent();
        }
        int indexOfThis = inlines.indexOf(this);
        Optional<PotentialEmphasisDelimiter> opener = previousOpener(inlines, indexOfThis);
        if (opener.isPresent()) {
            PotentialEmphasisDelimiter openingDelimiter = opener.get();
            int delimiterSize = delimiterSize(openingDelimiter);
            int indexOfOpeningDelimiter = inlines.indexOf(openingDelimiter);

            List<Inline> contents = InlineParser
                    .secondPass(inlines.subList(indexOfOpeningDelimiter + 1, indexOfThis));

            int spanOffset = openingDelimiter.getOffset();
            int spanLength = getOffset() + getLength() - openingDelimiter.getOffset();
            Inline emphasis = createEmphasis(openingDelimiter.getLine(), spanOffset, spanLength, delimiterSize,
                    contents);

            ImmutableList.Builder<Inline> substitutionInlines = ImmutableList.builder();
            if (delimiterSize < openingDelimiter.getLength()) {
                substitutionInlines.add(createPotentialOpeningDelimiter(openingDelimiter, delimiterSize));
            }
            substitutionInlines.add(emphasis);
            if (delimiterSize < getLength()) {
                substitutionInlines.add(createPotentialClosingDelimiter(delimiterSize));
            }

            return Optional.of(new InlinesSubstitution(openingDelimiter, this, substitutionInlines.build()));
        }
        return Optional.absent();
    }

    private Inline createPotentialClosingDelimiter(int delimiterSize) {
        return new PotentialEmphasisDelimiter(getLine(), getOffset() + delimiterSize, getLength() - delimiterSize,
                getText().substring(0 + delimiterSize, getText().length()), canOpen, canClose);
    }

    private Inline createEmphasis(Line line, int offset, int length, int delimiterSize, List<Inline> contents) {
        if (delimiterSize == 1) {
            return new Emphasis(line, offset, length, contents);
        }
        return new Strong(line, offset, length, contents);
    }

    private PotentialEmphasisDelimiter createPotentialOpeningDelimiter(PotentialEmphasisDelimiter openingDelimiter,
            int consumedSize) {
        return new PotentialEmphasisDelimiter(openingDelimiter.getLine(), openingDelimiter.getOffset(),
                openingDelimiter.getLength() - consumedSize,
                openingDelimiter.getText().substring(0, openingDelimiter.getText().length() - consumedSize),
                openingDelimiter.canOpen, openingDelimiter.canClose);
    }

    private int delimiterSize(PotentialEmphasisDelimiter openingDelimiter) {
        int openingLength = openingDelimiter.getLength();
        if (openingLength < 3 || getLength() < 3) {
            return openingLength > getLength() ? getLength() : openingLength;
        }
        return getLength() % 2 == 0 ? 2 : 1;
    }

    private Optional<PotentialEmphasisDelimiter> previousOpener(List<Inline> inlines, int indexOfThis) {
        char c = getText().charAt(0);
        for (int index = indexOfThis - 1; index >= 0; --index) {
            Inline inline = inlines.get(index);
            if (inline instanceof PotentialEmphasisDelimiter) {
                PotentialEmphasisDelimiter previousDelimiter = (PotentialEmphasisDelimiter) inline;
                if (previousDelimiter.canOpen && previousDelimiter.getText().charAt(0) == c) {
                    return Optional.of(previousDelimiter);
                }
            }
        }
        return Optional.absent();
    }
}