blob: a3d8d802e75245147ae83a90f7dc2befbc72604b [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2014, 2018 Stephan Wahlbrink and others.
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License 2.0 which is available at
# https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
# which is available at https://www.apache.org/licenses/LICENSE-2.0.
#
# SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
#
# Contributors:
# Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
#=============================================================================*/
package org.eclipse.statet.docmlet.wikitext.core.source;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.mylyn.wikitext.parser.Attributes;
import org.eclipse.statet.jcommons.text.core.TextRegion;
import org.eclipse.statet.ecommons.text.core.treepartitioner.ITreePartitionNode;
import org.eclipse.statet.ecommons.text.core.treepartitioner.ITreePartitionNodeScan;
import org.eclipse.statet.ecommons.text.core.treepartitioner.ITreePartitionNodeScan.BreakException;
import org.eclipse.statet.ecommons.text.core.treepartitioner.ITreePartitionNodeScanner;
import org.eclipse.statet.ecommons.text.core.treepartitioner.ITreePartitionNodeType;
import org.eclipse.statet.ecommons.text.core.treepartitioner.WrappedPartitionScan;
import org.eclipse.statet.docmlet.wikitext.core.markup.IMarkupLanguage;
import org.eclipse.statet.docmlet.wikitext.core.markup.MarkupParser2;
public class WikitextWeavePartitionNodeScanner extends WikitextPartitionNodeScanner {
protected class Embedding {
private final EmbeddingAttributes attributes;
protected ITreePartitionNode node;
protected int contentStartOffset;
protected int contentEndOffset;
private Embedding(final EmbeddingAttributes attributes) {
this.attributes= attributes;
}
public EmbeddingAttributes getAttributes() {
return this.attributes;
}
public String getForeignType() {
return this.attributes.getForeignType();
}
public void init(final ITreePartitionNode node) {
this.node= node;
final TextRegion contentRegion= this.attributes.getContentRegion();
if (contentRegion != null) {
this.contentStartOffset= getStartOffset() + contentRegion.getStartOffset();
this.contentEndOffset= getStartOffset() + contentRegion.getEndOffset();
}
else {
this.contentStartOffset= getStartOffset();
this.contentEndOffset= -1;
}
}
public void setContentStartOffset(final int offset) {
this.contentStartOffset= offset;
}
public void setContentEndOffset(final int offset) {
this.contentEndOffset= offset;
}
public ITreePartitionNode getNode() {
return this.node;
}
public int getContentStartOffset() {
return this.contentStartOffset;
}
public int getContentEndOffset() {
return this.contentEndOffset;
}
public void executeForeignScanner(final ITreePartitionNodeScanner scanner) {
final WrappedPartitionScan scan= getForeignScan();
scan.init(this.contentStartOffset, this.contentEndOffset, this.node);
scanner.execute(scan);
scan.exit();
}
}
private WrappedPartitionScan foreignScan;
private final List<Embedding> embeddingStack= new ArrayList<>();
public WikitextWeavePartitionNodeScanner(final IMarkupLanguage markupLanguage) {
this(markupLanguage, 0);
}
public WikitextWeavePartitionNodeScanner(final IMarkupLanguage markupLanguage,
final int markupLanguageMode) {
super(markupLanguage, markupLanguageMode);
}
@Override
public void execute(final ITreePartitionNodeScan scan) throws BreakException {
this.foreignScan= new WrappedPartitionScan(scan);
try {
super.execute(scan);
}
finally {
this.foreignScan= null;
}
}
@Override
protected void init() {
this.embeddingStack.clear();
super.init();
}
@Override
protected void configure(final MarkupParser2 markupParser) {
super.configure(markupParser);
markupParser.enable(MarkupParser2.INLINE_EMBEDDED);
}
protected WrappedPartitionScan getForeignScan() {
return this.foreignScan;
}
@Override
public void beginBlock(final BlockType type, final Attributes attributes) {
if (attributes instanceof EmbeddingAttributes) {
final Embedding embedding= new Embedding((EmbeddingAttributes) attributes);
this.embeddingStack.add(embedding);
beginEmbeddingBlock(type, embedding);
return;
}
super.beginBlock(type, attributes);
}
protected void beginEmbeddingBlock(final BlockType type, final Embedding embedding) {
throw new UnsupportedOperationException("blockType= " + type + ", foreignType= " + embedding.getForeignType()); //$NON-NLS-1$ //$NON-NLS-2$
}
@Override
public void endBlock() {
final int embeddingCount= this.embeddingStack.size();
if (embeddingCount > 0) {
final Embedding embedding= this.embeddingStack.remove(embeddingCount - 1);
endEmbeddingBlock(getNode().getType(), embedding);
return;
}
super.endBlock();
}
protected void endEmbeddingBlock(final ITreePartitionNodeType type,
final Embedding embedding) {
throw new IllegalStateException();
}
@Override
public void beginSpan(final SpanType type, final Attributes attributes) {
if (attributes instanceof EmbeddingAttributes) {
final Embedding embedding= new Embedding((EmbeddingAttributes) attributes);
this.embeddingStack.add(embedding);
beginEmbeddingSpan(type, embedding);
return;
}
super.beginSpan(type, attributes);
}
protected void beginEmbeddingSpan(final SpanType type, final Embedding embedding) {
throw new UnsupportedOperationException("spanType= " + type + ", foreignType= " + embedding.getForeignType()); //$NON-NLS-1$ //$NON-NLS-2$
}
@Override
public void endSpan() {
final int embeddingCount= this.embeddingStack.size();
if (embeddingCount > 0) {
final Embedding embedding= this.embeddingStack.remove(embeddingCount - 1);
endEmbeddingSpan(getNode().getType(), embedding);
return;
}
super.endSpan();
}
protected void endEmbeddingSpan(final ITreePartitionNodeType type,
final Embedding embedding) {
throw new IllegalStateException();
}
}