Java tutorial
/******************************************************************************* * 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(); } }