/**
*
* Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* Copyright (c) 2009-2014 Câmara dos Deputados. Todos os direitos reservados.
*
* e-Democracia é um software livre; você pode redistribuí-lo e/ou modificá-lo dentro
* dos termos da Licença Pública Geral Menor GNU como publicada pela Fundação do
* Software Livre (FSF); na versão 2.1 da Licença, ou (na sua opinião) qualquer versão.
*
* Este programa é distribuído na esperança de que possa ser útil, mas SEM NENHUMA GARANTIA;
* sem uma garantia implícita de ADEQUAÇÃO a qualquer MERCADO ou APLICAÇÃO EM PARTICULAR.
* Veja a Licença Pública Geral Menor GNU para maiores detalhes.
*
*/
package com.liferay.portal.parsers.bbcode;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.IntegerWrapper;
import com.liferay.portal.kernel.util.SetUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.Stack;
/**
* @author Iliyan Peychev
*/
public class BBCodeParser {
public static final int TYPE_DATA = 0x04;
public static final int TYPE_TAG_END = 0x02;
public static final int TYPE_TAG_START = 0x01;
public static final int TYPE_TAG_START_END = TYPE_TAG_START | TYPE_TAG_END;
public BBCodeParser() {
_blockElements = SetUtil.fromArray(
new String[] {
"*", "center", "code", "justify", "left", "li", "list", "q",
"quote", "right", "table", "td", "th", "tr"
});
_inlineElements = SetUtil.fromArray(
new String[] {
"b", "color", "font", "i", "img", "s", "size", "u", "url", "youtube"
});
_selfCloseElements = SetUtil.fromArray(new String[] {"*"});
}
public List<BBCodeItem> parse(String text) {
List<BBCodeItem> bbCodeItems = new ArrayList<BBCodeItem>();
BBCodeLexer bbCodeLexer = new BBCodeLexer(text);
Stack<String> tags = new Stack<String>();
IntegerWrapper marker = new IntegerWrapper();
BBCodeToken bbCodeToken = null;
while ((bbCodeToken = bbCodeLexer.getNextBBCodeToken()) != null) {
handleData(bbCodeItems, bbCodeLexer, marker, bbCodeToken, text);
if (bbCodeToken.getStartTag() == null) {
handleTagEnd(bbCodeItems, tags, bbCodeToken);
continue;
}
handleTagStart(bbCodeItems, tags, bbCodeToken);
String startTag = bbCodeToken.getStartTag();
if (!startTag.equals("code")) {
continue;
}
while (true) {
bbCodeToken = bbCodeLexer.getNextBBCodeToken();
if (bbCodeToken == null) {
break;
}
String endTag = GetterUtil.getString(bbCodeToken.getEndTag());
if (endTag.equals("code")) {
break;
}
}
handleData(bbCodeItems, bbCodeLexer, marker, bbCodeToken, text);
if (bbCodeToken != null) {
handleTagEnd(bbCodeItems, tags, bbCodeToken);
}
else {
break;
}
}
handleData(bbCodeItems, bbCodeLexer, marker, null, text);
handleTagEnd(bbCodeItems, tags, null);
return bbCodeItems;
}
protected void handleData(
List<BBCodeItem> bbCodeItems, BBCodeLexer bbCodeLexer,
IntegerWrapper marker, BBCodeToken bbCodeToken, String data) {
int length = data.length();
int lastIndex = length;
if (bbCodeToken != null) {
length = bbCodeToken.getStart();
lastIndex = bbCodeLexer.getLastIndex();
}
if (length > marker.getValue()) {
BBCodeItem bbCodeItem = new BBCodeItem(
TYPE_DATA, null, data.substring(marker.getValue(), length));
bbCodeItems.add(bbCodeItem);
}
marker.setValue(lastIndex);
}
protected void handleTagEnd(
List<BBCodeItem> bbCodeItems, Stack<String> tags,
BBCodeToken bbCodeToken) {
int size = 0;
if (bbCodeToken != null) {
String endTag = bbCodeToken.getEndTag();
for (size = tags.size() - 1; size >= 0; size--) {
if (endTag.equals(tags.elementAt(size))) {
break;
}
}
}
if (size >= 0) {
for (int i = tags.size() - 1; i >= size; i--) {
BBCodeItem bbCodeItem = new BBCodeItem(
TYPE_TAG_END, null, tags.elementAt(i));
bbCodeItems.add(bbCodeItem);
}
tags.setSize(size);
}
}
protected void handleTagStart(
List<BBCodeItem> bbCodeItems, Stack<String> tags,
BBCodeToken bbCodeToken) {
String startTag = bbCodeToken.getStartTag();
if (_blockElements.contains(startTag)) {
String currentTag = null;
while (!tags.isEmpty() &&
((currentTag = tags.lastElement()) != null) &&
_inlineElements.contains(currentTag)) {
BBCodeToken currentTagBBCodeToken = new BBCodeToken(currentTag);
handleTagEnd(bbCodeItems, tags, currentTagBBCodeToken);
}
}
if (_selfCloseElements.contains(startTag) &&
!tags.isEmpty() && startTag.equals(tags.lastElement())) {
BBCodeToken tagBBCodeToken = new BBCodeToken(startTag);
handleTagEnd(bbCodeItems, tags, tagBBCodeToken);
}
tags.push(startTag);
BBCodeItem bbCodeItem = new BBCodeItem(
TYPE_TAG_START, bbCodeToken.getAttribute(), startTag);
bbCodeItems.add(bbCodeItem);
}
private Set<String> _blockElements;
private Set<String> _inlineElements;
private Set<String> _selfCloseElements;
}