/*******************************************************************************
* Copyright (c) 2010, 2011 Obeo.
* 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:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.mylyn.docs.intent.markup.builder.state;
import java.util.Stack;
import org.eclipse.mylyn.docs.intent.markup.builder.BuilderState;
import org.eclipse.mylyn.docs.intent.markup.builder.operation.HasAttributeCopyAttributes;
import org.eclipse.mylyn.docs.intent.markup.builder.state.utils.CharacterEscapedAnalyser;
import org.eclipse.mylyn.docs.intent.markup.markup.Block;
import org.eclipse.mylyn.docs.intent.markup.markup.Entity;
import org.eclipse.mylyn.docs.intent.markup.markup.Formatting;
import org.eclipse.mylyn.docs.intent.markup.markup.Image;
import org.eclipse.mylyn.docs.intent.markup.markup.Link;
import org.eclipse.mylyn.docs.intent.markup.markup.ListItem;
import org.eclipse.mylyn.docs.intent.markup.markup.ListType;
import org.eclipse.mylyn.docs.intent.markup.markup.MarkupFactory;
import org.eclipse.mylyn.docs.intent.markup.markup.Text;
import org.eclipse.mylyn.wikitext.core.parser.Attributes;
import org.eclipse.mylyn.wikitext.core.parser.DocumentBuilder.BlockType;
import org.eclipse.mylyn.wikitext.core.parser.DocumentBuilder.SpanType;
import org.eclipse.mylyn.wikitext.core.parser.LinkAttributes;
/**
* class defining the behaviors of the parser if the current element is a bloc.
*
* @author <a href="mailto:alex.lagarde@obeo.fr">Alex Lagarde</a>
*/
public class SBlock extends BuilderState {
/**
* Block to manage for this SBlock.
*/
protected Block block;
/**
* Current text, used to assign multiple format to the same text.
*/
protected Text currentText;
/**
* Current Link, used to assign the link name after its creation.
*/
// private Link currentLink;
/**
* Stack representing the current styles to apply to a text.
*/
protected Stack<Formatting> spanStack;
/**
* SBlock constructor.
*
* @param previous
* previous state
* @param block
* Model element to stock.
*/
public SBlock(BuilderState previous, Block block) {
super(previous);
this.block = block;
spanStack = new Stack<Formatting>();
}
/**
* Adds all the format contained in the stack to the given text.
*
* @param text
* Text on which to apply the formats of the stack.
*/
protected void addAllFormatsFromStack(Text text) {
if (!spanStack.isEmpty()) {
for (Formatting format : spanStack) {
text.getFormat().add(format);
}
// if the Text has currently the 'none' format
if (text.getFormat().contains(Formatting.NONE)) {
// we remove this default format, because a specific format is
// required.
text.getFormat().remove(Formatting.NONE);
}
}
}
/**
* {@inheritDoc}
*
* @see org.eclipse.mylyn.docs.intent.markup.builder.BuilderState#endBlock()
*/
@Override
public BuilderState endBlock() {
return previousState();
}
/**
* {@inheritDoc}
*
* @see org.eclipse.mylyn.docs.intent.markup.builder.BuilderState#beginBlock(org.eclipse.mylyn.wikitext.core.parser.DocumentBuilder.BlockType,
* org.eclipse.mylyn.wikitext.core.parser.Attributes)
*/
@Override
public BuilderState beginBlock(BlockType type, Attributes attributes) {
BuilderState returnState = this;
switch (type) {
case QUOTE:
case CODE:
returnState = previousState().beginBlock(type, attributes);
break;
case BULLETED_LIST:
case NUMERIC_LIST:
// We create a listItem considered has a list of level 2
ListItem newItem = MarkupFactory.eINSTANCE.createListItem();
new HasAttributeCopyAttributes(newItem).setValues(attributes);
if (type == BlockType.BULLETED_LIST) {
newItem.setListType(ListType.BULLETED);
} else {
newItem.setListType(ListType.NUMERIC);
}
newItem.setIsList(true);
if (block instanceof ListItem) {
((ListItem)block).setIsList(true);
newItem.setImbricationLevel(((ListItem)block).getImbricationLevel() + 1);
((ListItem)block).getItems().add(newItem);
}
returnState = new SList(this, newItem);
break;
default:
break;
}
return returnState;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.mylyn.docs.intent.markup.builder.BuilderState#characters(java.lang.String)
*/
@Override
public BuilderState characters(String text) {
// We simply create the Text.
Text txt = MarkupFactory.eINSTANCE.createText();
txt.setData(text);
// We also add to this text the current formats in use.
addAllFormatsFromStack(txt);
currentText = txt;
block.getContent().add(txt);
return new SText(this, txt);
}
/**
* {@inheritDoc}
*
* @see org.eclipse.mylyn.docs.intent.markup.builder.BuilderState#charactersUnescaped(java.lang.String)
*/
@Override
public BuilderState charactersUnescaped(String literal) {
BuilderState returnState = null;
// If the unescaped character matches to a link declaration
if (CharacterEscapedAnalyser.isLinkDeclaration(literal)) {
Link newLink = MarkupFactory.eINSTANCE.createLink();
newLink.setHrefOrHashName(CharacterEscapedAnalyser.getLinkHref(literal));
newLink.setHasBeenDeclaredWithHTMLSyntax(true);
String linkTitle = CharacterEscapedAnalyser.getLinkTitle(literal);
// If the link has a title
if (linkTitle.length() > 0) {
// We create its attributes and initialize the Title value.
Attributes linkAttributes = new Attributes();
linkAttributes.setTitle(linkTitle);
new HasAttributeCopyAttributes(newLink).setValues(linkAttributes);
}
// We create the Name block of the new link
Block linkName = MarkupFactory.eINSTANCE.createBlock();
newLink.setName(linkName);
block.getContent().add(newLink);
returnState = new SLink(this, newLink.getName(), newLink);
}
// If the unescaped characted matches to a LineBreak declaration
if (CharacterEscapedAnalyser.isLineBreak(literal)) {
// We create an empty text with a lineBreak.
Text text = MarkupFactory.eINSTANCE.createText();
text.setData("");
text.setLineBreak(true);
block.getContent().add(text);
returnState = this;
}
// If the unescaped character matches to a tabulation declaration
if (CharacterEscapedAnalyser.isTabulation(literal)) {
Entity entity = MarkupFactory.eINSTANCE.createEntity();
entity.setData("<dd/>");
entity.setLineBreak(false);
block.getContent().add(entity);
returnState = this;
}
if (returnState != null) {
return returnState;
}
return super.charactersUnescaped(literal);
}
/**
* {@inheritDoc}
*
* @see org.eclipse.mylyn.docs.intent.markup.builder.BuilderState#lineBreak()
*/
@Override
public BuilderState lineBreak() {
// If the last content of the block is a text, we set the lineBreak.
if ((block.getContent().size() > 0)
&& (block.getContent().get(block.getContent().size() - 1) instanceof Text)) {
((Text)block.getContent().get(block.getContent().size() - 1)).setLineBreak(true);
}
return this;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.mylyn.docs.intent.markup.builder.BuilderState#entityReference(java.lang.String)
*/
@Override
public BuilderState entityReference(String entity) {
Entity newEntity = MarkupFactory.eINSTANCE.createEntity();
newEntity.setData(entity);
addAllFormatsFromStack(newEntity);
// if (currentLink != null) {
// if (currentLink.getName() == null) {
// Block bloc = MarkupFactory.eINSTANCE.createBlock();
// currentLink.setName(bloc);
// }
// currentLink.getName().getContent().add(newEntity);
// return this;
// } else {
block.getContent().add(newEntity);
return new SText(this, newEntity);
// }
}
/**
* {@inheritDoc}
*
* @see org.eclipse.mylyn.docs.intent.markup.builder.BuilderState#beginSpan(org.eclipse.mylyn.wikitext.core.parser.DocumentBuilder.SpanType,
* org.eclipse.mylyn.wikitext.core.parser.Attributes)
*/
@Override
public BuilderState beginSpan(SpanType type, Attributes attributes) {
BuilderState returnState = null;
// If the spanType is LINK
if (type == SpanType.LINK && attributes instanceof LinkAttributes) {
// we create a new Link with the given attributes
LinkAttributes linkAttributes = (LinkAttributes)attributes;
Link link = MarkupFactory.eINSTANCE.createLink();
link.setHrefOrHashName(linkAttributes.getHref());
link.setHasBeenDeclaredWithHTMLSyntax(false);
new HasAttributeCopyAttributes(link).setValues(attributes);
// We initialize the link content
Block linkName = MarkupFactory.eINSTANCE.createBlock();
link.setName(linkName);
block.getContent().add(link);
returnState = new SLink(this, linkName, link);
} else {
// We add this span in the format stack.
if (!spanStack.contains(Formatting.get(type.name().toLowerCase()))) {
spanStack.add(Formatting.get(type.name().toLowerCase()));
}
// If there is a current text with no data
if ((currentText != null) && (currentText.getData() == null)) {
// we add the format to this currentText
currentText.getFormat().add(Formatting.get(type.name().toLowerCase()));
// if the Text has currently the 'none' format
if (currentText.getFormat().contains(Formatting.NONE)) {
// we remove this default format, because a specific format
// is required.
currentText.getFormat().remove(Formatting.NONE);
}
returnState = new SText(this, currentText);
} else {
Text txt = MarkupFactory.eINSTANCE.createText();
// if the Text has currently the 'none' format
if (txt.getFormat().contains(Formatting.NONE)) {
// we remove this default format, because a specific format
// is required.
txt.getFormat().remove(Formatting.NONE);
}
txt.getFormat().add(Formatting.get(type.name().toLowerCase()));
// We also copy the formats of the stack
addAllFormatsFromStack(txt);
new HasAttributeCopyAttributes(txt).setValues(attributes);
block.getContent().add(txt);
currentText = txt;
returnState = new SText(this, txt);
}
}
return returnState;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.mylyn.docs.intent.markup.builder.BuilderState#endSpan()
*/
@Override
public BuilderState endSpan() {
// We remove the last declared span.
spanStack.pop();
return this;
};
/**
* {@inheritDoc}
*
* @see org.eclipse.mylyn.docs.intent.markup.builder.BuilderState#image(org.eclipse.mylyn.wikitext.core.parser.Attributes,
* java.lang.String)
*/
@Override
public BuilderState image(Attributes attributes, String url) {
Image img = MarkupFactory.eINSTANCE.createImage();
img.setUrl(url);
new HasAttributeCopyAttributes(img).setValues(attributes);
block.getContent().add(img);
return this;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.mylyn.docs.intent.markup.builder.BuilderState#imageLink(org.eclipse.mylyn.wikitext.core.parser.Attributes,
* org.eclipse.mylyn.wikitext.core.parser.Attributes, java.lang.String, java.lang.String)
*/
@Override
public BuilderState imageLink(Attributes attributes, Attributes imageAttributes, String href,
String imageUrl) {
Image img = MarkupFactory.eINSTANCE.createImage();
img.setUrl(imageUrl);
new HasAttributeCopyAttributes(img).setValues(attributes);
block.getContent().add(img);
return this;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.mylyn.docs.intent.markup.builder.BuilderState#link(org.eclipse.mylyn.wikitext.core.parser.Attributes,
* java.lang.String, java.lang.String)
*/
@Override
public BuilderState link(Attributes attributes, String hrefOrHashName, String text) {
Link lnk = MarkupFactory.eINSTANCE.createLink();
lnk.setHrefOrHashName(hrefOrHashName);
Text linkNameContent = MarkupFactory.eINSTANCE.createText();
linkNameContent.setData(text);
Block linkName = MarkupFactory.eINSTANCE.createBlock();
linkName.getContent().add(linkNameContent);
lnk.setName(linkName);
lnk.setHasBeenDeclaredWithHTMLSyntax(false);
new HasAttributeCopyAttributes(lnk).setValues(attributes);
block.getContent().add(lnk);
return super.link(attributes, hrefOrHashName, text);
}
/**
* {@inheritDoc}
*
* @see org.eclipse.mylyn.docs.intent.markup.builder.BuilderState#endHeading()
*/
@Override
public BuilderState endHeading() {
return previousState();
}
}